8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 00:03:03 +01:00
firebird-mirror/src/jrd/dyn_del.epp
brodsom 80b424e346 -Replace define with const
-Move SYS_ERR, ERRNO, H_ERRNO and INET_ERRNO(ERRNO in inet.cpp) macros to common.h
-Remove unused macros
2004-05-05 21:55:13 +00:00

2028 lines
53 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_proto.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 TEXT*, const TEXT*);
static bool delete_dimension_records(Global*, const TEXT*);
static void delete_f_key_constraint(thread_db*, Global*, const TEXT*, const TEXT*,
const TEXT*, const TEXT*);
static void delete_gfield_for_lfield(Global*, const TEXT*);
static bool delete_index_segment_records(Global*, const TEXT*);
static bool delete_security_class2(Global*, const TEXT*);
void DYN_delete_constraint (Global* gbl, const UCHAR** ptr, const TEXT* 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
*
**************************************/
SqlIdentifier rel_name, constraint;
/* GET name of the constraint to be deleted */
GET_STRING(ptr, constraint);
if (relation)
strcpy(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, NULL, NULL, NULL, NULL);
/* msg 130: "CONSTRAINT %s does not exist." */
}
void DYN_delete_dimensions(
Global* gbl,
const UCHAR** ptr,
const TEXT* relation_name, TEXT* 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.
*
**************************************/
SqlIdentifier 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.
*
**************************************/
SqlIdentifier t;
thread_db* tdbb = 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
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" */
}
}
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.
*
**************************************/
SqlIdentifier f;
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_filters, DYN_REQUESTS);
bool found = false;
try {
GET_STRING(ptr, f);
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FILTERS WITH X.RDB$FUNCTION_NAME = f
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, NULL, NULL, NULL, NULL, NULL);
/* msg 37: "Blob Filter 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.
*
**************************************/
SqlIdentifier f;
thread_db* tdbb = 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;
try {
GET_STRING(ptr, f);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FA IN RDB$FUNCTION_ARGUMENTS WITH FA.RDB$FUNCTION_NAME EQ f
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
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, NULL, NULL, NULL, NULL, NULL);
/* msg 41: "Function 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.
*
**************************************/
SqlIdentifier t;
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
jrd_req* request = NULL;
bool found = false;
try {
GET_STRING(ptr, t);
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
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, NULL, NULL, NULL, NULL, NULL);
/* msg 214: "Generator 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.
*
**************************************/
SqlIdentifier f;
thread_db* tdbb = 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
if (!DYN_REQUEST(drq_l_fld_src))
DYN_REQUEST(drq_l_fld_src) = request;
fb_utils::fb_exact_name_limit(Y.RDB$FIELD_SOURCE, sizeof(Y.RDB$FIELD_SOURCE));
fb_utils::fb_exact_name_limit(Y.RDB$RELATION_NAME, sizeof(Y.RDB$RELATION_NAME));
fb_utils::fb_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
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.
*
**************************************/
SqlIdentifier idx_name, rel_name;
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_indices, DYN_REQUESTS);
bool found = 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
if (!DYN_REQUEST(drq_e_indices))
DYN_REQUEST(drq_e_indices) = request;
strcpy(rel_name, IDX.RDB$RELATION_NAME);
fb_utils::fb_exact_name(rel_name);
found = true;
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" */
}
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 TEXT* relation_name, TEXT* 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.
*
**************************************/
SqlIdentifier tbl_nm, col_nm, constraint, index_name;
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
GET_STRING(ptr, col_nm);
if (relation_name)
strcpy(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 AND
X.RDB$FIELD_NAME EQ col_nm 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, tbl_nm, 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
AND REL_CONST.RDB$RELATION_NAME EQ tbl_nm
AND IDX_SEG.RDB$FIELD_NAME EQ col_nm
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) {
fb_utils::fb_exact_name_limit(REL_CONST.RDB$CONSTRAINT_NAME,
sizeof(REL_CONST.RDB$CONSTRAINT_NAME));
strcpy(constraint, REL_CONST.RDB$CONSTRAINT_NAME);
fb_utils::fb_exact_name_limit(IDX.RDB$INDEX_NAME, sizeof(IDX.RDB$INDEX_NAME));
strcpy(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, tbl_nm,
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
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
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, tbl_nm, 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
AND RFR.RDB$RELATION_NAME EQ tbl_nm
if (!DYN_REQUEST(drq_e_lfield))
DYN_REQUEST(drq_e_lfield) = request;
ERASE RFR;
found = true;
delete_gfield_for_lfield(gbl, RFR.RDB$FIELD_SOURCE);
while (*(*ptr)++ != isc_dyn_end) {
--(*ptr);
DYN_execute(gbl, ptr, RFR.RDB$RELATION_NAME,
RFR.RDB$FIELD_SOURCE, NULL, NULL, NULL);
}
END_FOR;
if (!DYN_REQUEST(drq_e_lfield)) {
DYN_REQUEST(drq_e_lfield) = request;
}
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
if (id == drq_l_dep_flds)
{
DYN_error_punt(true, 53, NULL, NULL, NULL, NULL, NULL);
/* msg 53: "ERASE RDB$RELATION_FIELDS failed" */
}
else
{
DYN_error_punt(true, 54, NULL, NULL, NULL, NULL, NULL);
/* msg 54: "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, TEXT* 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.
*
**************************************/
USHORT id;
SqlIdentifier name;
GET_STRING(ptr, name);
if (**ptr == isc_dyn_prc_name) {
DYN_get_string(reinterpret_cast<const TEXT**>(++ptr), proc_name,
MAX_SQL_IDENTIFIER_SIZE, true);
}
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_prm, DYN_REQUESTS);
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
AND PP.RDB$PARAMETER_NAME EQ name
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, proc_name, 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.
*
**************************************/
USHORT id;
SqlIdentifier name;
GET_STRING(ptr, name);
thread_db* tdbb = 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, 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);
id = drq_e_prms;
bool found = false;
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
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;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
P IN RDB$PROCEDURES WITH P.RDB$PROCEDURE_NAME EQ name
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
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;
} // 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, NULL, NULL, NULL, NULL);
/* msg 140: "Procedure %s not found" */
}
void DYN_delete_relation( Global* gbl, const UCHAR** ptr, const TEXT* 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.
*
**************************************/
USHORT id;
SqlIdentifier relation_name;
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
if (relation)
strcpy(relation_name, relation);
else
GET_STRING(ptr, relation_name);
jrd_req* request = CMP_find_request(tdbb, drq_e_rel_con2, DYN_REQUESTS);
id = drq_e_rel_con2;
bool found = false;
try {
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
CRT IN RDB$RELATION_CONSTRAINTS
WITH CRT.RDB$RELATION_NAME EQ relation_name 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
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 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;
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
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
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;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
R IN RDB$RELATIONS WITH R.RDB$RELATION_NAME EQ relation_name
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;
}
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 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;
/* Triggers must be deleted after check constraints */
request = CMP_find_request(tdbb, drq_e_trigger2, DYN_REQUESTS);
id = drq_e_trigger2;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$TRIGGERS WITH X.RDB$RELATION_NAME EQ relation_name
if (!DYN_REQUEST(drq_e_trigger2))
DYN_REQUEST(drq_e_trigger2) = request;
ERASE X;
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 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;
}
} // try
catch (const std::exception& ex) {
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -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.
*
**************************************/
USHORT id;
SqlIdentifier role_name, role_owner, user;
TEXT *ptr1, *ptr2;
thread_db* tdbb = 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;
try {
for (ptr1 = tdbb->tdbb_attachment->att_user->usr_user_name, ptr2 =
user; *ptr1; ptr1++, ptr2++)
{
*ptr2 = UPPER7(*ptr1);
}
*ptr2 = '\0';
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 if (!DYN_REQUEST(drq_drop_role))
DYN_REQUEST(drq_drop_role) = request;
fb_utils::fb_exact_name_limit(XX.RDB$OWNER_NAME, sizeof(XX.RDB$OWNER_NAME));
strcpy(role_owner, XX.RDB$OWNER_NAME);
if ((tdbb->tdbb_attachment->att_user->usr_flags & USR_locksmith) ||
(strcmp(role_owner, user) == 0))
{
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 AND
PRIV.RDB$OBJECT_TYPE = obj_sql_role)
OR(PRIV.RDB$USER EQ role_name 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
{
/****************************************************
**
** only owner of SQL role or USR_locksmith could drop SQL role
**
*****************************************************/
DYN_error(false, 191, user, role_name, NULL, NULL, NULL);
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);
}
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.
*
**************************************/
SqlIdentifier 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.
*
**************************************/
int shadow_number;
thread_db* tdbb = 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 {
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->tdbb_default, 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.
*
**************************************/
USHORT id;
SqlIdentifier r, t;
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
jrd_req* request = CMP_find_request(tdbb, drq_e_trg_msgs, DYN_REQUESTS);
id = drq_e_trg_msgs;
bool found = false;
try {
GET_STRING(ptr, t);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
TM IN RDB$TRIGGER_MESSAGES WITH TM.RDB$TRIGGER_NAME EQ t
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;
found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$TRIGGERS WITH X.RDB$TRIGGER_NAME EQ t
if (!DYN_REQUEST(drq_e_trigger))
DYN_REQUEST(drq_e_trigger) = request;
gds__vtov(X.RDB$RELATION_NAME, r, sizeof(r));
ERASE X;
found = true;
END_FOR;
if (!DYN_REQUEST(drq_e_trigger))
DYN_REQUEST(drq_e_trigger) = request;
if (!found) {
goto dyn_punt_67;
}
/* 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 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
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);
if (id == drq_e_trg_msgs)
{
DYN_error_punt(true, 65, NULL, NULL, NULL, NULL, NULL);
/* msg 65: "ERASE RDB$TRIGGER_MESSAGES failed" */
}
else if (id == drq_e_trigger)
{
DYN_error_punt(true, 66, NULL, NULL, NULL, NULL, NULL);
/* msg 66: "ERASE RDB$TRIGGERS failed" */
}
else
{
DYN_error_punt(true, 68, NULL, NULL, NULL, NULL, NULL);
/* msg 68: "MODIFY RDB$VIEW_RELATIONS failed" */
}
}
if (*(*ptr)++ != isc_dyn_end) {
DYN_unsupported_verb();
}
return;
dyn_punt_67:
DYN_error_punt(false, 67, NULL, NULL, NULL, NULL, NULL);
/* msg 67: "Trigger not found" */
}
void DYN_delete_trigger_msg( Global* gbl, const UCHAR** ptr, TEXT* 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.
*
**************************************/
int number;
SqlIdentifier t;
thread_db* tdbb = GET_THREAD_DATA;
Database* dbb = tdbb->tdbb_database;
number = DYN_get_number(ptr);
if (trigger_name)
strcpy(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 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 TEXT* constraint_name,
const TEXT* 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 = 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 AND
RC.RDB$RELATION_NAME EQ relation_name
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 TEXT* 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 = 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
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 TEXT* tbl_nm,
const TEXT* col_nm, // unused
const TEXT* constraint_nm,
const TEXT* 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
AND RC.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY
AND RC.RDB$RELATION_NAME EQ tbl_nm
AND RC.RDB$INDEX_NAME EQ index_name
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, 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 TEXT* 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 = 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
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 TEXT* 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 = 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
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 TEXT* 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 = 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
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;
}