8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 01:23:03 +01:00
firebird-mirror/src/jrd/dyn_del.epp
robocop 0285f6bf76 - Implement the proposed COMMENT keyword to allow descriptions in database objects. Subject to change or withdrawal.
- Enhance some messages. Reuse some msg numbers that were duplicate.
- Fix some issues found in Alex recent MetaName-related commits.
2005-05-17 07:17:25 +00:00

2128 lines
56 KiB
Plaintext

/*
* PROGRAM: JRD Data Definition Utility
* MODULE: dyn_delete.epp
* DESCRIPTION: Dynamic data definition - DYN_delete_<x>
*
* 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): ______________________________________.
*
* 24-May-2001 Claudio Valderrama - Forbid zero length identifiers,
* they are not ANSI SQL compliant.
* 23-May-2001 Claudio Valderrama - Move here DYN_delete_role.
* 20-Jun-2001 Claudio Valderrama - Make available DYN_delete_generator.
*/
#include "firebird.h"
#include <stdio.h>
#include <string.h>
#include "../jrd/common.h"
#include <stdarg.h>
#include "../jrd/jrd.h"
#include "../jrd/ods.h"
#include "../jrd/tra.h"
#include "../jrd/scl.h"
#include "../jrd/drq.h"
#include "../jrd/flags.h"
#include "../jrd/ibase.h"
#include "../jrd/lls.h"
#include "../jrd/all.h"
#include "../jrd/met.h"
#include "../jrd/btr.h"
#include "../jrd/intl.h"
#include "../jrd/dyn.h"
#include "../jrd/all_proto.h"
#include "../jrd/blb_proto.h"
#include "../jrd/cmp_proto.h"
#include "../jrd/dyn_proto.h"
#include "../jrd/dyn_proto.h"
#include "../jrd/dyn_dl_proto.h"
#include "../jrd/err_proto.h"
#include "../jrd/exe_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/inf_proto.h"
#include "../jrd/intl_proto.h"
#include "../jrd/isc_f_proto.h"
#include "../jrd/met_proto.h"
#include "../jrd/thd.h"
#include "../jrd/vio_proto.h"
#include "../common/utils_proto.h"
using namespace Jrd;
DATABASE DB = STATIC "ODS.RDB";
static bool delete_constraint_records(Global*, const Firebird::MetaName&, const Firebird::MetaName&);
static bool delete_dimension_records(Global*, const Firebird::MetaName&);
static void delete_f_key_constraint(thread_db*, Global*,
const Firebird::MetaName&, const Firebird::MetaName&,
const Firebird::MetaName&, const Firebird::MetaName&);
static void delete_gfield_for_lfield(Global*, const Firebird::MetaName&);
static bool delete_index_segment_records(Global*, const Firebird::MetaName&);
static bool delete_security_class2(Global*, const Firebird::MetaName&);
void DYN_delete_constraint (Global* gbl, const UCHAR** ptr, const Firebird::MetaName* relation)
{
/**************************************
*
* D Y N _ d e l e t e _ c o n s t r a i n t
*
**************************************
*
* Functional description
* Execute ddl to DROP an Integrity Constraint
*
**************************************/
Firebird::MetaName rel_name, constraint;
/* GET name of the constraint to be deleted */
GET_STRING(ptr, constraint);
if (relation)
rel_name = *relation;
else if (*(*ptr)++ != isc_dyn_rel_name) {
DYN_error_punt(false, 128, NULL, NULL, NULL, NULL, NULL);
/* msg 128: "No relation specified in delete_constraint" */
}
else
GET_STRING(ptr, rel_name);
if (!delete_constraint_records(gbl, constraint, rel_name))
DYN_error_punt(false, 130, constraint.c_str(), NULL, NULL, NULL, NULL);
/* msg 130: "CONSTRAINT %s does not exist." */
}
void DYN_delete_dimensions(Global* gbl,
const UCHAR** ptr,
const Firebird::MetaName* relation_name,
Firebird::MetaName* field_name)
{
/**************************************
*
* D Y N _ d e l e t e _ d i m e n s i o n s
*
**************************************
*
* Functional description
* Delete dimensions associated with
* a global field. Used when modifying
* the datatype and from places where a
* field is deleted directly in the system
* relations. The DYN version of delete
* global field deletes the dimensions for
* you.
*
**************************************/
Firebird::MetaName f;
GET_STRING(ptr, f);
delete_dimension_records(gbl, f);
while (*(*ptr)++ != isc_dyn_end) {
--(*ptr);
DYN_execute(gbl, ptr, NULL, &f, NULL, NULL, NULL);
}
}
void DYN_delete_exception( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ e x c e p t i o n
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes an exception.
*
**************************************/
Firebird::MetaName t;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
GET_STRING(ptr, t);
jrd_req* request = CMP_find_request(tdbb, drq_e_xcp, DYN_REQUESTS);
bool found = false;
try {
found = false;;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$EXCEPTIONS
WITH X.RDB$EXCEPTION_NAME EQ t.c_str()
if (!DYN_REQUEST(drq_e_xcp))
DYN_REQUEST(drq_e_xcp) = request;
found = true;
ERASE X;
END_FOR;
if (!DYN_REQUEST(drq_e_xcp))
DYN_REQUEST(drq_e_xcp) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 143, NULL, NULL, NULL, NULL, NULL);
/* msg 143: "ERASE EXCEPTION failed" */
}
if (!found) {
DYN_error_punt(false, 144, NULL, NULL, NULL, NULL, NULL);
/* msg 144: "Exception not found" */
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
}
void DYN_delete_filter( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ f i l t e r
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a blob filter.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_filters, DYN_REQUESTS);
bool found = false;
Firebird::MetaName f;
GET_STRING(ptr, f);
try {
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FILTERS WITH X.RDB$FUNCTION_NAME = f.c_str()
if (!DYN_REQUEST(drq_e_filters))
DYN_REQUEST(drq_e_filters) = request;
ERASE X;
found = true;
END_FOR;
if (!DYN_REQUEST(drq_e_filters))
DYN_REQUEST(drq_e_filters) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 36, NULL, NULL, NULL, NULL, NULL);
/* msg 36: "ERASE BLOB FILTER failed" */
}
if (!found) {
DYN_error_punt(false, 37, f.c_str(), NULL, NULL, NULL, NULL);
/* msg 37: "Blob Filter %s not found" */
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
}
void DYN_delete_function( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ f u n c t i o n
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a user defined function.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_func_args, DYN_REQUESTS);
USHORT id = drq_e_func_args;
bool found = false;
Firebird::MetaName f;
GET_STRING(ptr, f);
try {
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FA IN RDB$FUNCTION_ARGUMENTS WITH FA.RDB$FUNCTION_NAME EQ f.c_str()
if (!DYN_REQUEST(drq_e_func_args))
DYN_REQUEST(drq_e_func_args) = request;
ERASE FA;
END_FOR;
if (!DYN_REQUEST(drq_e_func_args))
DYN_REQUEST(drq_e_func_args) = request;
request = CMP_find_request(tdbb, drq_e_funcs, DYN_REQUESTS);
id = drq_e_funcs;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FUNCTIONS WITH X.RDB$FUNCTION_NAME EQ f.c_str()
if (!DYN_REQUEST(drq_e_funcs))
DYN_REQUEST(drq_e_funcs) = request;
ERASE X;
found = true;
END_FOR;
if (!DYN_REQUEST(drq_e_funcs))
DYN_REQUEST(drq_e_funcs) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
if (id == drq_e_func_args)
{
DYN_error_punt(true, 39, NULL, NULL, NULL, NULL, NULL);
/* msg 39: "ERASE RDB$FUNCTION_ARGUMENTS failed" */
}
else
{
DYN_error_punt(true, 40, NULL, NULL, NULL, NULL, NULL);
/* msg 40: "ERASE RDB$FUNCTIONS failed" */
}
}
if (!found)
{
DYN_error_punt(false, 41, f.c_str(), NULL, NULL, NULL, NULL);
/* msg 41: "Function %s not found" */
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
}
void DYN_delete_generator(Global* gbl, const UCHAR**ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ g e n e r a t o r
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a generator from rdb$generator but the
* space allocated in the page won't be released.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = NULL;
bool found = false;
Firebird::MetaName t;
GET_STRING(ptr, t);
try {
request = CMP_find_request(tdbb, drq_e_gens, DYN_REQUESTS);
found = false;
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$GENERATORS
WITH X.RDB$GENERATOR_NAME EQ t.c_str()
if (!DYN_REQUEST(drq_e_gens))
DYN_REQUEST(drq_e_gens) = request;
found = true;
ERASE X;
END_FOR;
if (!DYN_REQUEST(drq_e_gens))
DYN_REQUEST(drq_e_gens) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 213, NULL, NULL, NULL, NULL, NULL);
/* msg 213: "ERASE GENERATOR failed" */
}
if (!found) {
DYN_error_punt(false, 214, t.c_str(), NULL, NULL, NULL, NULL);
/* msg 214: "Generator %s not found" */
}
}
void DYN_delete_global_field( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a global field.
*
**************************************/
Firebird::MetaName f;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_l_fld_src, DYN_REQUESTS);
USHORT id = drq_l_fld_src;
bool found = false;
try {
GET_STRING(ptr, f);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
Y IN RDB$RELATION_FIELDS WITH Y.RDB$FIELD_SOURCE EQ f.c_str()
if (!DYN_REQUEST(drq_l_fld_src))
DYN_REQUEST(drq_l_fld_src) = request;
fb_utils::exact_name_limit(Y.RDB$FIELD_SOURCE, sizeof(Y.RDB$FIELD_SOURCE));
fb_utils::exact_name_limit(Y.RDB$RELATION_NAME, sizeof(Y.RDB$RELATION_NAME));
fb_utils::exact_name_limit(Y.RDB$FIELD_NAME, sizeof(Y.RDB$FIELD_NAME));
DYN_rundown_request(request, -1);
DYN_error_punt(false, 43, Y.RDB$FIELD_SOURCE, Y.RDB$RELATION_NAME,
Y.RDB$FIELD_NAME, NULL, NULL);
/* msg 43: "field %s is used in relation %s (local name %s) and can not be dropped" */
END_FOR;
if (!DYN_REQUEST(drq_l_fld_src))
DYN_REQUEST(drq_l_fld_src) = request;
request = CMP_find_request(tdbb, drq_e_gfields, DYN_REQUESTS);
id = drq_e_gfields;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FIELDS WITH X.RDB$FIELD_NAME EQ f.c_str()
if (!DYN_REQUEST(drq_e_gfields))
DYN_REQUEST(drq_e_gfields) = request;
delete_dimension_records(gbl, f);
ERASE X;
found = true;
END_FOR
if (!DYN_REQUEST(drq_e_gfields))
DYN_REQUEST(drq_e_gfields) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
if (id == drq_l_fld_src)
{
DYN_error_punt(true, 44, NULL, NULL, NULL, NULL, NULL);
/* msg 44: "ERASE RDB$FIELDS failed" */
}
else
{
DYN_error_punt(true, 45, NULL, NULL, NULL, NULL, NULL);
/* msg 45: "ERASE RDB$FIELDS failed" */
}
}
if (!found) {
DYN_error_punt(false, 46, NULL, NULL, NULL, NULL, NULL);
/* msg 46: "Field not found" */
}
while (*(*ptr)++ != isc_dyn_end) {
--(*ptr);
DYN_execute(gbl, ptr, NULL, &f, NULL, NULL, NULL);
}
}
void DYN_delete_index( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ i n d e x
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes an index.
*
**************************************/
Firebird::MetaName idx_name, rel_name;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_indices, DYN_REQUESTS);
bool found = false;
bool is_expression = false;
try {
GET_STRING(ptr, idx_name);
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
IDX IN RDB$INDICES WITH IDX.RDB$INDEX_NAME EQ idx_name.c_str()
if (!DYN_REQUEST(drq_e_indices))
DYN_REQUEST(drq_e_indices) = request;
rel_name = IDX.RDB$RELATION_NAME;
found = true;
is_expression = !IDX.RDB$EXPRESSION_BLR.NULL;
ERASE IDX;
END_FOR;
if (!DYN_REQUEST(drq_e_indices))
DYN_REQUEST(drq_e_indices) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 47, NULL, NULL, NULL, NULL, NULL);
/* msg 47: "ERASE RDB$INDICES failed" */
}
if (!found)
{
DYN_error_punt(false, 48, NULL, NULL, NULL, NULL, NULL);
/* msg 48: "Index not found" */
}
#ifdef EXPRESSION_INDICES
if (!is_expression)
#endif
if (!delete_index_segment_records(gbl, idx_name))
{
DYN_error_punt(false, 50, NULL, NULL, NULL, NULL, NULL);
/* msg 50: "No segments found for index" */
}
while (*(*ptr)++ != isc_dyn_end) {
--(*ptr);
DYN_execute(gbl, ptr, &rel_name, NULL, NULL, NULL, NULL);
}
}
void DYN_delete_local_field(Global* gbl,
const UCHAR** ptr,
const Firebird::MetaName* relation_name,
Firebird::MetaName* field_name)
{
/**************************************
*
* D Y N _ d e l e t e _ l o c a l _ f i e l d
*
**************************************
*
* Functional description
* Execute a dynamic ddl 'delete local field'
* statement.
*
* The rules for dropping a regular column:
*
* 1. the column is not referenced in any views.
* 2. the column is not part of any user defined indexes.
* 3. the column is not used in any SQL statements inside of store
* procedures or triggers
* 4. the column is not part of any check-constraints
*
* The rules for dropping a column that was created as primary key:
*
* 1. the column is not defined as any foreign keys
* 2. the column is not defined as part of compound primary keys
*
* The rules for dropping a column that was created as foreign key:
*
* 1. the column is not defined as a compound foreign key. A
* compound foreign key is a foreign key consisted of more
* than one columns.
*
* The RI enforcement for dropping primary key column is done by system
* triggers and the RI enforcement for dropping foreign key column is
* done by code and system triggers. See the functional description of
* delete_f_key_constraint function for detail.
*
**************************************/
Firebird::MetaName tbl_nm, col_nm, constraint, index_name;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
GET_STRING(ptr, col_nm);
if (relation_name)
tbl_nm = *relation_name;
else if (*(*ptr)++ != isc_dyn_rel_name) {
DYN_error_punt(false, 51, NULL, NULL, NULL, NULL, NULL);
/* msg 51: "No relation specified in ERASE RFR" */
}
else
GET_STRING(ptr, tbl_nm);
jrd_req* request = CMP_find_request(tdbb, drq_l_dep_flds, DYN_REQUESTS);
USHORT id = drq_l_dep_flds;
bool found;
try {
/*
** ================================================================
** ==
** == make sure that column is not referenced in any views
** ==
** ================================================================
*/
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$RELATION_FIELDS CROSS Y IN RDB$RELATION_FIELDS CROSS
Z IN RDB$VIEW_RELATIONS WITH
X.RDB$RELATION_NAME EQ tbl_nm.c_str() AND
X.RDB$FIELD_NAME EQ col_nm.c_str() AND
X.RDB$FIELD_NAME EQ Y.RDB$BASE_FIELD AND
X.RDB$FIELD_SOURCE EQ Y.RDB$FIELD_SOURCE AND
Y.RDB$RELATION_NAME EQ Z.RDB$VIEW_NAME AND
X.RDB$RELATION_NAME EQ Z.RDB$RELATION_NAME AND
Y.RDB$VIEW_CONTEXT EQ Z.RDB$VIEW_CONTEXT
if (!DYN_REQUEST(drq_l_dep_flds))
DYN_REQUEST(drq_l_dep_flds) = request;
DYN_rundown_request(request, -1);
DYN_error_punt(false, 52, col_nm.c_str(), tbl_nm.c_str(), Y.RDB$RELATION_NAME, NULL,
NULL);
/* msg 52: "field %s from relation %s is referenced in view %s" */
END_FOR;
if (!DYN_REQUEST(drq_l_dep_flds))
DYN_REQUEST(drq_l_dep_flds) = request;
/*
** ===============================================================
** ==
** == If the column to be dropped is being used as a foreign key
** == and the coulmn was not part of any compound foreign key,
** == then we can drop the column. But we have to drop the foreign key
** == constraint first.
** ==
** ===============================================================
*/
request = CMP_find_request(tdbb, drq_g_rel_constr_nm, DYN_REQUESTS);
id = drq_g_rel_constr_nm;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
IDX IN RDB$INDICES CROSS
IDX_SEG IN RDB$INDEX_SEGMENTS CROSS
REL_CONST IN RDB$RELATION_CONSTRAINTS
WITH IDX.RDB$RELATION_NAME EQ tbl_nm.c_str()
AND REL_CONST.RDB$RELATION_NAME EQ tbl_nm.c_str()
AND IDX_SEG.RDB$FIELD_NAME EQ col_nm.c_str()
AND IDX.RDB$INDEX_NAME EQ IDX_SEG.RDB$INDEX_NAME
AND IDX.RDB$INDEX_NAME EQ REL_CONST.RDB$INDEX_NAME
AND REL_CONST.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY
if (!DYN_REQUEST(drq_g_rel_constr_nm))
DYN_REQUEST(drq_g_rel_constr_nm) = request;
if (IDX.RDB$SEGMENT_COUNT == 1) {
constraint = REL_CONST.RDB$CONSTRAINT_NAME;
index_name = IDX.RDB$INDEX_NAME;
delete_f_key_constraint(tdbb, gbl, tbl_nm, col_nm,
constraint, index_name);
}
else {
DYN_rundown_request(request, -1);
DYN_error_punt(false, 187, col_nm.c_str(), tbl_nm.c_str(),
IDX.RDB$INDEX_NAME, NULL, NULL);
/* msg 187: "field %s from relation %s is referenced in index %s" */
}
END_FOR;
if (!DYN_REQUEST(drq_g_rel_constr_nm))
DYN_REQUEST(drq_g_rel_constr_nm) = request;
/*
** ================================================================
** ==
** == make sure that column is not referenced in any indexes
** ==
** == NOTE: You still could see the system generated indices even though
** == they were already been deleted when dropping column that was
** == used as foreign key before "commit".
** ==
** ================================================================
*/
request = CMP_find_request(tdbb, drq_e_l_idx, DYN_REQUESTS);
id = drq_e_l_idx;
jrd_req* old_request = NULL;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
IDX IN RDB$INDICES
WITH IDX.RDB$RELATION_NAME EQ tbl_nm.c_str()
if (!DYN_REQUEST(drq_e_l_idx))
DYN_REQUEST(drq_e_l_idx) = request;
found = false;
if (strncmp(IMPLICIT_DOMAIN_PREFIX, IDX.RDB$INDEX_NAME,
IMPLICIT_DOMAIN_PREFIX_LEN) != 0)
{
old_request = request;
id = drq_l_idx_seg;
request = CMP_find_request(tdbb, drq_l_idx_seg, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIRST 1 IDX_SEG IN RDB$INDEX_SEGMENTS
WITH IDX_SEG.RDB$INDEX_NAME EQ IDX.RDB$INDEX_NAME AND
IDX_SEG.RDB$FIELD_NAME = col_nm.c_str()
if (!DYN_REQUEST(drq_l_idx_seg))
DYN_REQUEST(drq_l_idx_seg) = request;
found = true;
END_FOR;
if (!DYN_REQUEST(drq_l_idx_seg))
DYN_REQUEST(drq_l_idx_seg) = request;
request = old_request;
id = drq_e_l_idx;
}
if (found) {
DYN_rundown_request(request, -1);
DYN_error_punt(false, 187, col_nm.c_str(), tbl_nm.c_str(), IDX.RDB$INDEX_NAME,
NULL, NULL);
/* msg 187: "field %s from relation %s is referenced in index %s" */
}
END_FOR;
if (!DYN_REQUEST(drq_e_l_idx))
DYN_REQUEST(drq_e_l_idx) = request;
request = CMP_find_request(tdbb, drq_e_lfield, DYN_REQUESTS);
id = drq_e_lfield;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
RFR IN RDB$RELATION_FIELDS
WITH RFR.RDB$FIELD_NAME EQ col_nm.c_str()
AND RFR.RDB$RELATION_NAME EQ tbl_nm.c_str()
if (!DYN_REQUEST(drq_e_lfield))
DYN_REQUEST(drq_e_lfield) = request;
ERASE RFR;
if (!RFR.RDB$SECURITY_CLASS.NULL
&& !strncmp(RFR.RDB$SECURITY_CLASS, SQL_SECCLASS_PREFIX, SQL_SECCLASS_PREFIX_LEN))
{
delete_security_class2(gbl, RFR.RDB$SECURITY_CLASS);
}
found = true;
delete_gfield_for_lfield(gbl, RFR.RDB$FIELD_SOURCE);
while (*(*ptr)++ != isc_dyn_end) {
--(*ptr);
Firebird::MetaName rel_name(RFR.RDB$RELATION_NAME);
MetaTmp(RFR.RDB$FIELD_SOURCE)
DYN_execute(gbl, ptr, &rel_name, &tmp, NULL, NULL, NULL);
}
END_FOR;
if (!DYN_REQUEST(drq_e_lfield)) {
DYN_REQUEST(drq_e_lfield) = request;
}
request = CMP_find_request(tdbb, drq_e_fld_prvs, DYN_REQUESTS);
id = drq_e_fld_prvs;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH
PRIV.RDB$RELATION_NAME EQ tbl_nm.c_str() AND
PRIV.RDB$FIELD_NAME EQ col_nm.c_str() AND
PRIV.RDB$OBJECT_TYPE = obj_relation
if (!DYN_REQUEST(drq_e_fld_prvs))
DYN_REQUEST(drq_e_fld_prvs) = request;
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_e_fld_prvs)) {
DYN_REQUEST(drq_e_fld_prvs) = request;
}
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
switch (id) {
case drq_l_dep_flds:
DYN_error_punt(true, 53, NULL, NULL, NULL, NULL, NULL);
// msg 53: "ERASE RDB$RELATION_FIELDS failed"
case drq_e_fld_prvs:
DYN_error_punt(true, 62, NULL, NULL, NULL, NULL, NULL);
// msg 62: "ERASE RDB$USER_PRIVILEGES failed"
default:
DYN_error_punt(true, 53, NULL, NULL, NULL, NULL, NULL);
// msg 53: "ERASE RDB$RELATION_FIELDS failed"
}
}
if (!found) {
DYN_error_punt(false, 55, NULL, NULL, NULL, NULL, NULL);
/* msg 55: "Field not found for relation" */
}
}
void DYN_delete_parameter(Global* gbl,
const UCHAR** ptr,
Firebird::MetaName* proc_name)
{
/**************************************
*
* D Y N _ d e l e t e _ p a r a m e t e r
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a stored procedure parameter.
*
**************************************/
Firebird::MetaName name;
GET_STRING(ptr, name);
if (**ptr == isc_dyn_prc_name) {
GET_STRING(ptr, *proc_name);
}
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_prm, DYN_REQUESTS);
USHORT id = drq_e_prms;
bool found = false;
try {
jrd_req* old_request = NULL;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PP IN RDB$PROCEDURE_PARAMETERS WITH PP.RDB$PROCEDURE_NAME EQ proc_name->c_str()
AND PP.RDB$PARAMETER_NAME EQ name.c_str()
if (!DYN_REQUEST(drq_e_prm))
DYN_REQUEST(drq_e_prm) = request;
found = true;
/* get rid of parameters in rdb$fields */
if (!PP.RDB$FIELD_SOURCE.NULL) {
old_request = request;
const USHORT old_id = id;
request = CMP_find_request(tdbb, drq_d_gfields, DYN_REQUESTS);
id = drq_d_gfields;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS
WITH FLD.RDB$FIELD_NAME EQ PP.RDB$FIELD_SOURCE
if (!DYN_REQUEST(drq_d_gfields))
DYN_REQUEST(drq_d_gfields) = request;
ERASE FLD;
END_FOR;
if (!DYN_REQUEST(drq_d_gfields))
DYN_REQUEST(drq_d_gfields) = request;
request = old_request;
id = old_id;
}
ERASE PP;
END_FOR;
if (!DYN_REQUEST(drq_e_prm)) {
DYN_REQUEST(drq_e_prm) = request;
}
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
if (id == drq_e_prms) {
DYN_error_punt(true, 138, NULL, NULL, NULL, NULL, NULL);
/* msg 138: "ERASE RDB$PROCEDURE_PARAMETERS failed" */
}
else {
DYN_error_punt(true, 35, NULL, NULL, NULL, NULL, NULL);
/* msg 35: "ERASE RDB$FIELDS failed" */
}
}
if (!found) {
DYN_error_punt(false, 146, name.c_str(), proc_name->c_str(), NULL, NULL, NULL);
/* msg 146: "Parameter %s in procedure %s not found" */
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
}
void DYN_delete_procedure( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ p r o c e d u r e
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a stored procedure.
*
**************************************/
Firebird::MetaName name;
GET_STRING(ptr, name);
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
tdbb->tdbb_flags |= TDBB_prc_being_dropped;
if (MET_lookup_procedure(tdbb, name, true) == 0)
{
tdbb->tdbb_flags &= ~TDBB_prc_being_dropped;
DYN_error_punt(false, 140, name.c_str(), NULL, NULL, NULL, NULL);
/* msg 140: "Procedure %s not found" */
}
tdbb->tdbb_flags &= ~TDBB_prc_being_dropped;
jrd_req* request = CMP_find_request(tdbb, drq_e_prms, DYN_REQUESTS);
USHORT id = drq_e_prms;
try {
jrd_req* old_request = NULL;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PP IN RDB$PROCEDURE_PARAMETERS WITH PP.RDB$PROCEDURE_NAME EQ name.c_str()
if (!DYN_REQUEST(drq_e_prms))
DYN_REQUEST(drq_e_prms) = request;
/* get rid of parameters in rdb$fields */
if (!PP.RDB$FIELD_SOURCE.NULL) {
old_request = request;
const USHORT old_id = id;
request = CMP_find_request(tdbb, drq_d_gfields, DYN_REQUESTS);
id = drq_d_gfields;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS
WITH FLD.RDB$FIELD_NAME EQ PP.RDB$FIELD_SOURCE
if (!DYN_REQUEST(drq_d_gfields))
DYN_REQUEST(drq_d_gfields) = request;
ERASE FLD;
END_FOR;
if (!DYN_REQUEST(drq_d_gfields))
DYN_REQUEST(drq_d_gfields) = request;
request = old_request;
id = old_id;
}
ERASE PP;
END_FOR;
if (!DYN_REQUEST(drq_e_prms)) {
DYN_REQUEST(drq_e_prms) = request;
}
request = CMP_find_request(tdbb, drq_e_prcs, DYN_REQUESTS);
id = drq_e_prcs;
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
P IN RDB$PROCEDURES WITH P.RDB$PROCEDURE_NAME EQ name.c_str()
if (!DYN_REQUEST(drq_e_prcs)) {
DYN_REQUEST(drq_e_prcs) = request;
}
ERASE P;
if (!P.RDB$SECURITY_CLASS.NULL) {
delete_security_class2(gbl, P.RDB$SECURITY_CLASS);
}
found = true;
END_FOR;
if (!DYN_REQUEST(drq_e_prcs)) {
DYN_REQUEST(drq_e_prcs) = request;
}
if (!found) {
goto dyn_punt_140;
}
request = CMP_find_request(tdbb, drq_e_prc_prvs, DYN_REQUESTS);
id = drq_e_prc_prvs;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$RELATION_NAME EQ name.c_str()
AND PRIV.RDB$OBJECT_TYPE = obj_procedure
if (!DYN_REQUEST(drq_e_prc_prvs))
DYN_REQUEST(drq_e_prc_prvs) = request;
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_e_prc_prvs))
DYN_REQUEST(drq_e_prc_prvs) = request;
request = CMP_find_request(tdbb, drq_e_prc_prv, DYN_REQUESTS);
id = drq_e_prc_prv;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$USER EQ name.c_str()
AND PRIV.RDB$USER_TYPE = obj_procedure
if (!DYN_REQUEST(drq_e_prc_prv))
DYN_REQUEST(drq_e_prc_prv) = request;
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_e_prc_prv))
DYN_REQUEST(drq_e_prc_prv) = request;
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
switch (id)
{
case drq_e_prms:
DYN_error_punt(true, 138, NULL, NULL, NULL, NULL, NULL);
/* msg 138: "ERASE RDB$PROCEDURE_PARAMETERS failed" */
break;
case drq_e_prcs:
DYN_error_punt(true, 139, NULL, NULL, NULL, NULL, NULL);
/* msg 139: "ERASE RDB$PROCEDURES failed" */
break;
case drq_d_gfields:
DYN_error_punt(true, 35, NULL, NULL, NULL, NULL, NULL);
/* msg 35: "ERASE RDB$FIELDS failed" */
break;
default:
DYN_error_punt(true, 62, NULL, NULL, NULL, NULL, NULL);
/* msg 62: "ERASE RDB$USER_PRIVILEGES failed" */
break;
}
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
return;
dyn_punt_140:
DYN_error_punt(false, 140, name.c_str(), NULL, NULL, NULL, NULL);
/* msg 140: "Procedure %s not found" */
}
void DYN_delete_relation( Global* gbl, const UCHAR** ptr, const Firebird::MetaName* relation)
{
/**************************************
*
* D Y N _ d e l e t e _ r e l a t i o n
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a relation with all its indices, triggers
* and fields.
*
**************************************/
Firebird::MetaName relation_name;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
if (relation)
relation_name = *relation;
else
GET_STRING(ptr, relation_name);
jrd_req* req2 = 0;
jrd_req* request = CMP_find_request(tdbb, drq_e_rel_con2, DYN_REQUESTS);
USHORT id = drq_e_rel_con2;
try {
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
CRT IN RDB$RELATION_CONSTRAINTS
WITH CRT.RDB$RELATION_NAME EQ relation_name.c_str() AND
(CRT.RDB$CONSTRAINT_TYPE EQ PRIMARY_KEY OR
CRT.RDB$CONSTRAINT_TYPE EQ UNIQUE_CNSTRT OR
CRT.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY)
SORTED BY ASCENDING CRT.RDB$CONSTRAINT_TYPE
if (!DYN_REQUEST(drq_e_rel_con2))
DYN_REQUEST(drq_e_rel_con2) = request;
ERASE CRT;
END_FOR;
if (!DYN_REQUEST(drq_e_rel_con2))
DYN_REQUEST(drq_e_rel_con2) = request;
request = CMP_find_request(tdbb, drq_e_rel_idxs, DYN_REQUESTS);
id = drq_e_rel_idxs;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
IDX IN RDB$INDICES WITH IDX.RDB$RELATION_NAME EQ relation_name.c_str()
if (!DYN_REQUEST(drq_e_rel_idxs))
DYN_REQUEST(drq_e_rel_idxs) = request;
delete_index_segment_records(gbl, IDX.RDB$INDEX_NAME);
ERASE IDX;
END_FOR;
if (!DYN_REQUEST(drq_e_rel_idxs))
DYN_REQUEST(drq_e_rel_idxs) = request;
request = CMP_find_request(tdbb, drq_e_trg_msgs2, DYN_REQUESTS);
id = drq_e_trg_msgs2;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
TM IN RDB$TRIGGER_MESSAGES CROSS
T IN RDB$TRIGGERS WITH T.RDB$RELATION_NAME EQ relation_name.c_str() AND
TM.RDB$TRIGGER_NAME EQ T.RDB$TRIGGER_NAME
if (!DYN_REQUEST(drq_e_trg_msgs2))
DYN_REQUEST(drq_e_trg_msgs2) = request;
ERASE TM;
END_FOR;
if (!DYN_REQUEST(drq_e_trg_msgs2))
DYN_REQUEST(drq_e_trg_msgs2) = request;
// CVC: Moved this block here to avoid SF Bug #1111570.
request = CMP_find_request(tdbb, drq_e_rel_con3, DYN_REQUESTS);
id = drq_e_rel_con3;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
CRT IN RDB$RELATION_CONSTRAINTS WITH
CRT.RDB$RELATION_NAME EQ relation_name.c_str() AND
(CRT.RDB$CONSTRAINT_TYPE EQ CHECK_CNSTRT OR
CRT.RDB$CONSTRAINT_TYPE EQ NOT_NULL_CNSTRT)
if (!DYN_REQUEST(drq_e_rel_con3))
DYN_REQUEST(drq_e_rel_con3) = request;
ERASE CRT;
END_FOR;
if (!DYN_REQUEST(drq_e_rel_con3))
DYN_REQUEST(drq_e_rel_con3) = request;
request = CMP_find_request(tdbb, drq_e_rel_flds, DYN_REQUESTS);
id = drq_e_rel_flds;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
RFR IN RDB$RELATION_FIELDS WITH RFR.RDB$RELATION_NAME EQ relation_name.c_str()
if (!DYN_REQUEST(drq_e_rel_flds))
DYN_REQUEST(drq_e_rel_flds) = request;
ERASE RFR;
if (!RFR.RDB$SECURITY_CLASS.NULL
&& !strncmp(RFR.RDB$SECURITY_CLASS, SQL_SECCLASS_PREFIX, SQL_SECCLASS_PREFIX_LEN))
{
delete_security_class2(gbl, RFR.RDB$SECURITY_CLASS);
}
delete_gfield_for_lfield(gbl, RFR.RDB$FIELD_SOURCE);
END_FOR;
if (!DYN_REQUEST(drq_e_rel_flds))
DYN_REQUEST(drq_e_rel_flds) = request;
request = CMP_find_request(tdbb, drq_e_view_rels, DYN_REQUESTS);
id = drq_e_view_rels;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
VR IN RDB$VIEW_RELATIONS WITH VR.RDB$VIEW_NAME EQ relation_name.c_str()
if (!DYN_REQUEST(drq_e_view_rels))
DYN_REQUEST(drq_e_view_rels) = request;
ERASE VR;
END_FOR;
if (!DYN_REQUEST(drq_e_view_rels))
DYN_REQUEST(drq_e_view_rels) = request;
request = CMP_find_request(tdbb, drq_e_relation, DYN_REQUESTS);
id = drq_e_relation;
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
R IN RDB$RELATIONS WITH R.RDB$RELATION_NAME EQ relation_name.c_str()
if (!DYN_REQUEST(drq_e_relation))
DYN_REQUEST(drq_e_relation) = request;
ERASE R;
if (!R.RDB$SECURITY_CLASS.NULL
&& !strncmp(R.RDB$SECURITY_CLASS, SQL_SECCLASS_PREFIX, SQL_SECCLASS_PREFIX_LEN))
{
delete_security_class2(gbl, R.RDB$SECURITY_CLASS);
}
found = true;
END_FOR;
if (!DYN_REQUEST(drq_e_relation))
DYN_REQUEST(drq_e_relation) = request;
if (!found) {
goto dyn_punt_61;
}
// Triggers must be deleted after check constraints
Firebird::MetaName trigger_name;
request = CMP_find_request(tdbb, drq_e_trigger2, DYN_REQUESTS);
id = drq_e_trigger2;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$TRIGGERS WITH X.RDB$RELATION_NAME EQ relation_name.c_str()
if (!DYN_REQUEST(drq_e_trigger2))
DYN_REQUEST(drq_e_trigger2) = request;
trigger_name = X.RDB$TRIGGER_NAME;
ERASE X;
req2 = CMP_find_request(tdbb, drq_e_trg_prv, DYN_REQUESTS);
id = drq_e_trg_prv;
FOR(REQUEST_HANDLE req2 TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$USER EQ trigger_name.c_str()
AND PRIV.RDB$USER_TYPE = obj_trigger
if (!DYN_REQUEST(drq_e_trg_prv))
DYN_REQUEST(drq_e_trg_prv) = req2;
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_e_trg_prv))
DYN_REQUEST(drq_e_trg_prv) = req2;
id = drq_e_trigger2;
END_FOR;
if (!DYN_REQUEST(drq_e_trigger2))
DYN_REQUEST(drq_e_trigger2) = request;
request = CMP_find_request(tdbb, drq_e_usr_prvs, DYN_REQUESTS);
id = drq_e_usr_prvs;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH
PRIV.RDB$RELATION_NAME EQ relation_name.c_str() AND
PRIV.RDB$OBJECT_TYPE = obj_relation
if (!DYN_REQUEST(drq_e_usr_prvs))
DYN_REQUEST(drq_e_usr_prvs) = request;
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_e_usr_prvs)) {
DYN_REQUEST(drq_e_usr_prvs) = request;
}
request = CMP_find_request(tdbb, drq_e_view_prv, DYN_REQUESTS);
id = drq_e_view_prv;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH
PRIV.RDB$USER EQ relation_name.c_str() AND
PRIV.RDB$USER_TYPE = obj_view
if (!DYN_REQUEST(drq_e_view_prv))
DYN_REQUEST(drq_e_view_prv) = request;
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_e_view_prv)) {
DYN_REQUEST(drq_e_view_prv) = request;
}
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_rundown_request(req2, -1);
// lookup error # from id
// msg 57: "ERASE RDB$INDICES failed"
// msg 58: "ERASE RDB$RELATION_FIELDS failed"
// msg 59: "ERASE RDB$VIEW_RELATIONS failed"
// msg 60: "ERASE RDB$RELATIONS failed"
// msg 62: "ERASE RDB$USER_PRIVILEGES failed"
// msg 65: "ERASE RDB$TRIGGER_MESSAGES failed"
// msg 66: "ERASE RDB$TRIGGERS failed"
// msg 74: "ERASE RDB$SECURITY_CLASSES failed"
// msg 129: "ERASE RDB$RELATION_CONSTRAINTS failed"
USHORT number;
switch (id) {
case drq_e_rel_con2: number = 129; break;
case drq_e_rel_idxs: number = 57; break;
case drq_e_trg_msgs2: number = 65; break;
case drq_e_trigger2: number = 66; break;
case drq_e_rel_flds: number = 58; break;
case drq_e_view_rels: number = 59; break;
case drq_e_relation: number = 60; break;
case drq_e_sec_class: number = 74; break;
default: number = 62; break;
}
DYN_error_punt(true, number, NULL, NULL, NULL, NULL, NULL);
}
while (*(*ptr)++ != isc_dyn_end)
{
--(*ptr);
DYN_execute(gbl, ptr, &relation_name, NULL, NULL, NULL, NULL);
}
return;
dyn_punt_61:
DYN_error_punt(false, 61, NULL, NULL, NULL, NULL, NULL);
/* msg 61: "Relation not found" */
}
void DYN_delete_role( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ r o l e
*
**************************************
*
* Functional description
*
* Execute a dynamic ddl statement that deletes a role with all its
* members of the role.
*
**************************************/
int id = -1;
Firebird::MetaName role_name;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
const USHORT major_version = dbb->dbb_ods_version;
const USHORT minor_original = dbb->dbb_minor_original;
if (ENCODE_ODS(major_version, minor_original) < ODS_9_0) {
DYN_error(false, 196, NULL, NULL, NULL, NULL, NULL);
ERR_punt();
return; // never reached
}
jrd_req* request = NULL;
bool found = false;
try {
Firebird::MetaName user = tdbb->tdbb_attachment->att_user->usr_user_name;
user.upper7();
GET_STRING(ptr, role_name);
request = CMP_find_request(tdbb, drq_drop_role, DYN_REQUESTS);
id = drq_drop_role;
bool del_role_ok = true;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
XX IN RDB$ROLES WITH
XX.RDB$ROLE_NAME EQ role_name.c_str()
if (!DYN_REQUEST(drq_drop_role))
DYN_REQUEST(drq_drop_role) = request;
found = true;
Firebird::MetaName role_owner = XX.RDB$OWNER_NAME;
if ((tdbb->tdbb_attachment->att_user->usr_flags & USR_locksmith) ||
(role_owner == user))
{
ERASE XX;
}
else
{
del_role_ok = false;
}
END_FOR;
if (!DYN_REQUEST(drq_drop_role)) {
DYN_REQUEST(drq_drop_role) = request;
}
if (del_role_ok)
{
request = CMP_find_request(tdbb, drq_del_role_1, DYN_REQUESTS);
id = drq_del_role_1;
/* The first OR clause Finds all members of the role
The 2nd OR clause Finds all privileges granted to the role */
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH
(PRIV.RDB$RELATION_NAME EQ role_name.c_str() AND
PRIV.RDB$OBJECT_TYPE = obj_sql_role)
OR (PRIV.RDB$USER EQ role_name.c_str() AND
PRIV.RDB$USER_TYPE = obj_sql_role)
if (!DYN_REQUEST(drq_del_role_1)) {
DYN_REQUEST(drq_del_role_1) = request;
}
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_del_role_1)) {
DYN_REQUEST(drq_del_role_1) = request;
}
}
else
{
DYN_error(false, 191, user.c_str(), role_name.c_str(), NULL, NULL, NULL);
// only owner of SQL role or USR_locksmith could drop SQL role
goto do_punt;
}
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
const USHORT number = (id == drq_drop_role ? 191 : 62);
// msg 191: "ERASE RDB$ROLES failed"
// msg 62: "ERASE RDB$USER_PRIVILEGES failed"
DYN_error_punt(true, number, NULL, NULL, NULL, NULL, NULL);
}
if (!found)
{
DYN_error_punt(false, 155, role_name.c_str(), NULL, NULL, NULL, NULL);
// msg 155: "Role %s not found"
}
return;
do_punt: // ugly, rethink logic of this function
ERR_punt();
}
void DYN_delete_security_class( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ s e c u r i t y _ c l a s s
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a security class.
*
**************************************/
Firebird::MetaName security_class;
GET_STRING(ptr, security_class);
if (!delete_security_class2(gbl, security_class))
DYN_error_punt(false, 75, NULL, NULL, NULL, NULL, NULL);
/* msg 75: "Security class not found" */
while (*(*ptr)++ != isc_dyn_end) {
--(*ptr);
DYN_execute(gbl, ptr, NULL, NULL, NULL, NULL, NULL);
}
}
void DYN_delete_shadow( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ s h a d o w
*
**************************************
*
* Functional description
* Delete a shadow.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
/*****
the code commented out in this routine was meant to delete the
shadow files, however this cannot be done until the transaction
is commited, which we cannot do automatically as the user may
choose to roll it back.
LLS files;
STR file;
files = NULL;
*****/
jrd_req* request = CMP_find_request(tdbb, drq_e_shadow, DYN_REQUESTS);
try {
const int shadow_number = DYN_get_number(ptr);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIL IN RDB$FILES WITH FIL.RDB$SHADOW_NUMBER EQ shadow_number
if (!DYN_REQUEST(drq_e_shadow))
DYN_REQUEST(drq_e_shadow) = request;
ERASE FIL;
/****
file = FB_NEW_RPT(*tdbb->getDefaultPool(), sizeof (FIL.RDB$FILE_NAME) - 1) str();
strcpy (file->str_data, FIL.RDB$FILE_NAME);
LLS_PUSH (file, &files);
****/
END_FOR;
if (!DYN_REQUEST(drq_e_shadow))
DYN_REQUEST(drq_e_shadow) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 63, NULL, NULL, NULL, NULL, NULL);
/* msg 63: "ERASE RDB$FILES failed" */
}
/****
while (files)
{
file = LLS_POP (&files);
unlink (file->str_data);
ALL_release (file);
}
****/
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
}
void DYN_delete_trigger( Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e l e t e _ t r i g g e r
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a trigger.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_trg_msgs, DYN_REQUESTS);
USHORT id = drq_e_trg_msgs;
Firebird::MetaName t;
GET_STRING(ptr, t);
try {
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
TM IN RDB$TRIGGER_MESSAGES WITH TM.RDB$TRIGGER_NAME EQ t.c_str()
if (!DYN_REQUEST(drq_e_trg_msgs))
DYN_REQUEST(drq_e_trg_msgs) = request;
ERASE TM;
END_FOR;
if (!DYN_REQUEST(drq_e_trg_msgs))
DYN_REQUEST(drq_e_trg_msgs) = request;
request = CMP_find_request(tdbb, drq_e_trigger, DYN_REQUESTS);
id = drq_e_trigger;
Firebird::MetaName r;
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$TRIGGERS WITH X.RDB$TRIGGER_NAME EQ t.c_str()
if (!DYN_REQUEST(drq_e_trigger))
DYN_REQUEST(drq_e_trigger) = request;
r = X.RDB$RELATION_NAME;
ERASE X;
found = true;
END_FOR;
if (!DYN_REQUEST(drq_e_trigger))
DYN_REQUEST(drq_e_trigger) = request;
if (!found) {
goto dyn_punt_147;
}
request = CMP_find_request(tdbb, drq_e_trg_prv, DYN_REQUESTS);
id = drq_e_trg_prv;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$USER EQ t.c_str()
AND PRIV.RDB$USER_TYPE = obj_trigger
if (!DYN_REQUEST(drq_e_trg_prv))
DYN_REQUEST(drq_e_trg_prv) = request;
ERASE PRIV;
END_FOR;
if (!DYN_REQUEST(drq_e_trg_prv))
DYN_REQUEST(drq_e_trg_prv) = request;
/* clear the update flags on the fields if this is the last remaining
trigger that changes a view */
request = CMP_find_request(tdbb, drq_l_view_rel2, DYN_REQUESTS);
id = drq_l_view_rel2;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIRST 1 V IN RDB$VIEW_RELATIONS
CROSS F IN RDB$RELATION_FIELDS CROSS T IN RDB$TRIGGERS
WITH V.RDB$VIEW_NAME EQ r.c_str() AND
F.RDB$RELATION_NAME EQ V.RDB$VIEW_NAME AND
F.RDB$RELATION_NAME EQ T.RDB$RELATION_NAME
if (!DYN_REQUEST(drq_l_view_rel2))
DYN_REQUEST(drq_l_view_rel2) = request;
found = true;
END_FOR;
if (!DYN_REQUEST(drq_l_view_rel2))
DYN_REQUEST(drq_l_view_rel2) = request;
if (!found) {
request = CMP_find_request(tdbb, drq_m_rel_flds, DYN_REQUESTS);
id = drq_m_rel_flds;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
F IN RDB$RELATION_FIELDS WITH F.RDB$RELATION_NAME EQ r.c_str()
if (!DYN_REQUEST(drq_m_rel_flds))
DYN_REQUEST(drq_m_rel_flds) = request;
MODIFY F USING
F.RDB$UPDATE_FLAG = FALSE;
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_rel_flds))
DYN_REQUEST(drq_m_rel_flds) = request;
}
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
switch (id)
{
case drq_e_trg_msgs:
DYN_error_punt(true, 65, NULL, NULL, NULL, NULL, NULL);
/* msg 65: "ERASE RDB$TRIGGER_MESSAGES failed" */
break;
case drq_e_trigger:
DYN_error_punt(true, 66, NULL, NULL, NULL, NULL, NULL);
/* msg 66: "ERASE RDB$TRIGGERS failed" */
break;
case drq_e_trg_prv:
DYN_error_punt(true, 62, NULL, NULL, NULL, NULL, NULL);
/* msg 62: "ERASE RDB$USER_PRIVILEGES failed" */
break;
default:
DYN_error_punt(true, 68, NULL, NULL, NULL, NULL, NULL);
/* msg 68: "MODIFY RDB$VIEW_RELATIONS failed" */
break;
}
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
return;
dyn_punt_147:
DYN_error_punt(false, 147, t.c_str(), NULL, NULL, NULL, NULL);
/* msg 147: "Trigger %s not found" */
}
void DYN_delete_trigger_msg( Global* gbl, const UCHAR** ptr, Firebird::MetaName* trigger_name)
{
/**************************************
*
* D Y N _ d e l e t e _ t r i g g e r _ m s g
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes an trigger message.
*
**************************************/
Firebird::MetaName t;
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
const int number = DYN_get_number(ptr);
if (trigger_name)
t = *trigger_name;
else if (*(*ptr)++ == isc_dyn_trg_name)
GET_STRING(ptr, t);
else
DYN_error_punt(false, 70, NULL, NULL, NULL, NULL, NULL);
/* msg 70: "TRIGGER NAME expected" */
jrd_req* request = CMP_find_request(tdbb, drq_e_trg_msg, DYN_REQUESTS);
bool found = false;
try {
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$TRIGGER_MESSAGES
WITH X.RDB$TRIGGER_NAME EQ t.c_str() AND X.RDB$MESSAGE_NUMBER EQ number
if (!DYN_REQUEST(drq_e_trg_msg))
DYN_REQUEST(drq_e_trg_msg) = request;
found = true;
ERASE X;
END_FOR;
if (!DYN_REQUEST(drq_e_trg_msg))
DYN_REQUEST(drq_e_trg_msg) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 71, NULL, NULL, NULL, NULL, NULL);
/* msg 71: "ERASE TRIGGER MESSAGE failed" */
}
if (!found)
{
DYN_error_punt(false, 72, NULL, NULL, NULL, NULL, NULL);
/* msg 72: "Trigger Message not found" */
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
}
static bool delete_constraint_records(Global* gbl,
const Firebird::MetaName& constraint_name,
const Firebird::MetaName& relation_name)
{
/**************************************
*
* d e l e t e _ c o n s t r a i n t _ r e c o r d s
*
**************************************
*
* Functional description
* Delete a record from RDB$RELATION_CONSTRAINTS
* based on a constraint name.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_rel_con, DYN_REQUESTS);
bool found = false;
try {
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
RC IN RDB$RELATION_CONSTRAINTS
WITH RC.RDB$CONSTRAINT_NAME EQ constraint_name.c_str() AND
RC.RDB$RELATION_NAME EQ relation_name.c_str()
if (!DYN_REQUEST(drq_e_rel_con))
DYN_REQUEST(drq_e_rel_con) = request;
found = true;
ERASE RC;
END_FOR;
if (!DYN_REQUEST(drq_e_rel_con))
DYN_REQUEST(drq_e_rel_con) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 129, NULL, NULL, NULL, NULL, NULL);
/* msg 129: "ERASE RDB$RELATION_CONSTRAINTS failed" */
}
return found;
}
static bool delete_dimension_records(Global* gbl,
const Firebird::MetaName& field_name)
{
/**************************************
*
* d e l e t e _ d i m e n s i o n s _ r e c o r d s
*
**************************************
*
* Functional description
* Delete the records in RDB$FIELD_DIMENSIONS
* pertaining to a field.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_dims, DYN_REQUESTS);
bool found = false;
try {
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FIELD_DIMENSIONS WITH X.RDB$FIELD_NAME EQ field_name.c_str()
if (!DYN_REQUEST(drq_e_dims))
DYN_REQUEST(drq_e_dims) = request;
found = true;
ERASE X;
END_FOR;
if (!DYN_REQUEST(drq_e_dims))
DYN_REQUEST(drq_e_dims) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 35, NULL, NULL, NULL, NULL, NULL);
/* msg 35: "ERASE RDB$FIELDS failed" */
}
return found;
}
static void delete_f_key_constraint(thread_db* tdbb,
Global* gbl,
const Firebird::MetaName& tbl_nm,
const Firebird::MetaName& ,
const Firebird::MetaName& constraint_nm,
const Firebird::MetaName& index_name)
{
/**************************************
*
* d e l e t e _ f _ k e y _ c o n s t r a i n t
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a record from RDB$RELATION_CONSTRAINTS based on a constraint_nm
*
* On deleting from RDB$RELATION_CONSTRAINTS, 2 system triggers fire:
*
* (A) pre delete trigger: pre_delete_constraint, will:
*
* 1. delete a record first from RDB$REF_CONSTRAINTS where
* RDB$REF_CONSTRAINTS.RDB$CONSTRAINT_NAME =
* RDB$RELATION_CONSTRAINTS.RDB$CONSTRAINT_NAME
*
* (B) post delete trigger: post_delete_constraint will:
*
* 1. also delete a record from RDB$INDICES where
* RDB$INDICES.RDB$INDEX_NAME =
* RDB$RELATION_CONSTRAINTS.RDB$INDEX_NAME
*
* 2. also delete a record from RDB$INDEX_SEGMENTS where
* RDB$INDEX_SEGMENTS.RDB$INDEX_NAME =
* RDB$RELATION_CONSTRAINTS.RDB$INDEX_NAME
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_rel_const, DYN_REQUESTS);
try {
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
RC IN RDB$RELATION_CONSTRAINTS
WITH RC.RDB$CONSTRAINT_NAME EQ constraint_nm.c_str()
AND RC.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY
AND RC.RDB$RELATION_NAME EQ tbl_nm.c_str()
AND RC.RDB$INDEX_NAME EQ index_name.c_str()
if (!DYN_REQUEST(drq_e_rel_const))
DYN_REQUEST(drq_e_rel_const) = request;
found = true;
ERASE RC;
END_FOR;
if (!DYN_REQUEST(drq_e_rel_const))
DYN_REQUEST(drq_e_rel_const) = request;
if (!found)
{
DYN_error_punt(false, 130, constraint_nm.c_str(), NULL, NULL, NULL, NULL);
/* msg 130: "CONSTRAINT %s does not exist." */
}
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 129, NULL, NULL, NULL, NULL, NULL);
/* msg 49: "ERASE RDB$RELATION_CONSTRAINTS failed" */
}
}
static void delete_gfield_for_lfield( Global* gbl, const Firebird::MetaName& lfield_name)
{
/**************************************
*
* d e l e t e _ g f i e l d _ f o r _ l f i e l d
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that
* deletes a global field for a given local field.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_l_gfld, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS
WITH FLD.RDB$FIELD_NAME EQ lfield_name.c_str()
AND FLD.RDB$VALIDATION_SOURCE MISSING AND
FLD.RDB$NULL_FLAG MISSING AND
FLD.RDB$DEFAULT_SOURCE MISSING AND
FLD.RDB$FIELD_NAME STARTING WITH IMPLICIT_DOMAIN_PREFIX AND
NOT ANY RFR IN RDB$RELATION_FIELDS WITH
RFR.RDB$FIELD_SOURCE EQ FLD.RDB$FIELD_NAME
if (!DYN_REQUEST(drq_e_l_gfld))
DYN_REQUEST(drq_e_l_gfld) = request;
delete_dimension_records(gbl, FLD.RDB$FIELD_NAME);
ERASE FLD;
END_FOR;
if (!DYN_REQUEST(drq_e_l_gfld))
DYN_REQUEST(drq_e_l_gfld) = request;
}
static bool delete_index_segment_records(Global* gbl,
const Firebird::MetaName& index_name)
{
/**************************************
*
* d e l e t e _ i n d e x _ s e g m e n t _ r e c o r d s
*
**************************************
*
* Functional description
* Delete the records in RDB$INDEX_SEGMENTS
* pertaining to an index.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_idx_segs, DYN_REQUESTS);
bool found = false;
try {
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
I_S IN RDB$INDEX_SEGMENTS WITH I_S.RDB$INDEX_NAME EQ index_name.c_str()
if (!DYN_REQUEST(drq_e_idx_segs))
DYN_REQUEST(drq_e_idx_segs) = request;
found = true;
ERASE I_S;
END_FOR;
if (!DYN_REQUEST(drq_e_idx_segs))
DYN_REQUEST(drq_e_idx_segs) = request;
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 49, NULL, NULL, NULL, NULL, NULL);
/* msg 49: "ERASE RDB$INDEX_SEGMENTS failed" */
}
return found;
}
static bool delete_security_class2( Global* gbl, const Firebird::MetaName& security_class)
{
/**************************************
*
* d e l e t e _ s e c u r i t y _ c l a s s 2
*
**************************************
*
* Functional description
* Utility routine for delete_security_class(),
* which takes a string as input.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_class, DYN_REQUESTS);
bool found = false;
try {
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
SC IN RDB$SECURITY_CLASSES
WITH SC.RDB$SECURITY_CLASS EQ security_class.c_str()
if (!DYN_REQUEST(drq_e_class))
DYN_REQUEST(drq_e_class) = request;
found = true;
ERASE SC;
END_FOR;
if (!DYN_REQUEST(drq_e_class)) {
DYN_REQUEST(drq_e_class) = request;
}
}
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 74, NULL, NULL, NULL, NULL, NULL);
/* msg 74: "ERASE RDB$SECURITY_CLASSES failed" */
}
return found;
}