mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-31 04:03:03 +01:00
1773 lines
48 KiB
Plaintext
1773 lines
48 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 "dyn_consts.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "../jrd/common.h"
|
|
#include "../dsql/DdlNodes.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/met.h"
|
|
#include "../jrd/btr.h"
|
|
#include "../jrd/intl.h"
|
|
#include "../jrd/dyn.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/vio_proto.h"
|
|
#include "../common/utils_proto.h"
|
|
|
|
using MsgFormat::SafeArg;
|
|
|
|
using namespace Jrd;
|
|
using namespace Firebird;
|
|
|
|
|
|
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 void delete_identity_generator(thread_db* tdbb, jrd_tra* transaction,
|
|
const MetaName& generatorName);
|
|
static bool delete_index_segment_records(Global*, const Firebird::MetaName&);
|
|
|
|
|
|
void DYN_delete_collation(Global* gbl, const UCHAR** ptr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D Y N _ d e l e t e _ c o l l a t i o n
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Execute a dynamic ddl statement that
|
|
* deletes a collation from rdb$collations.
|
|
*
|
|
**************************************/
|
|
thread_db* tdbb = JRD_get_thread_data();
|
|
Database* dbb = tdbb->getDatabase();
|
|
|
|
jrd_req* request = NULL;
|
|
|
|
bool found = false;
|
|
Firebird::MetaName collName;
|
|
|
|
try
|
|
{
|
|
GET_STRING(ptr, collName);
|
|
|
|
request = CMP_find_request(tdbb, drq_e_colls, DYN_REQUESTS);
|
|
|
|
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
COLL IN RDB$COLLATIONS
|
|
CROSS CS IN RDB$CHARACTER_SETS
|
|
WITH COLL.RDB$COLLATION_NAME EQ collName.c_str() AND
|
|
CS.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID
|
|
|
|
if (!DYN_REQUEST(drq_e_colls))
|
|
DYN_REQUEST(drq_e_colls) = request;
|
|
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
|
|
DDL_TRIGGER_DROP_COLLATION, collName, gbl->sqlText);
|
|
|
|
if (COLL.RDB$SYSTEM_FLAG == 1)
|
|
{
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(false, 237);
|
|
// msg 237: "Cannot delete system collation"
|
|
}
|
|
|
|
if (COLL.RDB$COLLATION_ID == 0 ||
|
|
(!CS.RDB$DEFAULT_COLLATE_NAME.NULL &&
|
|
Firebird::MetaName(COLL.RDB$COLLATION_NAME) == Firebird::MetaName(CS.RDB$DEFAULT_COLLATE_NAME)))
|
|
{
|
|
fb_utils::exact_name_limit(CS.RDB$CHARACTER_SET_NAME,
|
|
sizeof(CS.RDB$CHARACTER_SET_NAME));
|
|
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(false, 238, CS.RDB$CHARACTER_SET_NAME);
|
|
// msg 238: "Cannot delete default collation of CHARACTER SET %s"
|
|
}
|
|
|
|
found = true;
|
|
fb_utils::exact_name_limit(COLL.RDB$COLLATION_NAME,
|
|
sizeof(COLL.RDB$COLLATION_NAME));
|
|
|
|
jrd_req* request2 = CMP_find_request(tdbb, drq_l_rfld_coll, DYN_REQUESTS);
|
|
|
|
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
RF IN RDB$RELATION_FIELDS CROSS F IN RDB$FIELDS
|
|
WITH RF.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND
|
|
F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND
|
|
RF.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID
|
|
|
|
if (!DYN_REQUEST(drq_l_rfld_coll))
|
|
DYN_REQUEST(drq_l_rfld_coll) = request2;
|
|
|
|
fb_utils::exact_name_limit(RF.RDB$RELATION_NAME, sizeof(RF.RDB$RELATION_NAME));
|
|
fb_utils::exact_name_limit(RF.RDB$FIELD_NAME, sizeof(RF.RDB$FIELD_NAME));
|
|
|
|
DYN_rundown_request(request2, -1);
|
|
DYN_error_punt(false, 235, SafeArg() << COLL.RDB$COLLATION_NAME <<
|
|
RF.RDB$RELATION_NAME << RF.RDB$FIELD_NAME);
|
|
// msg 235: "Collation %s is used in table %s (field name %s) and cannot be dropped"
|
|
END_FOR;
|
|
|
|
if (!DYN_REQUEST(drq_l_rfld_coll))
|
|
DYN_REQUEST(drq_l_rfld_coll) = request2;
|
|
|
|
request2 = CMP_find_request(tdbb, drq_l_prm_coll, DYN_REQUESTS);
|
|
|
|
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
PRM IN RDB$PROCEDURE_PARAMETERS CROSS F IN RDB$FIELDS
|
|
WITH PRM.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND
|
|
F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND
|
|
PRM.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID
|
|
|
|
if (!DYN_REQUEST(drq_l_prm_coll))
|
|
DYN_REQUEST(drq_l_prm_coll) = request2;
|
|
|
|
fb_utils::exact_name_limit(PRM.RDB$PARAMETER_NAME, sizeof(PRM.RDB$PARAMETER_NAME));
|
|
|
|
DYN_rundown_request(request2, -1);
|
|
DYN_error_punt(false, 243, SafeArg() <<
|
|
COLL.RDB$COLLATION_NAME <<
|
|
QualifiedName(PRM.RDB$PROCEDURE_NAME,
|
|
(PRM.RDB$PACKAGE_NAME.NULL ? NULL : PRM.RDB$PACKAGE_NAME)).toString().c_str() <<
|
|
PRM.RDB$PARAMETER_NAME);
|
|
// msg 243: "Collation %s is used in procedure %s (parameter name %s) and cannot be dropped"
|
|
END_FOR;
|
|
|
|
if (!DYN_REQUEST(drq_l_prm_coll))
|
|
DYN_REQUEST(drq_l_prm_coll) = request2;
|
|
|
|
request2 = CMP_find_request(tdbb, drq_l_fld_coll, DYN_REQUESTS);
|
|
|
|
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
F IN RDB$FIELDS
|
|
WITH F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND
|
|
F.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID
|
|
|
|
if (!DYN_REQUEST(drq_l_fld_coll))
|
|
DYN_REQUEST(drq_l_fld_coll) = request2;
|
|
|
|
fb_utils::exact_name_limit(F.RDB$FIELD_NAME, sizeof(F.RDB$FIELD_NAME));
|
|
|
|
DYN_rundown_request(request2, -1);
|
|
DYN_error_punt(false, 236, SafeArg() << COLL.RDB$COLLATION_NAME << F.RDB$FIELD_NAME);
|
|
// msg 236: "Collation %s is used in domain %s and cannot be dropped"
|
|
END_FOR;
|
|
|
|
if (!DYN_REQUEST(drq_l_fld_coll))
|
|
DYN_REQUEST(drq_l_fld_coll) = request2;
|
|
|
|
ERASE COLL;
|
|
END_FOR;
|
|
|
|
if (!DYN_REQUEST(drq_e_colls))
|
|
DYN_REQUEST(drq_e_colls) = request;
|
|
}
|
|
catch (const Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 233);
|
|
// msg 234: "ERASE RDB$COLLATIONS failed"
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
|
|
DDL_TRIGGER_DROP_COLLATION, collName, gbl->sqlText);
|
|
}
|
|
else
|
|
{
|
|
DYN_error_punt(false, 152, collName.c_str());
|
|
// msg 152: "Collation %s not found"
|
|
}
|
|
}
|
|
|
|
|
|
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); // 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()); // 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) // Obtained from the stream
|
|
{
|
|
/**************************************
|
|
*
|
|
* 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->getDatabase();
|
|
|
|
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;
|
|
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
|
|
DDL_TRIGGER_DROP_EXCEPTION, t, gbl->sqlText);
|
|
|
|
ERASE X;
|
|
END_FOR;
|
|
if (!DYN_REQUEST(drq_e_xcp))
|
|
DYN_REQUEST(drq_e_xcp) = request;
|
|
|
|
} // try
|
|
catch (const Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 143);
|
|
// msg 143: "ERASE EXCEPTION failed"
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
|
|
DDL_TRIGGER_DROP_EXCEPTION, t, gbl->sqlText);
|
|
}
|
|
else
|
|
{
|
|
DYN_error_punt(false, 144);
|
|
// 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->getDatabase();
|
|
|
|
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 Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 36);
|
|
// msg 36: "ERASE BLOB FILTER failed"
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
DYN_error_punt(false, 37, f.c_str());
|
|
// msg 37: "Blob Filter %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->getDatabase();
|
|
|
|
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;
|
|
|
|
if (X.RDB$SYSTEM_FLAG != 0)
|
|
{
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(false, 272); // msg 272: "Cannot delete system generator"
|
|
}
|
|
|
|
found = true;
|
|
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
|
|
DDL_TRIGGER_DROP_SEQUENCE, t, gbl->sqlText);
|
|
|
|
ERASE X;
|
|
END_FOR;
|
|
|
|
if (!DYN_REQUEST(drq_e_gens))
|
|
DYN_REQUEST(drq_e_gens) = request;
|
|
}
|
|
catch (const Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 213);
|
|
// msg 213: "ERASE GENERATOR failed"
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
|
|
DDL_TRIGGER_DROP_SEQUENCE, t, gbl->sqlText);
|
|
}
|
|
else
|
|
{
|
|
DYN_error_punt(false, 214, t.c_str());
|
|
// 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->getDatabase();
|
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_e_gfields, DYN_REQUESTS);
|
|
|
|
bool found = false;
|
|
|
|
try
|
|
{
|
|
GET_STRING(ptr, f);
|
|
|
|
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;
|
|
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
|
|
DDL_TRIGGER_DROP_DOMAIN, f, gbl->sqlText);
|
|
|
|
delete_dimension_records(gbl, f);
|
|
ERASE X;
|
|
found = true;
|
|
END_FOR
|
|
if (!DYN_REQUEST(drq_e_gfields))
|
|
DYN_REQUEST(drq_e_gfields) = request;
|
|
|
|
request = CMP_find_request(tdbb, drq_l_fld_src, DYN_REQUESTS);
|
|
|
|
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, SafeArg() << Y.RDB$FIELD_SOURCE << Y.RDB$RELATION_NAME <<
|
|
Y.RDB$FIELD_NAME);
|
|
// msg 43: "Domain %s is used in table %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_l_prp_src, DYN_REQUESTS);
|
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
X IN RDB$PROCEDURE_PARAMETERS
|
|
WITH X.RDB$FIELD_SOURCE EQ f.c_str()
|
|
if (!DYN_REQUEST(drq_l_prp_src))
|
|
DYN_REQUEST(drq_l_prp_src) = request;
|
|
|
|
fb_utils::exact_name_limit(X.RDB$FIELD_SOURCE, sizeof(X.RDB$FIELD_SOURCE));
|
|
fb_utils::exact_name_limit(X.RDB$PROCEDURE_NAME, sizeof(X.RDB$PROCEDURE_NAME));
|
|
fb_utils::exact_name_limit(X.RDB$PARAMETER_NAME, sizeof(X.RDB$PARAMETER_NAME));
|
|
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(false, 239, SafeArg() << X.RDB$FIELD_SOURCE <<
|
|
QualifiedName(X.RDB$PROCEDURE_NAME,
|
|
(X.RDB$PACKAGE_NAME.NULL ? NULL : X.RDB$PACKAGE_NAME)).toString().c_str() <<
|
|
X.RDB$PARAMETER_NAME);
|
|
// msg 239: "Domain %s is used in procedure %s (parameter name %s) and cannot be dropped"
|
|
|
|
END_FOR
|
|
if (!DYN_REQUEST(drq_l_prp_src))
|
|
DYN_REQUEST(drq_l_prp_src) = request;
|
|
} // try
|
|
catch (const Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 44);
|
|
// msg 44: "ERASE RDB$FIELDS failed"
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
|
|
DDL_TRIGGER_DROP_DOMAIN, f, gbl->sqlText);
|
|
}
|
|
else
|
|
{
|
|
DYN_error_punt(false, 89);
|
|
// msg 89: "Domain 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->getDatabase();
|
|
|
|
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;
|
|
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
|
|
DDL_TRIGGER_DROP_INDEX, idx_name, gbl->sqlText);
|
|
|
|
is_expression = !IDX.RDB$EXPRESSION_BLR.NULL;
|
|
ERASE IDX;
|
|
END_FOR;
|
|
if (!DYN_REQUEST(drq_e_indices))
|
|
DYN_REQUEST(drq_e_indices) = request;
|
|
} //try
|
|
catch (const Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 47);
|
|
// msg 47: "ERASE RDB$INDICES failed"
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
|
|
DDL_TRIGGER_DROP_INDEX, idx_name, gbl->sqlText);
|
|
}
|
|
else
|
|
{
|
|
DYN_error_punt(false, 48);
|
|
// msg 48: "Index not found"
|
|
}
|
|
|
|
if (!is_expression)
|
|
if (!delete_index_segment_records(gbl, idx_name))
|
|
{
|
|
DYN_error_punt(false, 50);
|
|
// 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) // Obtained from the stream
|
|
{
|
|
/**************************************
|
|
*
|
|
* 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->getDatabase();
|
|
|
|
GET_STRING(ptr, col_nm);
|
|
|
|
if (relation_name)
|
|
tbl_nm = *relation_name;
|
|
else if (*(*ptr)++ != isc_dyn_rel_name)
|
|
{
|
|
DYN_error_punt(false, 51);
|
|
// 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, SafeArg() << col_nm.c_str() << tbl_nm.c_str() << Y.RDB$RELATION_NAME);
|
|
// 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 column 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, SafeArg() << col_nm.c_str() << tbl_nm.c_str() <<
|
|
IDX.RDB$INDEX_NAME);
|
|
// 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 user-defined 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;
|
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
IDX IN RDB$INDICES CROSS
|
|
IDX_SEG IN RDB$INDEX_SEGMENTS
|
|
WITH IDX.RDB$INDEX_NAME EQ IDX_SEG.RDB$INDEX_NAME
|
|
AND IDX.RDB$RELATION_NAME EQ tbl_nm.c_str()
|
|
AND IDX_SEG.RDB$FIELD_NAME EQ col_nm.c_str()
|
|
AND NOT ANY
|
|
REL_CONST IN RDB$RELATION_CONSTRAINTS
|
|
WITH REL_CONST.RDB$RELATION_NAME EQ IDX.RDB$RELATION_NAME
|
|
AND REL_CONST.RDB$INDEX_NAME EQ IDX.RDB$INDEX_NAME
|
|
if (!DYN_REQUEST(drq_e_l_idx))
|
|
DYN_REQUEST(drq_e_l_idx) = request;
|
|
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(false, 187, SafeArg() << col_nm.c_str() << tbl_nm.c_str() <<
|
|
fb_utils::exact_name_limit(IDX.RDB$INDEX_NAME, sizeof(IDX.RDB$INDEX_NAME)));
|
|
// 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;
|
|
|
|
if (!RFR.RDB$GENERATOR_NAME.NULL)
|
|
delete_identity_generator(tdbb, gbl->gbl_transaction, RFR.RDB$GENERATOR_NAME);
|
|
|
|
ERASE RFR;
|
|
|
|
if (!RFR.RDB$SECURITY_CLASS.NULL &&
|
|
!strncmp(RFR.RDB$SECURITY_CLASS, SQL_SECCLASS_PREFIX, SQL_SECCLASS_PREFIX_LEN))
|
|
{
|
|
DYN_delete_security_class2(gbl->gbl_transaction, RFR.RDB$SECURITY_CLASS);
|
|
}
|
|
|
|
found = true;
|
|
delete_gfield_for_lfield(gbl, RFR.RDB$FIELD_SOURCE);
|
|
const Firebird::MetaName rel_name(RFR.RDB$RELATION_NAME);
|
|
while (*(*ptr)++ != isc_dyn_end)
|
|
{
|
|
--(*ptr);
|
|
{
|
|
MetaNameProxy tmp(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 Firebird::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);
|
|
// msg 53: "ERASE RDB$RELATION_FIELDS failed"
|
|
case drq_e_fld_prvs:
|
|
DYN_error_punt(true, 62);
|
|
// msg 62: "ERASE RDB$USER_PRIVILEGES failed"
|
|
default:
|
|
DYN_error_punt(true, 53);
|
|
// msg 53: "ERASE RDB$RELATION_FIELDS failed"
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
DYN_error_punt(false, 176, SafeArg() << col_nm.c_str() << tbl_nm.c_str());
|
|
// msg 176: "column %s does not exist in table/view %s"
|
|
}
|
|
}
|
|
|
|
|
|
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->getDatabase();
|
|
|
|
if (relation)
|
|
relation_name = *relation;
|
|
else
|
|
GET_STRING(ptr, relation_name);
|
|
|
|
jrd_req* req2 = NULL;
|
|
jrd_req* request = CMP_find_request(tdbb, drq_l_relation, DYN_REQUESTS);
|
|
USHORT id = drq_l_relation;
|
|
|
|
bool found = false;
|
|
bool view = false;
|
|
|
|
try {
|
|
|
|
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_l_relation))
|
|
DYN_REQUEST(drq_l_relation) = request;
|
|
|
|
view = !R.RDB$VIEW_BLR.NULL;
|
|
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
|
|
(view ? DDL_TRIGGER_DROP_VIEW : DDL_TRIGGER_DROP_TABLE), relation_name, gbl->sqlText);
|
|
END_FOR;
|
|
|
|
if (!DYN_REQUEST(drq_l_relation))
|
|
DYN_REQUEST(drq_l_relation) = request;
|
|
|
|
request = CMP_find_request(tdbb, drq_e_rel_con2, DYN_REQUESTS);
|
|
id = drq_e_rel_con2;
|
|
|
|
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;
|
|
|
|
if (!RFR.RDB$GENERATOR_NAME.NULL)
|
|
delete_identity_generator(tdbb, gbl->gbl_transaction, RFR.RDB$GENERATOR_NAME);
|
|
|
|
ERASE RFR;
|
|
|
|
if (!RFR.RDB$SECURITY_CLASS.NULL &&
|
|
!strncmp(RFR.RDB$SECURITY_CLASS, SQL_SECCLASS_PREFIX, SQL_SECCLASS_PREFIX_LEN))
|
|
{
|
|
DYN_delete_security_class2(gbl->gbl_transaction, 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;
|
|
|
|
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))
|
|
{
|
|
DYN_delete_security_class2(gbl->gbl_transaction, 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 Firebird::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_l_relation:
|
|
case drq_e_relation:
|
|
number = 60;
|
|
break;
|
|
//case drq_e_sec_class:
|
|
// number = 74;
|
|
// break;
|
|
default:
|
|
number = 62;
|
|
break;
|
|
}
|
|
|
|
DYN_error_punt(true, number);
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
|
|
(view ? DDL_TRIGGER_DROP_VIEW : DDL_TRIGGER_DROP_TABLE), relation_name, gbl->sqlText);
|
|
}
|
|
|
|
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);
|
|
// 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->getDatabase();
|
|
|
|
jrd_req* request = NULL;
|
|
bool found = false;
|
|
|
|
try
|
|
{
|
|
Firebird::MetaName user(tdbb->getAttachment()->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;
|
|
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
|
|
DDL_TRIGGER_DROP_ROLE, role_name, gbl->sqlText);
|
|
|
|
const Firebird::MetaName role_owner(XX.RDB$OWNER_NAME);
|
|
|
|
if (tdbb->getAttachment()->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, SafeArg() << user.c_str() << role_name.c_str());
|
|
// only owner of SQL role or USR_locksmith could drop SQL role
|
|
goto do_punt;
|
|
}
|
|
} // try
|
|
catch (const Firebird::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);
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
|
|
DDL_TRIGGER_DROP_ROLE, role_name, gbl->sqlText);
|
|
}
|
|
else
|
|
{
|
|
DYN_error_punt(false, 155, role_name.c_str());
|
|
// msg 155: "Role %s not found"
|
|
}
|
|
|
|
return;
|
|
|
|
do_punt: // ugly, rethink logic of this function
|
|
ERR_punt();
|
|
}
|
|
|
|
|
|
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->getDatabase();
|
|
|
|
if (!tdbb->getAttachment()->locksmith())
|
|
{
|
|
ERR_post(Arg::Gds(isc_adm_task_denied));
|
|
}
|
|
|
|
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;
|
|
END_FOR;
|
|
|
|
if (!DYN_REQUEST(drq_e_shadow))
|
|
DYN_REQUEST(drq_e_shadow) = request;
|
|
|
|
}
|
|
catch (const Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 63);
|
|
// msg 63: "ERASE RDB$FILES failed"
|
|
}
|
|
|
|
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->getDatabase();
|
|
|
|
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 Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 129);
|
|
// 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->getDatabase();
|
|
|
|
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 Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 35);
|
|
// 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->getDatabase();
|
|
|
|
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());
|
|
// msg 130: "CONSTRAINT %s does not exist."
|
|
}
|
|
}
|
|
catch (const Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 129);
|
|
// 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->getDatabase();
|
|
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 void delete_identity_generator(thread_db* tdbb, jrd_tra* transaction,
|
|
const MetaName& generatorName)
|
|
{
|
|
AutoCacheRequest request(tdbb, drq_e_ident_gens, DYN_REQUESTS);
|
|
|
|
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
|
GEN IN RDB$GENERATORS
|
|
WITH GEN.RDB$GENERATOR_NAME EQ generatorName.c_str()
|
|
{
|
|
ERASE GEN;
|
|
}
|
|
END_FOR
|
|
}
|
|
|
|
|
|
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->getDatabase();
|
|
|
|
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 Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 49);
|
|
// msg 49: "ERASE RDB$INDEX_SEGMENTS failed"
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
|
|
bool DYN_delete_security_class2(jrd_tra* transaction, const Firebird::MetaName& security_class)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D Y N _ 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->getDatabase();
|
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_e_class, DYN_REQUESTS);
|
|
|
|
bool found = false;
|
|
|
|
try
|
|
{
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE 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 Firebird::Exception& ex)
|
|
{
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
|
DYN_rundown_request(request, -1);
|
|
DYN_error_punt(true, 74);
|
|
// msg 74: "ERASE RDB$SECURITY_CLASSES failed"
|
|
}
|
|
|
|
return found;
|
|
}
|