8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 18:03: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)
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,
name, NULL);
}
else
else if (!silent)
status_exception::raise(Arg::Gds(isc_dyn_collation_not_found) << Arg::Str(name));
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,
name, NULL);
}
else
else if (!silent)
{
// msg 89: "Domain not found"
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
// deleteKeyConstraint function for detail.
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);
bool found = false;
@ -6358,7 +6358,7 @@ void RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
}
END_FOR
if (!found)
if (!found && !silent)
{
// msg 176: "column %s does not exist in table/view %s"
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));
}
deleteLocalField(tdbb, transaction, name, clause->name);
deleteLocalField(tdbb, transaction, name, clause->name, clause->silent);
break;
}
@ -7840,8 +7840,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
case Clause::TYPE_DROP_CONSTRAINT:
{
CreateDropConstraint& dropConstraint = constraints.add();
dropConstraint.name =
static_cast<const DropConstraintClause*>(i->getObject())->name;
dropConstraint.name = static_cast<const DropConstraintClause*>(i->getObject())->name;
dropConstraint.silent = static_cast<const DropConstraintClause*>(i->getObject())->silent;
break;
}
@ -7933,7 +7933,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
}
END_FOR
if (!found)
if (!found && !constraint->silent)
{
// msg 130: "CONSTRAINT %s does not exist."
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)
{
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,
name, NULL);
}
else
else if (!silent)
{
// msg 48: "Index not found"
status_exception::raise(Arg::PrivateDyn(48));
@ -10283,7 +10283,7 @@ void DropFilterNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch
}
END_FOR
if (!found)
if (!found && !silent)
{
// msg 37: "Blob Filter %s not found"
status_exception::raise(Arg::PrivateDyn(37) << name);
@ -10990,19 +10990,24 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
break;
case MAP_MOD:
case MAP_DROP:
case MAP_COMMENT:
if (!found)
(Arg::Gds(isc_map_not_exists) << name).raise();
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)
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL);
if (op != MAP_COMMENT)
DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::MAPPING_CACHE);
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,
name, NULL);
}
else
else if (!silent)
{
// msg 155: "Role %s not found"
status_exception::raise(Arg::PrivateDyn(155) << name);

View File

@ -918,6 +918,7 @@ protected:
public:
MetaName name;
bool silent = false;
};
@ -1025,6 +1026,7 @@ private:
public:
MetaName name;
bool silent = false;
};
@ -1301,6 +1303,7 @@ public:
MetaName name;
Firebird::AutoPtr<Constraint> create;
bool silent = false;
};
struct Clause
@ -1484,13 +1487,13 @@ public:
{
explicit DropColumnClause(MemoryPool& p)
: Clause(p, TYPE_DROP_COLUMN),
name(p),
cascade(false)
name(p)
{
}
MetaName name;
bool cascade;
bool cascade = false;
bool silent = false;
};
struct DropConstraintClause : public Clause
@ -1502,12 +1505,13 @@ public:
}
MetaName name;
bool silent = false;
};
RelationNode(MemoryPool& p, RelationSourceNode* aDsqlNode);
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,
const MetaName& tableName, const MetaName& pubTame);
@ -1858,6 +1862,7 @@ protected:
public:
MetaName name;
bool silent = false;
};
@ -1946,6 +1951,7 @@ protected:
public:
MetaName name;
bool silent = false;
};
@ -2081,16 +2087,7 @@ public:
: DdlNode(p),
name(p, nm),
fromUtf8(p),
plugin(NULL),
db(NULL),
fromType(NULL),
from(NULL),
to(NULL),
comment(NULL),
op(o),
mode('#'),
global(false),
role(false)
op(o)
{
}
@ -2117,16 +2114,17 @@ private:
public:
MetaName name;
Firebird::string fromUtf8;
MetaName* plugin;
MetaName* db;
MetaName* fromType;
IntlString* from;
MetaName* to;
Firebird::string* comment;
MetaName* plugin = nullptr;
MetaName* db = nullptr;
MetaName* fromType = nullptr;
IntlString* from = nullptr;
MetaName* to = nullptr;
Firebird::string* comment = nullptr;
OP op;
char mode; // * - any source, P - plugin, M - mapping, S - any serverwide plugin
bool global;
bool role;
char mode = '#'; // * - any source, P - plugin, M - mapping, S - any serverwide plugin
bool global = false;
bool role = false;
bool silentDrop = false;
};
@ -2152,6 +2150,7 @@ protected:
public:
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>)
alter_op($relationNode)
: DROP symbol_column_name drop_behaviour
: DROP if_exists_opt symbol_column_name drop_behaviour
{
RelationNode::DropColumnClause* clause = newNode<RelationNode::DropColumnClause>();
clause->name = *$2;
clause->cascade = $3;
clause->silent = $2;
clause->name = *$3;
clause->cascade = $4;
$relationNode->clauses.add(clause);
}
| DROP CONSTRAINT symbol_constraint_name
| DROP CONSTRAINT if_exists_opt symbol_constraint_name
{
RelationNode::DropConstraintClause* clause = newNode<RelationNode::DropConstraintClause>();
clause->name = *$3;
clause->silent = $3;
clause->name = *$4;
$relationNode->clauses.add(clause);
}
| ADD column_def($relationNode)
@ -4775,48 +4777,138 @@ drop
%type <ddlNode> drop_clause
drop_clause
: EXCEPTION symbol_exception_name
{ $$ = newNode<DropExceptionNode>(*$2); }
| INDEX symbol_index_name
{ $$ = newNode<DropIndexNode>(*$2); }
| PROCEDURE symbol_procedure_name
{ $$ = newNode<DropProcedureNode>(*$2); }
| TABLE symbol_table_name
{ $$ = newNode<DropRelationNode>(*$2, false); }
| TRIGGER symbol_trigger_name
{ $$ = newNode<DropTriggerNode>(*$2); }
| VIEW symbol_view_name
{ $$ = newNode<DropRelationNode>(*$2, true); }
| FILTER symbol_filter_name
{ $$ = newNode<DropFilterNode>(*$2); }
| DOMAIN symbol_domain_name
{ $$ = newNode<DropDomainNode>(*$2); }
| EXTERNAL FUNCTION symbol_UDF_name
{ $$ = newNode<DropFunctionNode>(*$3); }
| FUNCTION symbol_UDF_name
{ $$ = newNode<DropFunctionNode>(*$2); }
| SHADOW pos_short_integer opt_no_file_delete
{ $$ = newNode<DropShadowNode>($2, $3); }
| ROLE symbol_role_name
{ $$ = newNode<DropRoleNode>(*$2); }
| GENERATOR symbol_generator_name
{ $$ = newNode<DropSequenceNode>(*$2); }
| SEQUENCE symbol_generator_name
{ $$ = newNode<DropSequenceNode>(*$2); }
| COLLATION symbol_collation_name
{ $$ = newNode<DropCollationNode>(*$2); }
| USER symbol_user_name USING PLUGIN valid_symbol_name
{ $$ = newNode<DropUserNode>(*$2, $5); }
| USER symbol_user_name
{ $$ = newNode<DropUserNode>(*$2); }
| PACKAGE symbol_package_name
{ $$ = newNode<DropPackageNode>(*$2); }
| PACKAGE BODY symbol_package_name
{ $$ = newNode<DropPackageBodyNode>(*$3); }
| MAPPING drop_map_clause(false)
{ $$ = $2; }
| GLOBAL MAPPING drop_map_clause(true)
{ $$ = $3; }
: EXCEPTION if_exists_opt symbol_exception_name
{
const auto node = newNode<DropExceptionNode>(*$3);
node->silent = $2;
$$ = node;
}
| INDEX if_exists_opt symbol_index_name
{
const auto node = newNode<DropIndexNode>(*$3);
node->silent = $2;
$$ = node;
}
| PROCEDURE if_exists_opt symbol_procedure_name
{
const auto node = newNode<DropProcedureNode>(*$3);
node->silent = $2;
$$ = node;
}
| TABLE if_exists_opt symbol_table_name
{
const auto node = newNode<DropRelationNode>(*$3, false);
node->silent = $2;
$$ = node;
}
| TRIGGER if_exists_opt symbol_trigger_name
{
const auto node = newNode<DropTriggerNode>(*$3);
node->silent = $2;
$$ = node;
}
| VIEW if_exists_opt symbol_view_name
{
const auto node = newNode<DropRelationNode>(*$3, true);
node->silent = $2;
$$ = node;
}
| FILTER if_exists_opt symbol_filter_name
{
const auto node = newNode<DropFilterNode>(*$3);
node->silent = $2;
$$ = node;
}
| 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