mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 17:23:03 +01:00
parent
2f444071a1
commit
77ee904255
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
71 shift/reduce conflicts, 22 reduce/reduce conflicts.
|
||||
94 shift/reduce conflicts, 22 reduce/reduce conflicts.
|
||||
|
186
src/dsql/parse.y
186
src/dsql/parse.y
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user