mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:03:02 +01:00
parent
aaf5fafac6
commit
b6eab891d5
@ -664,5 +664,43 @@ DROP USER [IF EXISTS] <user> [USING PLUGIN <plugin>]
|
|||||||
DROP PACKAGE [IF EXISTS] <package>
|
DROP PACKAGE [IF EXISTS] <package>
|
||||||
DROP PACKAGE BODY [IF EXISTS] <package>
|
DROP PACKAGE BODY [IF EXISTS] <package>
|
||||||
DROP [GLOBAL] MAPPING [IF EXISTS] <mapping>
|
DROP [GLOBAL] MAPPING [IF EXISTS] <mapping>
|
||||||
ALTER TABLE <table> DROP [IF EXISTS] <column>
|
ALTER TABLE <table> DROP [IF EXISTS] <column name>
|
||||||
ALTER TABLE <table> DROP CONSTRAINT [IF EXISTS] <constraint>
|
ALTER TABLE <table> DROP CONSTRAINT [IF EXISTS] <constraint name>
|
||||||
|
|
||||||
|
2) CREATE [IF NOT EXISTS]
|
||||||
|
|
||||||
|
Using subclause IF NOT EXISTS, it's now possible to try to create objects and do not get errors when they
|
||||||
|
already exists.
|
||||||
|
|
||||||
|
For ALTER TABLE ... ADD subclause, DDL triggers are not fired if there are only IF NOT EXISTS subclauses and all
|
||||||
|
of them are related to existing columns or constraints.
|
||||||
|
|
||||||
|
For others commands where IF NOT EXISTS is part of the main command, DDL triggers are not fired when the object
|
||||||
|
already exists.
|
||||||
|
|
||||||
|
The engine only verifies if the name (object, column or constraint) already exists, and if yes, do nothing.
|
||||||
|
It never tries to match the existing object with the one being created.
|
||||||
|
|
||||||
|
The following statements are supported:
|
||||||
|
|
||||||
|
CREATE EXCEPTION [IF NOT EXISTS] ...
|
||||||
|
CREATE INDEX [IF NOT EXISTS] ...
|
||||||
|
CREATE PROCEDURE [IF NOT EXISTS] ...
|
||||||
|
CREATE TABLE [IF NOT EXISTS] ...
|
||||||
|
CREATE TRIGGER [IF NOT EXISTS] ...
|
||||||
|
CREATE VIEW [IF NOT EXISTS] ...
|
||||||
|
CREATE FILTER [IF NOT EXISTS] ...
|
||||||
|
CREATE DOMAIN [IF NOT EXISTS] ...
|
||||||
|
CREATE FUNCTION [IF NOT EXISTS] ...
|
||||||
|
DECLARE EXTERNAL FUNCTION [IF NOT EXISTS] ...
|
||||||
|
CREATE SHADOW [IF NOT EXISTS] ...
|
||||||
|
CREATE ROLE [IF NOT EXISTS] ...
|
||||||
|
CREATE GENERATOR [IF NOT EXISTS] ...
|
||||||
|
CREATE SEQUENCE [IF NOT EXISTS] ...
|
||||||
|
CREATE COLLATION [IF NOT EXISTS] ...
|
||||||
|
CREATE USER [IF NOT EXISTS] ...
|
||||||
|
CREATE PACKAGE [IF NOT EXISTS] ...
|
||||||
|
CREATE PACKAGE BODY [IF NOT EXISTS] ...
|
||||||
|
CREATE [GLOBAL] MAPPING [IF NOT EXISTS] ...
|
||||||
|
ALTER TABLE <table> ADD [IF NOT EXISTS] <column name> ...
|
||||||
|
ALTER TABLE <table> ADD CONSTRAINT [IF NOT EXISTS] <constraint name> ...
|
||||||
|
@ -220,6 +220,7 @@ public:
|
|||||||
unsigned int op;
|
unsigned int op;
|
||||||
int trustedAuth;
|
int trustedAuth;
|
||||||
bool silent;
|
bool silent;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
CharField user, pass, first, last, middle, com, attr;
|
CharField user, pass, first, last, middle, com, attr;
|
||||||
IntField adm, act;
|
IntField adm, act;
|
||||||
CharField database, dba, dbaPassword, role;
|
CharField database, dba, dbaPassword, role;
|
||||||
|
@ -1789,6 +1789,9 @@ void CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
|
|||||||
|
|
||||||
if (package.isEmpty())
|
if (package.isEmpty())
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_udf))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||||
DDL_TRIGGER_CREATE_FUNCTION, name, NULL);
|
DDL_TRIGGER_CREATE_FUNCTION, name, NULL);
|
||||||
|
|
||||||
@ -2804,6 +2807,9 @@ void CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
|
|||||||
|
|
||||||
if (package.isEmpty())
|
if (package.isEmpty())
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_procedure))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||||
DDL_TRIGGER_CREATE_PROCEDURE, name, NULL);
|
DDL_TRIGGER_CREATE_PROCEDURE, name, NULL);
|
||||||
|
|
||||||
@ -3724,9 +3730,14 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
|
|||||||
void CreateAlterTriggerNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
void CreateAlterTriggerNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||||
jrd_tra* transaction)
|
jrd_tra* transaction)
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_trigger))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_TRIGGER,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_TRIGGER,
|
||||||
name, NULL);
|
name, NULL);
|
||||||
|
|
||||||
|
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_trigger);
|
||||||
|
|
||||||
store(tdbb, dsqlScratch, transaction);
|
store(tdbb, dsqlScratch, transaction);
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_TRIGGER,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_TRIGGER,
|
||||||
@ -4010,9 +4021,14 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
|||||||
// run all statements under savepoint control
|
// run all statements under savepoint control
|
||||||
AutoSavePoint savePoint(tdbb, transaction);
|
AutoSavePoint savePoint(tdbb, transaction);
|
||||||
|
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_collation))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||||
DDL_TRIGGER_CREATE_COLLATION, name, NULL);
|
DDL_TRIGGER_CREATE_COLLATION, name, NULL);
|
||||||
|
|
||||||
|
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_collation);
|
||||||
|
|
||||||
AutoCacheRequest request(tdbb, drq_s_colls, DYN_REQUESTS);
|
AutoCacheRequest request(tdbb, drq_s_colls, DYN_REQUESTS);
|
||||||
|
|
||||||
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
@ -4400,9 +4416,14 @@ void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
|||||||
// run all statements under savepoint control
|
// run all statements under savepoint control
|
||||||
AutoSavePoint savePoint(tdbb, transaction);
|
AutoSavePoint savePoint(tdbb, transaction);
|
||||||
|
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, nameType->name, obj_field))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||||
DDL_TRIGGER_CREATE_DOMAIN, nameType->name, NULL);
|
DDL_TRIGGER_CREATE_DOMAIN, nameType->name, NULL);
|
||||||
|
|
||||||
|
DYN_UTIL_check_unique_name(tdbb, transaction, nameType->name, obj_field);
|
||||||
|
|
||||||
storeGlobalField(tdbb, transaction, nameType->name, type);
|
storeGlobalField(tdbb, transaction, nameType->name, type);
|
||||||
|
|
||||||
if (nameType->defaultClause || check || notNull)
|
if (nameType->defaultClause || check || notNull)
|
||||||
@ -5539,6 +5560,9 @@ void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
|
|||||||
Attachment* const attachment = transaction->getAttachment();
|
Attachment* const attachment = transaction->getAttachment();
|
||||||
const MetaString& ownerName = attachment->getEffectiveUserName();
|
const MetaString& ownerName = attachment->getEffectiveUserName();
|
||||||
|
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_exception))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||||
DDL_TRIGGER_CREATE_EXCEPTION, name, NULL);
|
DDL_TRIGGER_CREATE_EXCEPTION, name, NULL);
|
||||||
|
|
||||||
@ -5766,9 +5790,14 @@ void CreateAlterSequenceNode::putErrorPrefix(Firebird::Arg::StatusVector& status
|
|||||||
void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||||
jrd_tra* transaction)
|
jrd_tra* transaction)
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_generator))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE,
|
||||||
name, NULL);
|
name, NULL);
|
||||||
|
|
||||||
|
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_generator);
|
||||||
|
|
||||||
const SINT64 val = value.value_or(1);
|
const SINT64 val = value.value_or(1);
|
||||||
SLONG initialStep = 1;
|
SLONG initialStep = 1;
|
||||||
if (step.has_value())
|
if (step.has_value())
|
||||||
@ -5777,6 +5806,7 @@ void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
|
|||||||
if (initialStep == 0)
|
if (initialStep == 0)
|
||||||
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
|
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
store(tdbb, transaction, name, fb_sysflag_user, val, initialStep);
|
store(tdbb, transaction, name, fb_sysflag_user, val, initialStep);
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE,
|
||||||
@ -6398,11 +6428,25 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
|||||||
const ObjectsArray<MetaName>* pkCols)
|
const ObjectsArray<MetaName>* pkCols)
|
||||||
{
|
{
|
||||||
dsql_fld* field = clause->field;
|
dsql_fld* field = clause->field;
|
||||||
|
dsql_rel* relation = dsqlScratch->relation;
|
||||||
|
|
||||||
|
if (clause->createIfNotExistsOnly)
|
||||||
|
{
|
||||||
|
AutoCacheRequest request(tdbb, drq_l_rel_fld_name, DYN_REQUESTS);
|
||||||
|
|
||||||
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
|
RFL IN RDB$RELATION_FIELDS
|
||||||
|
WITH RFL.RDB$RELATION_NAME = relation->rel_name.c_str() AND
|
||||||
|
RFL.RDB$FIELD_NAME = field->fld_name.c_str()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
END_FOR
|
||||||
|
}
|
||||||
|
|
||||||
// Add the field to the relation being defined for parsing purposes.
|
// Add the field to the relation being defined for parsing purposes.
|
||||||
|
|
||||||
bool permanent = false;
|
bool permanent = false;
|
||||||
dsql_rel* relation = dsqlScratch->relation;
|
|
||||||
if (relation != NULL)
|
if (relation != NULL)
|
||||||
{
|
{
|
||||||
if (!(relation->rel_flags & REL_new_relation))
|
if (!(relation->rel_flags & REL_new_relation))
|
||||||
@ -6596,12 +6640,26 @@ bool RelationNode::defineDefault(thread_db* /*tdbb*/, DsqlCompilerScratch* dsqlS
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make a constraint object from a legacy node.
|
// Make a constraint object from a legacy node.
|
||||||
void RelationNode::makeConstraint(thread_db* /*tdbb*/, DsqlCompilerScratch* dsqlScratch,
|
void RelationNode::makeConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||||
jrd_tra* transaction, AddConstraintClause* clause,
|
jrd_tra* transaction, AddConstraintClause* clause,
|
||||||
ObjectsArray<CreateDropConstraint>& constraints, bool* notNull)
|
ObjectsArray<CreateDropConstraint>& constraints, bool* notNull)
|
||||||
{
|
{
|
||||||
MemoryPool& pool = dsqlScratch->getPool();
|
MemoryPool& pool = dsqlScratch->getPool();
|
||||||
|
|
||||||
|
if (clause->createIfNotExistsOnly)
|
||||||
|
{
|
||||||
|
AutoCacheRequest request(tdbb, drq_l_rel_con, DYN_REQUESTS);
|
||||||
|
|
||||||
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
|
RC IN RDB$RELATION_CONSTRAINTS
|
||||||
|
WITH RC.RDB$CONSTRAINT_NAME EQ clause->name.c_str() AND
|
||||||
|
RC.RDB$RELATION_NAME EQ name.c_str()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
END_FOR
|
||||||
|
}
|
||||||
|
|
||||||
switch (clause->constraintType)
|
switch (clause->constraintType)
|
||||||
{
|
{
|
||||||
case AddConstraintClause::CTYPE_NOT_NULL:
|
case AddConstraintClause::CTYPE_NOT_NULL:
|
||||||
@ -7474,6 +7532,9 @@ void CreateRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
|||||||
void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||||
jrd_tra* transaction)
|
jrd_tra* transaction)
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_relation))
|
||||||
|
return;
|
||||||
|
|
||||||
saveRelation(tdbb, dsqlScratch, name, false, true);
|
saveRelation(tdbb, dsqlScratch, name, false, true);
|
||||||
|
|
||||||
if (externalFile)
|
if (externalFile)
|
||||||
@ -8790,6 +8851,9 @@ void CreateAlterViewNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
|||||||
void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||||
jrd_tra* transaction)
|
jrd_tra* transaction)
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_relation))
|
||||||
|
return;
|
||||||
|
|
||||||
Attachment* const attachment = transaction->tra_attachment;
|
Attachment* const attachment = transaction->tra_attachment;
|
||||||
const MetaString& ownerName = attachment->getEffectiveUserName();
|
const MetaString& ownerName = attachment->getEffectiveUserName();
|
||||||
|
|
||||||
@ -9962,6 +10026,9 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
|||||||
// run all statements under savepoint control
|
// run all statements under savepoint control
|
||||||
AutoSavePoint savePoint(tdbb, transaction);
|
AutoSavePoint savePoint(tdbb, transaction);
|
||||||
|
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_index))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_INDEX,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_INDEX,
|
||||||
name, NULL);
|
name, NULL);
|
||||||
|
|
||||||
@ -10402,6 +10469,9 @@ void CreateShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
|
|||||||
FIRST 1 X IN RDB$FILES
|
FIRST 1 X IN RDB$FILES
|
||||||
WITH X.RDB$SHADOW_NUMBER EQ number
|
WITH X.RDB$SHADOW_NUMBER EQ number
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly)
|
||||||
|
return;
|
||||||
|
|
||||||
// msg 165: "Shadow %ld already exists"
|
// msg 165: "Shadow %ld already exists"
|
||||||
status_exception::raise(Arg::PrivateDyn(165) << Arg::Num(number));
|
status_exception::raise(Arg::PrivateDyn(165) << Arg::Num(number));
|
||||||
}
|
}
|
||||||
@ -10522,6 +10592,10 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
|||||||
|
|
||||||
// run all statements under savepoint control
|
// run all statements under savepoint control
|
||||||
AutoSavePoint savePoint(tdbb, transaction);
|
AutoSavePoint savePoint(tdbb, transaction);
|
||||||
|
MetaName dummyName;
|
||||||
|
|
||||||
|
if (createIfNotExistsOnly && isItSqlRole(tdbb, transaction, name, dummyName))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||||
createFlag ? DDL_TRIGGER_CREATE_ROLE : DDL_TRIGGER_ALTER_ROLE, name, NULL);
|
createFlag ? DDL_TRIGGER_CREATE_ROLE : DDL_TRIGGER_ALTER_ROLE, name, NULL);
|
||||||
@ -10544,7 +10618,6 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
|||||||
status_exception::raise(Arg::PrivateDyn(193) << name);
|
status_exception::raise(Arg::PrivateDyn(193) << name);
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaName dummyName;
|
|
||||||
if (createFlag && isItSqlRole(tdbb, transaction, name, dummyName))
|
if (createFlag && isItSqlRole(tdbb, transaction, name, dummyName))
|
||||||
{
|
{
|
||||||
// msg 194: "SQL role @1 already exists"
|
// msg 194: "SQL role @1 already exists"
|
||||||
@ -10701,6 +10774,8 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
|
|||||||
{
|
{
|
||||||
case MAP_ADD:
|
case MAP_ADD:
|
||||||
ddl = "CREATE MAPPING ";
|
ddl = "CREATE MAPPING ";
|
||||||
|
if (createIfNotExistsOnly)
|
||||||
|
ddl += "IF NOT EXISTS ";
|
||||||
break;
|
break;
|
||||||
case MAP_MOD:
|
case MAP_MOD:
|
||||||
ddl = "ALTER MAPPING ";
|
ddl = "ALTER MAPPING ";
|
||||||
@ -11014,6 +11089,8 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
|
|||||||
case MAP_ADD:
|
case MAP_ADD:
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly)
|
||||||
|
return;
|
||||||
(Arg::Gds(isc_map_already_exists) << name).raise();
|
(Arg::Gds(isc_map_already_exists) << name).raise();
|
||||||
}
|
}
|
||||||
// fall through ...
|
// fall through ...
|
||||||
@ -11261,6 +11338,8 @@ void CreateAlterUserNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
|||||||
(Arg::Gds(isc_random) << "Missing user name for ALTER CURRENT USER").raise();
|
(Arg::Gds(isc_random) << "Missing user name for ALTER CURRENT USER").raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userData->createIfNotExistsOnly = createIfNotExistsOnly;
|
||||||
|
|
||||||
Firebird::LocalStatus s;
|
Firebird::LocalStatus s;
|
||||||
CheckStatusWrapper statusWrapper(&s);
|
CheckStatusWrapper statusWrapper(&s);
|
||||||
|
|
||||||
|
@ -475,6 +475,7 @@ public:
|
|||||||
MetaName name;
|
MetaName name;
|
||||||
bool create;
|
bool create;
|
||||||
bool alter;
|
bool alter;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
NestConst<ExternalClause> external;
|
NestConst<ExternalClause> external;
|
||||||
Firebird::TriState deterministic;
|
Firebird::TriState deterministic;
|
||||||
Firebird::Array<NestConst<ParameterClause> > parameters;
|
Firebird::Array<NestConst<ParameterClause> > parameters;
|
||||||
@ -614,6 +615,7 @@ public:
|
|||||||
MetaName name;
|
MetaName name;
|
||||||
bool create;
|
bool create;
|
||||||
bool alter;
|
bool alter;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
NestConst<ExternalClause> external;
|
NestConst<ExternalClause> external;
|
||||||
Firebird::Array<NestConst<ParameterClause> > parameters;
|
Firebird::Array<NestConst<ParameterClause> > parameters;
|
||||||
Firebird::Array<NestConst<ParameterClause> > returns;
|
Firebird::Array<NestConst<ParameterClause> > returns;
|
||||||
@ -789,6 +791,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
bool create;
|
bool create;
|
||||||
bool alter;
|
bool alter;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
NestConst<LocalDeclarationsNode> localDeclList;
|
NestConst<LocalDeclarationsNode> localDeclList;
|
||||||
NestConst<StmtNode> body;
|
NestConst<StmtNode> body;
|
||||||
bool compiled;
|
bool compiled;
|
||||||
@ -888,6 +891,7 @@ public:
|
|||||||
MetaName fromName;
|
MetaName fromName;
|
||||||
Firebird::string fromExternal;
|
Firebird::string fromExternal;
|
||||||
Firebird::UCharBuffer specificAttributes;
|
Firebird::UCharBuffer specificAttributes;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
USHORT attributesOn;
|
USHORT attributesOn;
|
||||||
@ -949,6 +953,7 @@ public:
|
|||||||
NestConst<ParameterClause> nameType;
|
NestConst<ParameterClause> nameType;
|
||||||
bool notNull;
|
bool notNull;
|
||||||
NestConst<BoolSourceClause> check;
|
NestConst<BoolSourceClause> check;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1068,6 +1073,7 @@ public:
|
|||||||
Firebird::string message;
|
Firebird::string message;
|
||||||
bool create;
|
bool create;
|
||||||
bool alter;
|
bool alter;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1152,6 +1158,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
bool create;
|
bool create;
|
||||||
bool alter;
|
bool alter;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
bool legacy;
|
bool legacy;
|
||||||
bool restartSpecified;
|
bool restartSpecified;
|
||||||
const MetaName name;
|
const MetaName name;
|
||||||
@ -1380,6 +1387,7 @@ public:
|
|||||||
Firebird::ObjectsArray<MetaName> refColumns;
|
Firebird::ObjectsArray<MetaName> refColumns;
|
||||||
NestConst<RefActionClause> refAction;
|
NestConst<RefActionClause> refAction;
|
||||||
NestConst<BoolSourceClause> check;
|
NestConst<BoolSourceClause> check;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IdentityOptions
|
struct IdentityOptions
|
||||||
@ -1422,6 +1430,7 @@ public:
|
|||||||
NestConst<ValueSourceClause> computed;
|
NestConst<ValueSourceClause> computed;
|
||||||
NestConst<IdentityOptions> identityOptions;
|
NestConst<IdentityOptions> identityOptions;
|
||||||
bool notNullSpecified;
|
bool notNullSpecified;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AlterColNameClause : public Clause
|
struct AlterColNameClause : public Clause
|
||||||
@ -1596,6 +1605,7 @@ public:
|
|||||||
std::optional<rel_t> relationType = rel_persistent;
|
std::optional<rel_t> relationType = rel_persistent;
|
||||||
bool preserveRowsOpt;
|
bool preserveRowsOpt;
|
||||||
bool deleteRowsOpt;
|
bool deleteRowsOpt;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1699,6 +1709,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
bool create;
|
bool create;
|
||||||
bool alter;
|
bool alter;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
NestConst<ValueListNode> viewFields;
|
NestConst<ValueListNode> viewFields;
|
||||||
NestConst<SelectExprNode> selectExpr;
|
NestConst<SelectExprNode> selectExpr;
|
||||||
Firebird::string source;
|
Firebird::string source;
|
||||||
@ -1783,6 +1794,7 @@ public:
|
|||||||
NestConst<ValueListNode> columns;
|
NestConst<ValueListNode> columns;
|
||||||
NestConst<ValueSourceClause> computed;
|
NestConst<ValueSourceClause> computed;
|
||||||
NestConst<BoolSourceClause> partial;
|
NestConst<BoolSourceClause> partial;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1990,6 +2002,7 @@ public:
|
|||||||
bool manual;
|
bool manual;
|
||||||
bool conditional;
|
bool conditional;
|
||||||
Firebird::Array<NestConst<DbFileClause> > files;
|
Firebird::Array<NestConst<DbFileClause> > files;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2067,7 +2080,9 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
MetaName name;
|
MetaName name;
|
||||||
bool createFlag, sysPrivDrop;
|
bool createFlag;
|
||||||
|
bool sysPrivDrop;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
|
|
||||||
void addPrivilege(const MetaName* privName)
|
void addPrivilege(const MetaName* privName)
|
||||||
{
|
{
|
||||||
@ -2127,6 +2142,7 @@ public:
|
|||||||
bool global = false;
|
bool global = false;
|
||||||
bool role = false;
|
bool role = false;
|
||||||
bool silentDrop = false;
|
bool silentDrop = false;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2226,6 +2242,7 @@ public:
|
|||||||
Firebird::TriState adminRole;
|
Firebird::TriState adminRole;
|
||||||
Firebird::TriState active;
|
Firebird::TriState active;
|
||||||
Mode mode;
|
Mode mode;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
|
|
||||||
void addProperty(MetaName* pr, Firebird::string* val = NULL)
|
void addProperty(MetaName* pr, Firebird::string* val = NULL)
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "../jrd/jrd.h"
|
#include "../jrd/jrd.h"
|
||||||
#include "../jrd/tra.h"
|
#include "../jrd/tra.h"
|
||||||
#include "../jrd/dfw_proto.h"
|
#include "../jrd/dfw_proto.h"
|
||||||
|
#include "../jrd/dyn_ut_proto.h"
|
||||||
#include "../jrd/exe_proto.h"
|
#include "../jrd/exe_proto.h"
|
||||||
#include "../jrd/met_proto.h"
|
#include "../jrd/met_proto.h"
|
||||||
#include "../jrd/vio_proto.h"
|
#include "../jrd/vio_proto.h"
|
||||||
@ -363,9 +364,14 @@ void CreateAlterPackageNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch*
|
|||||||
Attachment* const attachment = transaction->getAttachment();
|
Attachment* const attachment = transaction->getAttachment();
|
||||||
const MetaString& ownerName = attachment->getEffectiveUserName();
|
const MetaString& ownerName = attachment->getEffectiveUserName();
|
||||||
|
|
||||||
|
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_package_header))
|
||||||
|
return;
|
||||||
|
|
||||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||||
DDL_TRIGGER_CREATE_PACKAGE, name, NULL);
|
DDL_TRIGGER_CREATE_PACKAGE, name, NULL);
|
||||||
|
|
||||||
|
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_package_header);
|
||||||
|
|
||||||
AutoCacheRequest requestHandle(tdbb, drq_s_pkg, DYN_REQUESTS);
|
AutoCacheRequest requestHandle(tdbb, drq_s_pkg, DYN_REQUESTS);
|
||||||
|
|
||||||
STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
|
STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
|
||||||
@ -789,6 +795,9 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
|
|||||||
{
|
{
|
||||||
if (!PKG.RDB$VALID_BODY_FLAG.NULL && PKG.RDB$VALID_BODY_FLAG != 0)
|
if (!PKG.RDB$VALID_BODY_FLAG.NULL && PKG.RDB$VALID_BODY_FLAG != 0)
|
||||||
{
|
{
|
||||||
|
if (createIfNotExistsOnly)
|
||||||
|
return;
|
||||||
|
|
||||||
status_exception::raise(
|
status_exception::raise(
|
||||||
Arg::Gds(isc_no_meta_update) <<
|
Arg::Gds(isc_no_meta_update) <<
|
||||||
Arg::Gds(isc_dyn_package_body_exists) << Arg::Str(name));
|
Arg::Gds(isc_dyn_package_body_exists) << Arg::Str(name));
|
||||||
|
@ -107,6 +107,7 @@ public:
|
|||||||
MetaName name;
|
MetaName name;
|
||||||
bool create;
|
bool create;
|
||||||
bool alter;
|
bool alter;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
Firebird::string source;
|
Firebird::string source;
|
||||||
Firebird::Array<Item>* items;
|
Firebird::Array<Item>* items;
|
||||||
Firebird::SortedArray<MetaName> functionNames;
|
Firebird::SortedArray<MetaName> functionNames;
|
||||||
@ -179,6 +180,7 @@ public:
|
|||||||
Firebird::string source;
|
Firebird::string source;
|
||||||
Firebird::Array<CreateAlterPackageNode::Item>* declaredItems;
|
Firebird::Array<CreateAlterPackageNode::Item>* declaredItems;
|
||||||
Firebird::Array<CreateAlterPackageNode::Item>* items;
|
Firebird::Array<CreateAlterPackageNode::Item>* items;
|
||||||
|
bool createIfNotExistsOnly = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Firebird::string owner;
|
Firebird::string owner;
|
||||||
|
@ -1 +1 @@
|
|||||||
94 shift/reduce conflicts, 22 reduce/reduce conflicts.
|
115 shift/reduce conflicts, 22 reduce/reduce conflicts.
|
||||||
|
186
src/dsql/parse.y
186
src/dsql/parse.y
@ -822,6 +822,7 @@ using namespace Firebird;
|
|||||||
Jrd::ValueSourceClause* valueSourceClause;
|
Jrd::ValueSourceClause* valueSourceClause;
|
||||||
Jrd::RelationNode* relationNode;
|
Jrd::RelationNode* relationNode;
|
||||||
Jrd::RelationNode::AddColumnClause* addColumnClause;
|
Jrd::RelationNode::AddColumnClause* addColumnClause;
|
||||||
|
Jrd::RelationNode::AddConstraintClause* addConstraintClause;
|
||||||
Jrd::RelationNode::RefActionClause* refActionClause;
|
Jrd::RelationNode::RefActionClause* refActionClause;
|
||||||
Jrd::RelationNode::IndexConstraintClause* indexConstraintClause;
|
Jrd::RelationNode::IndexConstraintClause* indexConstraintClause;
|
||||||
Jrd::RelationNode::IdentityOptions* identityOptions;
|
Jrd::RelationNode::IdentityOptions* identityOptions;
|
||||||
@ -1406,7 +1407,12 @@ declare
|
|||||||
%type <ddlNode> declare_clause
|
%type <ddlNode> declare_clause
|
||||||
declare_clause
|
declare_clause
|
||||||
: FILTER filter_decl_clause { $$ = $2; }
|
: FILTER filter_decl_clause { $$ = $2; }
|
||||||
| EXTERNAL FUNCTION udf_decl_clause { $$ = $3; }
|
| EXTERNAL FUNCTION if_not_exists_opt udf_decl_clause
|
||||||
|
{
|
||||||
|
const auto node = $4;
|
||||||
|
node->createIfNotExistsOnly = $3;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
%type <createAlterFunctionNode> udf_decl_clause
|
%type <createAlterFunctionNode> udf_decl_clause
|
||||||
@ -1534,37 +1540,129 @@ create
|
|||||||
|
|
||||||
%type <ddlNode> create_clause
|
%type <ddlNode> create_clause
|
||||||
create_clause
|
create_clause
|
||||||
: EXCEPTION exception_clause { $$ = $2; }
|
: EXCEPTION if_not_exists_opt exception_clause
|
||||||
| unique_opt order_direction INDEX symbol_index_name ON simple_table_name
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| unique_opt order_direction INDEX if_not_exists_opt symbol_index_name ON simple_table_name
|
||||||
{
|
{
|
||||||
CreateIndexNode* node = newNode<CreateIndexNode>(*$4);
|
const auto node = newNode<CreateIndexNode>(*$5);
|
||||||
node->unique = $1;
|
node->unique = $1;
|
||||||
node->descending = $2;
|
node->descending = $2;
|
||||||
node->relation = $6;
|
node->createIfNotExistsOnly = $4;
|
||||||
|
node->relation = $7;
|
||||||
$$ = node;
|
$$ = node;
|
||||||
}
|
}
|
||||||
index_definition(static_cast<CreateIndexNode*>($7))
|
index_definition(static_cast<CreateIndexNode*>($8))
|
||||||
{
|
{
|
||||||
$$ = $7;
|
$$ = $8;
|
||||||
}
|
}
|
||||||
| FUNCTION function_clause { $$ = $2; }
|
| FUNCTION if_not_exists_opt function_clause
|
||||||
| PROCEDURE procedure_clause { $$ = $2; }
|
{
|
||||||
| TABLE table_clause { $$ = $2; }
|
const auto node = $3;
|
||||||
| GLOBAL TEMPORARY TABLE gtt_table_clause { $$ = $4; }
|
node->createIfNotExistsOnly = $2;
|
||||||
| TRIGGER trigger_clause { $$ = $2; }
|
$$ = node;
|
||||||
| VIEW view_clause { $$ = $2; }
|
}
|
||||||
| GENERATOR generator_clause { $$ = $2; }
|
| PROCEDURE if_not_exists_opt procedure_clause
|
||||||
| SEQUENCE generator_clause { $$ = $2; }
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| TABLE if_not_exists_opt table_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| GLOBAL TEMPORARY TABLE if_not_exists_opt gtt_table_clause
|
||||||
|
{
|
||||||
|
const auto node = $5;
|
||||||
|
node->createIfNotExistsOnly = $4;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| TRIGGER if_not_exists_opt trigger_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| VIEW if_not_exists_opt view_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| GENERATOR if_not_exists_opt generator_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| SEQUENCE if_not_exists_opt generator_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
| DATABASE db_clause { $$ = $2; }
|
| DATABASE db_clause { $$ = $2; }
|
||||||
| DOMAIN domain_clause { $$ = $2; }
|
| DOMAIN if_not_exists_opt domain_clause
|
||||||
| SHADOW shadow_clause { $$ = $2; }
|
{
|
||||||
| ROLE role_clause { $2->createFlag = true; $$ = $2; }
|
const auto node = $3;
|
||||||
| COLLATION collation_clause { $$ = $2; }
|
node->createIfNotExistsOnly = $2;
|
||||||
| USER create_user_clause { $$ = $2; }
|
$$ = node;
|
||||||
| PACKAGE package_clause { $$ = $2; }
|
}
|
||||||
| PACKAGE BODY package_body_clause { $$ = $3; }
|
| SHADOW if_not_exists_opt shadow_clause
|
||||||
| MAPPING create_map_clause(false) { $$ = $2; }
|
{
|
||||||
| GLOBAL MAPPING create_map_clause(true) { $$ = $3; }
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| ROLE if_not_exists_opt role_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
node->createFlag = true;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| COLLATION if_not_exists_opt collation_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| USER if_not_exists_opt create_user_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| PACKAGE if_not_exists_opt package_clause
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| PACKAGE BODY if_not_exists_opt package_body_clause
|
||||||
|
{
|
||||||
|
const auto node = $4;
|
||||||
|
node->createIfNotExistsOnly = $3;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| MAPPING if_not_exists_opt create_map_clause(false)
|
||||||
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
|
| GLOBAL MAPPING if_not_exists_opt create_map_clause(true)
|
||||||
|
{
|
||||||
|
const auto node = $4;
|
||||||
|
node->createIfNotExistsOnly = $3;
|
||||||
|
$$ = node;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@ -2345,7 +2443,7 @@ table_element($createRelationNode)
|
|||||||
|
|
||||||
// column definition
|
// column definition
|
||||||
|
|
||||||
%type column_def(<relationNode>)
|
%type <addColumnClause> column_def(<relationNode>)
|
||||||
column_def($relationNode)
|
column_def($relationNode)
|
||||||
: symbol_column_name data_type_or_domain domain_default_opt
|
: symbol_column_name data_type_or_domain domain_default_opt
|
||||||
{
|
{
|
||||||
@ -2359,6 +2457,7 @@ column_def($relationNode)
|
|||||||
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
|
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
|
||||||
{
|
{
|
||||||
setCollate($2, $6);
|
setCollate($2, $6);
|
||||||
|
$$ = $<addColumnClause>4;
|
||||||
}
|
}
|
||||||
| symbol_column_name data_type_or_domain identity_clause
|
| symbol_column_name data_type_or_domain identity_clause
|
||||||
{
|
{
|
||||||
@ -2372,6 +2471,7 @@ column_def($relationNode)
|
|||||||
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
|
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
|
||||||
{
|
{
|
||||||
setCollate($2, $6);
|
setCollate($2, $6);
|
||||||
|
$$ = $<addColumnClause>4;
|
||||||
}
|
}
|
||||||
| symbol_column_name non_array_type def_computed
|
| symbol_column_name non_array_type def_computed
|
||||||
{
|
{
|
||||||
@ -2381,6 +2481,7 @@ column_def($relationNode)
|
|||||||
clause->computed = $3;
|
clause->computed = $3;
|
||||||
$relationNode->clauses.add(clause);
|
$relationNode->clauses.add(clause);
|
||||||
clause->field->flags |= FLD_computed;
|
clause->field->flags |= FLD_computed;
|
||||||
|
$$ = clause;
|
||||||
}
|
}
|
||||||
| symbol_column_name def_computed
|
| symbol_column_name def_computed
|
||||||
{
|
{
|
||||||
@ -2390,6 +2491,7 @@ column_def($relationNode)
|
|||||||
clause->computed = $2;
|
clause->computed = $2;
|
||||||
$relationNode->clauses.add(clause);
|
$relationNode->clauses.add(clause);
|
||||||
clause->field->flags |= FLD_computed;
|
clause->field->flags |= FLD_computed;
|
||||||
|
$$ = clause;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -2577,15 +2679,13 @@ column_constraint($addColumnClause)
|
|||||||
|
|
||||||
// table constraints
|
// table constraints
|
||||||
|
|
||||||
%type table_constraint_definition(<relationNode>)
|
%type <addConstraintClause> table_constraint_definition(<relationNode>)
|
||||||
table_constraint_definition($relationNode)
|
table_constraint_definition($relationNode)
|
||||||
: constraint_name_opt table_constraint($relationNode)
|
: constraint_name_opt table_constraint($relationNode)
|
||||||
{
|
{
|
||||||
if ($1)
|
if ($1)
|
||||||
{
|
$2->name = *$1;
|
||||||
static_cast<RelationNode::AddConstraintClause*>(
|
$$ = $2;
|
||||||
$relationNode->clauses.back().getObject())->name = *$1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -2595,7 +2695,7 @@ constraint_name_opt
|
|||||||
| CONSTRAINT symbol_constraint_name { $$ = $2; }
|
| CONSTRAINT symbol_constraint_name { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%type table_constraint(<relationNode>)
|
%type <addConstraintClause> table_constraint(<relationNode>)
|
||||||
table_constraint($relationNode)
|
table_constraint($relationNode)
|
||||||
: UNIQUE column_parens constraint_index_opt
|
: UNIQUE column_parens constraint_index_opt
|
||||||
{
|
{
|
||||||
@ -2611,6 +2711,7 @@ table_constraint($relationNode)
|
|||||||
constraint.index = $3;
|
constraint.index = $3;
|
||||||
|
|
||||||
$relationNode->clauses.add(&constraint);
|
$relationNode->clauses.add(&constraint);
|
||||||
|
$$ = &constraint;
|
||||||
}
|
}
|
||||||
| PRIMARY KEY column_parens constraint_index_opt
|
| PRIMARY KEY column_parens constraint_index_opt
|
||||||
{
|
{
|
||||||
@ -2626,6 +2727,7 @@ table_constraint($relationNode)
|
|||||||
constraint.index = $4;
|
constraint.index = $4;
|
||||||
|
|
||||||
$relationNode->clauses.add(&constraint);
|
$relationNode->clauses.add(&constraint);
|
||||||
|
$$ = &constraint;
|
||||||
}
|
}
|
||||||
| FOREIGN KEY column_parens REFERENCES symbol_table_name column_parens_opt
|
| FOREIGN KEY column_parens REFERENCES symbol_table_name column_parens_opt
|
||||||
referential_trigger_action constraint_index_opt
|
referential_trigger_action constraint_index_opt
|
||||||
@ -2654,6 +2756,7 @@ table_constraint($relationNode)
|
|||||||
constraint.index = $8;
|
constraint.index = $8;
|
||||||
|
|
||||||
$relationNode->clauses.add(&constraint);
|
$relationNode->clauses.add(&constraint);
|
||||||
|
$$ = &constraint;
|
||||||
}
|
}
|
||||||
| check_constraint
|
| check_constraint
|
||||||
{
|
{
|
||||||
@ -2661,6 +2764,7 @@ table_constraint($relationNode)
|
|||||||
constraint->constraintType = RelationNode::AddConstraintClause::CTYPE_CHECK;
|
constraint->constraintType = RelationNode::AddConstraintClause::CTYPE_CHECK;
|
||||||
constraint->check = $1;
|
constraint->check = $1;
|
||||||
$relationNode->clauses.add(constraint);
|
$relationNode->clauses.add(constraint);
|
||||||
|
$$ = constraint;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -4267,8 +4371,18 @@ alter_op($relationNode)
|
|||||||
clause->name = *$4;
|
clause->name = *$4;
|
||||||
$relationNode->clauses.add(clause);
|
$relationNode->clauses.add(clause);
|
||||||
}
|
}
|
||||||
| ADD column_def($relationNode)
|
| ADD if_not_exists_opt column_def($relationNode)
|
||||||
| ADD table_constraint_definition($relationNode)
|
{
|
||||||
|
const auto node = $3;
|
||||||
|
node->createIfNotExistsOnly = $2;
|
||||||
|
}
|
||||||
|
| ADD table_constraint($relationNode)
|
||||||
|
| ADD CONSTRAINT if_not_exists_opt symbol_constraint_name table_constraint($relationNode)
|
||||||
|
{
|
||||||
|
const auto node = $5;
|
||||||
|
node->name = *$4;
|
||||||
|
node->createIfNotExistsOnly = $3;
|
||||||
|
}
|
||||||
| col_opt alter_column_name POSITION pos_short_integer
|
| col_opt alter_column_name POSITION pos_short_integer
|
||||||
{
|
{
|
||||||
RelationNode::AlterColPosClause* clause = newNode<RelationNode::AlterColPosClause>();
|
RelationNode::AlterColPosClause* clause = newNode<RelationNode::AlterColPosClause>();
|
||||||
@ -4917,6 +5031,12 @@ if_exists_opt
|
|||||||
| IF EXISTS { $$ = true; }
|
| IF EXISTS { $$ = true; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
%type <boolVal> if_not_exists_opt
|
||||||
|
if_not_exists_opt
|
||||||
|
: /* nothing */ { $$ = false; }
|
||||||
|
| IF NOT EXISTS { $$ = true; }
|
||||||
|
;
|
||||||
|
|
||||||
%type <boolVal> opt_no_file_delete
|
%type <boolVal> opt_no_file_delete
|
||||||
opt_no_file_delete
|
opt_no_file_delete
|
||||||
: /* nothing */ { $$ = false; }
|
: /* nothing */ { $$ = false; }
|
||||||
|
@ -299,3 +299,7 @@ FB_IMPL_MSG(DYN, 306, dyn_rel_not_exist, -901, "42", "000", "Table @1 does not e
|
|||||||
FB_IMPL_MSG(DYN, 307, dyn_exc_not_exist, -901, "42", "000", "Exception @1 does not exist")
|
FB_IMPL_MSG(DYN, 307, dyn_exc_not_exist, -901, "42", "000", "Exception @1 does not exist")
|
||||||
FB_IMPL_MSG(DYN, 308, dyn_gen_not_exist, -901, "42", "000", "Generator/Sequence @1 does not exist")
|
FB_IMPL_MSG(DYN, 308, dyn_gen_not_exist, -901, "42", "000", "Generator/Sequence @1 does not exist")
|
||||||
FB_IMPL_MSG(DYN, 309, dyn_fld_not_exist, -901, "42", "000", "Field @1 of table @2 does not exist")
|
FB_IMPL_MSG(DYN, 309, dyn_fld_not_exist, -901, "42", "000", "Field @1 of table @2 does not exist")
|
||||||
|
FB_IMPL_MSG_SYMBOL(DYN, 310, dyn_dup_trigger, "Trigger @1 already exists")
|
||||||
|
FB_IMPL_MSG_SYMBOL(DYN, 311, dyn_dup_domain, "Domain @1 already exists")
|
||||||
|
FB_IMPL_MSG_SYMBOL(DYN, 312, dyn_dup_collation, "Collation @1 already exists")
|
||||||
|
FB_IMPL_MSG_SYMBOL(DYN, 313, dyn_dup_package, "Package @1 already exists")
|
||||||
|
@ -482,8 +482,13 @@ void UserManagement::execute(USHORT id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int errcode = manager->execute(&statusWrapper, command, NULL);
|
int errcode = manager->execute(&statusWrapper, command, NULL);
|
||||||
if (!command->silent)
|
|
||||||
|
if (!command->silent &&
|
||||||
|
!(command->createIfNotExistsOnly &&
|
||||||
|
fb_utils::containsErrorCode(status.getErrors(), isc_unique_key_violation)))
|
||||||
|
{
|
||||||
checkSecurityResult(errcode, &status, command->userName()->get(), command->operation());
|
checkSecurityResult(errcode, &status, command->userName()->get(), command->operation());
|
||||||
|
}
|
||||||
|
|
||||||
delete commands[id];
|
delete commands[id];
|
||||||
commands[id] = NULL;
|
commands[id] = NULL;
|
||||||
|
@ -249,6 +249,12 @@ enum drq_type_t
|
|||||||
drq_l_pub_rel_name, // lookup relation by name
|
drq_l_pub_rel_name, // lookup relation by name
|
||||||
drq_l_pub_all_rels, // iterate through all user relations
|
drq_l_pub_all_rels, // iterate through all user relations
|
||||||
drq_e_pub_tab_all, // erase relation from all publication
|
drq_e_pub_tab_all, // erase relation from all publication
|
||||||
|
drq_l_trg_name, // lookup trigger name
|
||||||
|
drq_l_fld_name, // lookup field name
|
||||||
|
drq_l_coll_name, // lookup collation name
|
||||||
|
drq_l_pkg_name, // lookup package name
|
||||||
|
drq_l_rel_con, // lookup relation constraint
|
||||||
|
drq_l_rel_fld_name, // lookup relation field name
|
||||||
|
|
||||||
drq_MAX
|
drq_MAX
|
||||||
};
|
};
|
||||||
|
@ -37,6 +37,8 @@ void DYN_UTIL_generate_field_position(Jrd::thread_db*, const Jrd::MetaName&, SLO
|
|||||||
void DYN_UTIL_generate_field_name(Jrd::thread_db*, TEXT*);
|
void DYN_UTIL_generate_field_name(Jrd::thread_db*, TEXT*);
|
||||||
void DYN_UTIL_generate_field_name(Jrd::thread_db*, Jrd::MetaName&);
|
void DYN_UTIL_generate_field_name(Jrd::thread_db*, Jrd::MetaName&);
|
||||||
void DYN_UTIL_generate_constraint_name(Jrd::thread_db*, Jrd::MetaName&);
|
void DYN_UTIL_generate_constraint_name(Jrd::thread_db*, Jrd::MetaName&);
|
||||||
|
bool DYN_UTIL_check_unique_name_nothrow(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction,
|
||||||
|
const Jrd::MetaName& object_name, int object_type, USHORT* errorCode = nullptr);
|
||||||
void DYN_UTIL_check_unique_name(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction,
|
void DYN_UTIL_check_unique_name(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction,
|
||||||
const Jrd::MetaName& object_name, int object_type);
|
const Jrd::MetaName& object_name, int object_type);
|
||||||
SINT64 DYN_UTIL_gen_unique_id(Jrd::thread_db*, SSHORT, const char*);
|
SINT64 DYN_UTIL_gen_unique_id(Jrd::thread_db*, SSHORT, const char*);
|
||||||
|
@ -78,23 +78,16 @@ static const UCHAR gen_id_blr2[] =
|
|||||||
blr_parameter, 0, 0, 0, blr_end, blr_end, blr_end, blr_eoc
|
blr_parameter, 0, 0, 0, blr_end, blr_end, blr_end, blr_eoc
|
||||||
};
|
};
|
||||||
|
|
||||||
void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
// Check if an object already exists. If yes, return false.
|
||||||
const MetaName& object_name, int object_type)
|
bool DYN_UTIL_check_unique_name_nothrow(thread_db* tdbb, jrd_tra* transaction,
|
||||||
|
const MetaName& object_name, int object_type, USHORT* errorCode)
|
||||||
{
|
{
|
||||||
/**************************************
|
|
||||||
*
|
|
||||||
* D Y N _ U T I L _ c h e c k _ u n i q u e _ n a m e
|
|
||||||
*
|
|
||||||
**************************************
|
|
||||||
*
|
|
||||||
* Functional description
|
|
||||||
* Check if an object already exists.
|
|
||||||
* If yes then return error.
|
|
||||||
*
|
|
||||||
**************************************/
|
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
|
|
||||||
USHORT error_code = 0;
|
USHORT tempErrorCode;
|
||||||
|
errorCode = errorCode ? errorCode : &tempErrorCode;
|
||||||
|
*errorCode = 0;
|
||||||
|
|
||||||
AutoCacheRequest request;
|
AutoCacheRequest request;
|
||||||
|
|
||||||
switch (object_type)
|
switch (object_type)
|
||||||
@ -106,11 +99,11 @@ void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
EREL IN RDB$RELATIONS WITH EREL.RDB$RELATION_NAME EQ object_name.c_str()
|
EREL IN RDB$RELATIONS WITH EREL.RDB$RELATION_NAME EQ object_name.c_str()
|
||||||
{
|
{
|
||||||
error_code = 132;
|
*errorCode = 132;
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
if (!error_code)
|
if (!*errorCode)
|
||||||
{
|
{
|
||||||
request.reset(tdbb, drq_l_prc_name, DYN_REQUESTS);
|
request.reset(tdbb, drq_l_prc_name, DYN_REQUESTS);
|
||||||
|
|
||||||
@ -119,7 +112,7 @@ void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
WITH EPRC.RDB$PROCEDURE_NAME EQ object_name.c_str() AND
|
WITH EPRC.RDB$PROCEDURE_NAME EQ object_name.c_str() AND
|
||||||
EPRC.RDB$PACKAGE_NAME MISSING
|
EPRC.RDB$PACKAGE_NAME MISSING
|
||||||
{
|
{
|
||||||
error_code = 135;
|
*errorCode = 135;
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
}
|
}
|
||||||
@ -131,7 +124,7 @@ void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
EIDX IN RDB$INDICES WITH EIDX.RDB$INDEX_NAME EQ object_name.c_str()
|
EIDX IN RDB$INDICES WITH EIDX.RDB$INDEX_NAME EQ object_name.c_str()
|
||||||
{
|
{
|
||||||
error_code = 251;
|
*errorCode = 251;
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
@ -143,7 +136,7 @@ void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
EXCP IN RDB$EXCEPTIONS WITH EXCP.RDB$EXCEPTION_NAME EQ object_name.c_str()
|
EXCP IN RDB$EXCEPTIONS WITH EXCP.RDB$EXCEPTION_NAME EQ object_name.c_str()
|
||||||
{
|
{
|
||||||
error_code = 253;
|
*errorCode = 253;
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
@ -155,7 +148,7 @@ void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
EGEN IN RDB$GENERATORS WITH EGEN.RDB$GENERATOR_NAME EQ object_name.c_str()
|
EGEN IN RDB$GENERATORS WITH EGEN.RDB$GENERATOR_NAME EQ object_name.c_str()
|
||||||
{
|
{
|
||||||
error_code = 254;
|
*errorCode = 254;
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
@ -169,7 +162,59 @@ void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
WITH EFUN.RDB$FUNCTION_NAME EQ object_name.c_str() AND
|
WITH EFUN.RDB$FUNCTION_NAME EQ object_name.c_str() AND
|
||||||
EFUN.RDB$PACKAGE_NAME MISSING
|
EFUN.RDB$PACKAGE_NAME MISSING
|
||||||
{
|
{
|
||||||
error_code = 268;
|
*errorCode = 268;
|
||||||
|
}
|
||||||
|
END_FOR
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case obj_trigger:
|
||||||
|
request.reset(tdbb, drq_l_trg_name, DYN_REQUESTS);
|
||||||
|
|
||||||
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
|
TRG IN RDB$TRIGGERS
|
||||||
|
WITH TRG.RDB$TRIGGER_NAME EQ object_name.c_str()
|
||||||
|
{
|
||||||
|
*errorCode = 310;
|
||||||
|
}
|
||||||
|
END_FOR
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case obj_field:
|
||||||
|
request.reset(tdbb, drq_l_fld_name, DYN_REQUESTS);
|
||||||
|
|
||||||
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
|
FLD IN RDB$FIELDS
|
||||||
|
WITH FLD.RDB$FIELD_NAME EQ object_name.c_str()
|
||||||
|
{
|
||||||
|
*errorCode = 311;
|
||||||
|
}
|
||||||
|
END_FOR
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case obj_collation:
|
||||||
|
request.reset(tdbb, drq_l_coll_name, DYN_REQUESTS);
|
||||||
|
|
||||||
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
|
COLL IN RDB$COLLATIONS
|
||||||
|
WITH COLL.RDB$COLLATION_NAME EQ object_name.c_str()
|
||||||
|
{
|
||||||
|
*errorCode = 312;
|
||||||
|
}
|
||||||
|
END_FOR
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case obj_package_header:
|
||||||
|
request.reset(tdbb, drq_l_pkg_name, DYN_REQUESTS);
|
||||||
|
|
||||||
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||||
|
PKG IN RDB$PACKAGES
|
||||||
|
WITH PKG.RDB$PACKAGE_NAME EQ object_name.c_str()
|
||||||
|
{
|
||||||
|
*errorCode = 313;
|
||||||
}
|
}
|
||||||
END_FOR
|
END_FOR
|
||||||
|
|
||||||
@ -179,8 +224,16 @@ void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction,
|
|||||||
fb_assert(false);
|
fb_assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error_code)
|
return *errorCode == 0;
|
||||||
status_exception::raise(Arg::PrivateDyn(error_code) << object_name.c_str());
|
}
|
||||||
|
|
||||||
|
// Check if an object already exists. If yes, throw error.
|
||||||
|
void DYN_UTIL_check_unique_name(thread_db* tdbb, jrd_tra* transaction, const MetaName& object_name, int object_type)
|
||||||
|
{
|
||||||
|
USHORT errorCode;
|
||||||
|
|
||||||
|
if (!DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, object_name, object_type, &errorCode))
|
||||||
|
status_exception::raise(Arg::PrivateDyn(errorCode) << object_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user