8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 17:23:03 +01:00

Feature #4203 - DROP [IF EXISTS] (#7946)

This commit is contained in:
Adriano dos Santos Fernandes 2024-01-07 11:30:33 -03:00 committed by GitHub
parent 2f444071a1
commit 77ee904255
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 210 additions and 85 deletions

View File

@ -629,3 +629,32 @@ Only users with administrator rights can use this option.
(Dmitry Sibiryakov) (Dmitry Sibiryakov)
If is used twice, an error is returned. If is used twice, an error is returned.
DDL enhancements in Firebird v6.
--------------------------------
1) DROP [IF EXISTS]
Using subclause IF EXISTS, it's now possible to try to drop objects and do not get errors when they di not exists.
DROP EXCEPTION [IF EXISTS] <exception>
DROP INDEX [IF EXISTS] <index>
DROP PROCEDURE [IF EXISTS] <procedure>
DROP TABLE [IF EXISTS] <table>
DROP TRIGGER [IF EXISTS] <trigger>
DROP VIEW [IF EXISTS] <view>
DROP FILTER [IF EXISTS] <filter>
DROP DOMAIN [IF EXISTS] <domain>
DROP [EXTERNAL] FUNCTION [IF EXISTS] <function>
DROP SHADOW [IF EXISTS] <shadow>
DROP ROLE [IF EXISTS] <role>
DROP GENERATOR [IF EXISTS] <generator>
DROP SEQUENCE [IF EXISTS] <sequence>
DROP COLLATION [IF EXISTS] <collation>
DROP USER [IF EXISTS] <user> [USING PLUGIN <plugin>]
DROP PACKAGE [IF EXISTS] <package>
DROP PACKAGE BODY [IF EXISTS] <package>
DROP [GLOBAL] MAPPING [IF EXISTS] <mapping>
ALTER TABLE <table> DROP [IF EXISTS] <column>
ALTER TABLE <table> DROP CONSTRAINT [IF EXISTS] <constraint>

View File

@ -4335,7 +4335,7 @@ void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_COLLATION, executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_COLLATION,
name, NULL); name, NULL);
} }
else else if (!silent)
status_exception::raise(Arg::Gds(isc_dyn_collation_not_found) << Arg::Str(name)); status_exception::raise(Arg::Gds(isc_dyn_collation_not_found) << Arg::Str(name));
savePoint.release(); // everything is ok savePoint.release(); // everything is ok
@ -5406,7 +5406,7 @@ void DropDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_DOMAIN, executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_DOMAIN,
name, NULL); name, NULL);
} }
else else if (!silent)
{ {
// msg 89: "Domain not found" // msg 89: "Domain not found"
status_exception::raise(Arg::PrivateDyn(89)); status_exception::raise(Arg::PrivateDyn(89));
@ -6236,7 +6236,7 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
// done by code and system triggers. See the functional description of // done by code and system triggers. See the functional description of
// deleteKeyConstraint function for detail. // deleteKeyConstraint function for detail.
void RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction, void RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
const MetaName& relationName, const MetaName& fieldName) const MetaName& relationName, const MetaName& fieldName, bool silent)
{ {
AutoCacheRequest request(tdbb, drq_l_dep_flds, DYN_REQUESTS); AutoCacheRequest request(tdbb, drq_l_dep_flds, DYN_REQUESTS);
bool found = false; bool found = false;
@ -6358,7 +6358,7 @@ void RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
} }
END_FOR END_FOR
if (!found) if (!found && !silent)
{ {
// msg 176: "column %s does not exist in table/view %s" // msg 176: "column %s does not exist in table/view %s"
status_exception::raise(Arg::PrivateDyn(176) << fieldName << relationName); status_exception::raise(Arg::PrivateDyn(176) << fieldName << relationName);
@ -7828,7 +7828,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
Arg::Gds(isc_dsql_construct_err)); Arg::Gds(isc_dsql_construct_err));
} }
deleteLocalField(tdbb, transaction, name, clause->name); deleteLocalField(tdbb, transaction, name, clause->name, clause->silent);
break; break;
} }
@ -7840,8 +7840,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
case Clause::TYPE_DROP_CONSTRAINT: case Clause::TYPE_DROP_CONSTRAINT:
{ {
CreateDropConstraint& dropConstraint = constraints.add(); CreateDropConstraint& dropConstraint = constraints.add();
dropConstraint.name = dropConstraint.name = static_cast<const DropConstraintClause*>(i->getObject())->name;
static_cast<const DropConstraintClause*>(i->getObject())->name; dropConstraint.silent = static_cast<const DropConstraintClause*>(i->getObject())->silent;
break; break;
} }
@ -7933,7 +7933,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
} }
END_FOR END_FOR
if (!found) if (!found && !constraint->silent)
{ {
// msg 130: "CONSTRAINT %s does not exist." // msg 130: "CONSTRAINT %s does not exist."
status_exception::raise(Arg::PrivateDyn(130) << constraint->name); status_exception::raise(Arg::PrivateDyn(130) << constraint->name);
@ -9222,7 +9222,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
for (dsql_fld* relField = modifyingView->rel_fields; relField; relField = relField->fld_next) for (dsql_fld* relField = modifyingView->rel_fields; relField; relField = relField->fld_next)
{ {
if (!modifiedFields.exist(relField)) if (!modifiedFields.exist(relField))
deleteLocalField(tdbb, transaction, name, relField->fld_name); deleteLocalField(tdbb, transaction, name, relField->fld_name, false);
} }
} }
@ -10154,7 +10154,7 @@ void DropIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, j
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_INDEX, executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_INDEX,
name, NULL); name, NULL);
} }
else else if (!silent)
{ {
// msg 48: "Index not found" // msg 48: "Index not found"
status_exception::raise(Arg::PrivateDyn(48)); status_exception::raise(Arg::PrivateDyn(48));
@ -10283,7 +10283,7 @@ void DropFilterNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch
} }
END_FOR END_FOR
if (!found) if (!found && !silent)
{ {
// msg 37: "Blob Filter %s not found" // msg 37: "Blob Filter %s not found"
status_exception::raise(Arg::PrivateDyn(37) << name); status_exception::raise(Arg::PrivateDyn(37) << name);
@ -10990,19 +10990,24 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
break; break;
case MAP_MOD: case MAP_MOD:
case MAP_DROP:
case MAP_COMMENT: case MAP_COMMENT:
if (!found) if (!found)
(Arg::Gds(isc_map_not_exists) << name).raise(); (Arg::Gds(isc_map_not_exists) << name).raise();
break; break;
case MAP_DROP:
if (!found && !silentDrop)
(Arg::Gds(isc_map_not_exists) << name).raise();
break;
} }
fb_assert(ddlTriggerAction > 0 || op == MAP_COMMENT); fb_assert(ddlTriggerAction > 0 || op == MAP_COMMENT || (op == MAP_DROP && silentDrop));
if (ddlTriggerAction > 0) if (ddlTriggerAction > 0)
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL); executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL);
if (op != MAP_COMMENT) if (op != MAP_COMMENT)
DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::MAPPING_CACHE); DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::MAPPING_CACHE);
savePoint.release(); // everything is ok savePoint.release(); // everything is ok
} }
@ -11083,7 +11088,7 @@ void DropRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jr
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_ROLE, executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_ROLE,
name, NULL); name, NULL);
} }
else else if (!silent)
{ {
// msg 155: "Role %s not found" // msg 155: "Role %s not found"
status_exception::raise(Arg::PrivateDyn(155) << name); status_exception::raise(Arg::PrivateDyn(155) << name);

View File

@ -918,6 +918,7 @@ protected:
public: public:
MetaName name; MetaName name;
bool silent = false;
}; };
@ -1025,6 +1026,7 @@ private:
public: public:
MetaName name; MetaName name;
bool silent = false;
}; };
@ -1301,6 +1303,7 @@ public:
MetaName name; MetaName name;
Firebird::AutoPtr<Constraint> create; Firebird::AutoPtr<Constraint> create;
bool silent = false;
}; };
struct Clause struct Clause
@ -1484,13 +1487,13 @@ public:
{ {
explicit DropColumnClause(MemoryPool& p) explicit DropColumnClause(MemoryPool& p)
: Clause(p, TYPE_DROP_COLUMN), : Clause(p, TYPE_DROP_COLUMN),
name(p), name(p)
cascade(false)
{ {
} }
MetaName name; MetaName name;
bool cascade; bool cascade = false;
bool silent = false;
}; };
struct DropConstraintClause : public Clause struct DropConstraintClause : public Clause
@ -1502,12 +1505,13 @@ public:
} }
MetaName name; MetaName name;
bool silent = false;
}; };
RelationNode(MemoryPool& p, RelationSourceNode* aDsqlNode); RelationNode(MemoryPool& p, RelationSourceNode* aDsqlNode);
static void deleteLocalField(thread_db* tdbb, jrd_tra* transaction, static void deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
const MetaName& relationName, const MetaName& fieldName); const MetaName& relationName, const MetaName& fieldName, bool silent);
static void addToPublication(thread_db* tdbb, jrd_tra* transaction, static void addToPublication(thread_db* tdbb, jrd_tra* transaction,
const MetaName& tableName, const MetaName& pubTame); const MetaName& tableName, const MetaName& pubTame);
@ -1858,6 +1862,7 @@ protected:
public: public:
MetaName name; MetaName name;
bool silent = false;
}; };
@ -1946,6 +1951,7 @@ protected:
public: public:
MetaName name; MetaName name;
bool silent = false;
}; };
@ -2081,16 +2087,7 @@ public:
: DdlNode(p), : DdlNode(p),
name(p, nm), name(p, nm),
fromUtf8(p), fromUtf8(p),
plugin(NULL), op(o)
db(NULL),
fromType(NULL),
from(NULL),
to(NULL),
comment(NULL),
op(o),
mode('#'),
global(false),
role(false)
{ {
} }
@ -2117,16 +2114,17 @@ private:
public: public:
MetaName name; MetaName name;
Firebird::string fromUtf8; Firebird::string fromUtf8;
MetaName* plugin; MetaName* plugin = nullptr;
MetaName* db; MetaName* db = nullptr;
MetaName* fromType; MetaName* fromType = nullptr;
IntlString* from; IntlString* from = nullptr;
MetaName* to; MetaName* to = nullptr;
Firebird::string* comment; Firebird::string* comment = nullptr;
OP op; OP op;
char mode; // * - any source, P - plugin, M - mapping, S - any serverwide plugin char mode = '#'; // * - any source, P - plugin, M - mapping, S - any serverwide plugin
bool global; bool global = false;
bool role; bool role = false;
bool silentDrop = false;
}; };
@ -2152,6 +2150,7 @@ protected:
public: public:
MetaName name; MetaName name;
bool silent = false;
}; };

View File

@ -1 +1 @@
71 shift/reduce conflicts, 22 reduce/reduce conflicts. 94 shift/reduce conflicts, 22 reduce/reduce conflicts.

View File

@ -4249,17 +4249,19 @@ alter_ops($relationNode)
%type alter_op(<relationNode>) %type alter_op(<relationNode>)
alter_op($relationNode) alter_op($relationNode)
: DROP symbol_column_name drop_behaviour : DROP if_exists_opt symbol_column_name drop_behaviour
{ {
RelationNode::DropColumnClause* clause = newNode<RelationNode::DropColumnClause>(); RelationNode::DropColumnClause* clause = newNode<RelationNode::DropColumnClause>();
clause->name = *$2; clause->silent = $2;
clause->cascade = $3; clause->name = *$3;
clause->cascade = $4;
$relationNode->clauses.add(clause); $relationNode->clauses.add(clause);
} }
| DROP CONSTRAINT symbol_constraint_name | DROP CONSTRAINT if_exists_opt symbol_constraint_name
{ {
RelationNode::DropConstraintClause* clause = newNode<RelationNode::DropConstraintClause>(); RelationNode::DropConstraintClause* clause = newNode<RelationNode::DropConstraintClause>();
clause->name = *$3; clause->silent = $3;
clause->name = *$4;
$relationNode->clauses.add(clause); $relationNode->clauses.add(clause);
} }
| ADD column_def($relationNode) | ADD column_def($relationNode)
@ -4775,48 +4777,138 @@ drop
%type <ddlNode> drop_clause %type <ddlNode> drop_clause
drop_clause drop_clause
: EXCEPTION symbol_exception_name : EXCEPTION if_exists_opt symbol_exception_name
{ $$ = newNode<DropExceptionNode>(*$2); } {
| INDEX symbol_index_name const auto node = newNode<DropExceptionNode>(*$3);
{ $$ = newNode<DropIndexNode>(*$2); } node->silent = $2;
| PROCEDURE symbol_procedure_name $$ = node;
{ $$ = newNode<DropProcedureNode>(*$2); } }
| TABLE symbol_table_name | INDEX if_exists_opt symbol_index_name
{ $$ = newNode<DropRelationNode>(*$2, false); } {
| TRIGGER symbol_trigger_name const auto node = newNode<DropIndexNode>(*$3);
{ $$ = newNode<DropTriggerNode>(*$2); } node->silent = $2;
| VIEW symbol_view_name $$ = node;
{ $$ = newNode<DropRelationNode>(*$2, true); } }
| FILTER symbol_filter_name | PROCEDURE if_exists_opt symbol_procedure_name
{ $$ = newNode<DropFilterNode>(*$2); } {
| DOMAIN symbol_domain_name const auto node = newNode<DropProcedureNode>(*$3);
{ $$ = newNode<DropDomainNode>(*$2); } node->silent = $2;
| EXTERNAL FUNCTION symbol_UDF_name $$ = node;
{ $$ = newNode<DropFunctionNode>(*$3); } }
| FUNCTION symbol_UDF_name | TABLE if_exists_opt symbol_table_name
{ $$ = newNode<DropFunctionNode>(*$2); } {
| SHADOW pos_short_integer opt_no_file_delete const auto node = newNode<DropRelationNode>(*$3, false);
{ $$ = newNode<DropShadowNode>($2, $3); } node->silent = $2;
| ROLE symbol_role_name $$ = node;
{ $$ = newNode<DropRoleNode>(*$2); } }
| GENERATOR symbol_generator_name | TRIGGER if_exists_opt symbol_trigger_name
{ $$ = newNode<DropSequenceNode>(*$2); } {
| SEQUENCE symbol_generator_name const auto node = newNode<DropTriggerNode>(*$3);
{ $$ = newNode<DropSequenceNode>(*$2); } node->silent = $2;
| COLLATION symbol_collation_name $$ = node;
{ $$ = newNode<DropCollationNode>(*$2); } }
| USER symbol_user_name USING PLUGIN valid_symbol_name | VIEW if_exists_opt symbol_view_name
{ $$ = newNode<DropUserNode>(*$2, $5); } {
| USER symbol_user_name const auto node = newNode<DropRelationNode>(*$3, true);
{ $$ = newNode<DropUserNode>(*$2); } node->silent = $2;
| PACKAGE symbol_package_name $$ = node;
{ $$ = newNode<DropPackageNode>(*$2); } }
| PACKAGE BODY symbol_package_name | FILTER if_exists_opt symbol_filter_name
{ $$ = newNode<DropPackageBodyNode>(*$3); } {
| MAPPING drop_map_clause(false) const auto node = newNode<DropFilterNode>(*$3);
{ $$ = $2; } node->silent = $2;
| GLOBAL MAPPING drop_map_clause(true) $$ = node;
{ $$ = $3; } }
| DOMAIN if_exists_opt symbol_domain_name
{
const auto node = newNode<DropDomainNode>(*$3);
node->silent = $2;
$$ = node;
}
| EXTERNAL FUNCTION if_exists_opt symbol_UDF_name
{
const auto node = newNode<DropFunctionNode>(*$4);
node->silent = $3;
$$ = node;
}
| FUNCTION if_exists_opt symbol_UDF_name
{
const auto node = newNode<DropFunctionNode>(*$3);
node->silent = $2;
$$ = node;
}
| SHADOW if_exists_opt pos_short_integer opt_no_file_delete
{
const auto node = newNode<DropShadowNode>($3, $4);
// DROP SHADOW implicitly has IF EXISTS behavior
$$ = node;
}
| ROLE if_exists_opt symbol_role_name
{
const auto node = newNode<DropRoleNode>(*$3);
node->silent = $2;
$$ = node;
}
| GENERATOR if_exists_opt symbol_generator_name
{
const auto node = newNode<DropSequenceNode>(*$3);
node->silent = $2;
$$ = node;
}
| SEQUENCE if_exists_opt symbol_generator_name
{
const auto node = newNode<DropSequenceNode>(*$3);
node->silent = $2;
$$ = node;
}
| COLLATION if_exists_opt symbol_collation_name
{
const auto node = newNode<DropCollationNode>(*$3);
node->silent = $2;
$$ = node;
}
| USER if_exists_opt symbol_user_name USING PLUGIN valid_symbol_name
{
const auto node = newNode<DropUserNode>(*$3, $6);
node->silent = $2;
$$ = node;
}
| USER if_exists_opt symbol_user_name
{
const auto node = newNode<DropUserNode>(*$3);
node->silent = $2;
$$ = node;
}
| PACKAGE if_exists_opt symbol_package_name
{
const auto node = newNode<DropPackageNode>(*$3);
node->silent = $2;
$$ = node;
}
| PACKAGE BODY if_exists_opt symbol_package_name
{
const auto node = newNode<DropPackageBodyNode>(*$4);
node->silent = $3;
$$ = node;
}
| MAPPING if_exists_opt drop_map_clause(false)
{
const auto node = $3;
node->silentDrop = $2;
$$ = node;
}
| GLOBAL MAPPING if_exists_opt drop_map_clause(true)
{
const auto node = $4;
node->silentDrop = $3;
$$ = node;
}
;
%type <boolVal> if_exists_opt
if_exists_opt
: /* nothing */ { $$ = false; }
| IF EXISTS { $$ = true; }
; ;
%type <boolVal> opt_no_file_delete %type <boolVal> opt_no_file_delete