@@ -1832,6 +1832,9 @@ void CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
1832
1832
1833
1833
if (package.isEmpty())
1834
1834
{
1835
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_udf))
1836
+ return;
1837
+
1835
1838
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
1836
1839
DDL_TRIGGER_CREATE_FUNCTION, name, NULL);
1837
1840
@@ -2847,6 +2850,9 @@ void CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
2847
2850
2848
2851
if (package.isEmpty())
2849
2852
{
2853
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_procedure))
2854
+ return;
2855
+
2850
2856
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
2851
2857
DDL_TRIGGER_CREATE_PROCEDURE, name, NULL);
2852
2858
@@ -3766,9 +3772,14 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
3766
3772
void CreateAlterTriggerNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
3767
3773
jrd_tra* transaction)
3768
3774
{
3775
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_trigger))
3776
+ return;
3777
+
3769
3778
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_TRIGGER,
3770
3779
name, NULL);
3771
3780
3781
+ DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_trigger);
3782
+
3772
3783
store(tdbb, dsqlScratch, transaction);
3773
3784
3774
3785
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_TRIGGER,
@@ -4052,9 +4063,14 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
4052
4063
// run all statements under savepoint control
4053
4064
AutoSavePoint savePoint(tdbb, transaction);
4054
4065
4066
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_collation))
4067
+ return;
4068
+
4055
4069
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
4056
4070
DDL_TRIGGER_CREATE_COLLATION, name, NULL);
4057
4071
4072
+ DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_collation);
4073
+
4058
4074
AutoCacheRequest request(tdbb, drq_s_colls, DYN_REQUESTS);
4059
4075
4060
4076
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
@@ -4442,9 +4458,14 @@ void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
4442
4458
// run all statements under savepoint control
4443
4459
AutoSavePoint savePoint(tdbb, transaction);
4444
4460
4461
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, nameType->name, obj_field))
4462
+ return;
4463
+
4445
4464
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
4446
4465
DDL_TRIGGER_CREATE_DOMAIN, nameType->name, NULL);
4447
4466
4467
+ DYN_UTIL_check_unique_name(tdbb, transaction, nameType->name, obj_field);
4468
+
4448
4469
storeGlobalField(tdbb, transaction, nameType->name, type);
4449
4470
4450
4471
if (nameType->defaultClause || check || notNull)
@@ -5581,6 +5602,9 @@ void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
5581
5602
Attachment* const attachment = transaction->getAttachment();
5582
5603
const MetaString& ownerName = attachment->getEffectiveUserName();
5583
5604
5605
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_exception))
5606
+ return;
5607
+
5584
5608
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
5585
5609
DDL_TRIGGER_CREATE_EXCEPTION, name, NULL);
5586
5610
@@ -5808,9 +5832,14 @@ void CreateAlterSequenceNode::putErrorPrefix(Firebird::Arg::StatusVector& status
5808
5832
void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
5809
5833
jrd_tra* transaction)
5810
5834
{
5835
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_generator))
5836
+ return;
5837
+
5811
5838
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE,
5812
5839
name, NULL);
5813
5840
5841
+ DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_generator);
5842
+
5814
5843
const SINT64 val = value.value_or(1);
5815
5844
SLONG initialStep = 1;
5816
5845
if (step.has_value())
@@ -5819,6 +5848,7 @@ void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
5819
5848
if (initialStep == 0)
5820
5849
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
5821
5850
}
5851
+
5822
5852
store(tdbb, transaction, name, fb_sysflag_user, val, initialStep);
5823
5853
5824
5854
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE,
@@ -6440,11 +6470,25 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
6440
6470
const ObjectsArray<MetaName>* pkCols)
6441
6471
{
6442
6472
dsql_fld* field = clause->field;
6473
+ dsql_rel* relation = dsqlScratch->relation;
6474
+
6475
+ if (clause->createIfNotExistsOnly)
6476
+ {
6477
+ AutoCacheRequest request(tdbb, drq_l_rel_fld_name, DYN_REQUESTS);
6478
+
6479
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
6480
+ RFL IN RDB$RELATION_FIELDS
6481
+ WITH RFL.RDB$RELATION_NAME = relation->rel_name.c_str() AND
6482
+ RFL.RDB$FIELD_NAME = field->fld_name.c_str()
6483
+ {
6484
+ return;
6485
+ }
6486
+ END_FOR
6487
+ }
6443
6488
6444
6489
// Add the field to the relation being defined for parsing purposes.
6445
6490
6446
6491
bool permanent = false;
6447
- dsql_rel* relation = dsqlScratch->relation;
6448
6492
if (relation != NULL)
6449
6493
{
6450
6494
if (!(relation->rel_flags & REL_new_relation))
@@ -6638,12 +6682,26 @@ bool RelationNode::defineDefault(thread_db* /*tdbb*/, DsqlCompilerScratch* dsqlS
6638
6682
}
6639
6683
6640
6684
// Make a constraint object from a legacy node.
6641
- void RelationNode::makeConstraint(thread_db* /* tdbb*/ , DsqlCompilerScratch* dsqlScratch,
6685
+ void RelationNode::makeConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
6642
6686
jrd_tra* transaction, AddConstraintClause* clause,
6643
6687
ObjectsArray<CreateDropConstraint>& constraints, bool* notNull)
6644
6688
{
6645
6689
MemoryPool& pool = dsqlScratch->getPool();
6646
6690
6691
+ if (clause->createIfNotExistsOnly)
6692
+ {
6693
+ AutoCacheRequest request(tdbb, drq_l_rel_con, DYN_REQUESTS);
6694
+
6695
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
6696
+ RC IN RDB$RELATION_CONSTRAINTS
6697
+ WITH RC.RDB$CONSTRAINT_NAME EQ clause->name.c_str() AND
6698
+ RC.RDB$RELATION_NAME EQ name.c_str()
6699
+ {
6700
+ return;
6701
+ }
6702
+ END_FOR
6703
+ }
6704
+
6647
6705
switch (clause->constraintType)
6648
6706
{
6649
6707
case AddConstraintClause::CTYPE_NOT_NULL:
@@ -7516,6 +7574,9 @@ void CreateRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
7516
7574
void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
7517
7575
jrd_tra* transaction)
7518
7576
{
7577
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_relation))
7578
+ return;
7579
+
7519
7580
saveRelation(tdbb, dsqlScratch, name, false, true);
7520
7581
7521
7582
if (externalFile)
@@ -8944,6 +9005,9 @@ void CreateAlterViewNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
8944
9005
void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
8945
9006
jrd_tra* transaction)
8946
9007
{
9008
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_relation))
9009
+ return;
9010
+
8947
9011
Attachment* const attachment = transaction->tra_attachment;
8948
9012
const MetaString& ownerName = attachment->getEffectiveUserName();
8949
9013
@@ -10116,6 +10180,9 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
10116
10180
// run all statements under savepoint control
10117
10181
AutoSavePoint savePoint(tdbb, transaction);
10118
10182
10183
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_index))
10184
+ return;
10185
+
10119
10186
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_INDEX,
10120
10187
name, NULL);
10121
10188
@@ -10558,6 +10625,9 @@ void CreateShadowNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
10558
10625
FIRST 1 X IN RDB$FILES
10559
10626
WITH X.RDB$SHADOW_NUMBER EQ number
10560
10627
{
10628
+ if (createIfNotExistsOnly)
10629
+ return;
10630
+
10561
10631
// msg 165: "Shadow %ld already exists"
10562
10632
status_exception::raise(Arg::PrivateDyn(165) << Arg::Num(number));
10563
10633
}
@@ -10678,6 +10748,10 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
10678
10748
10679
10749
// run all statements under savepoint control
10680
10750
AutoSavePoint savePoint(tdbb, transaction);
10751
+ MetaName dummyName;
10752
+
10753
+ if (createIfNotExistsOnly && isItSqlRole(tdbb, transaction, name, dummyName))
10754
+ return;
10681
10755
10682
10756
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
10683
10757
createFlag ? DDL_TRIGGER_CREATE_ROLE : DDL_TRIGGER_ALTER_ROLE, name, NULL);
@@ -10700,7 +10774,6 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
10700
10774
status_exception::raise(Arg::PrivateDyn(193) << name);
10701
10775
}
10702
10776
10703
- MetaName dummyName;
10704
10777
if (createFlag && isItSqlRole(tdbb, transaction, name, dummyName))
10705
10778
{
10706
10779
// msg 194: "SQL role @1 already exists"
@@ -10857,6 +10930,8 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
10857
10930
{
10858
10931
case MAP_ADD:
10859
10932
ddl = "CREATE MAPPING ";
10933
+ if (createIfNotExistsOnly)
10934
+ ddl += "IF NOT EXISTS ";
10860
10935
break;
10861
10936
case MAP_MOD:
10862
10937
ddl = "ALTER MAPPING ";
@@ -11170,6 +11245,8 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
11170
11245
case MAP_ADD:
11171
11246
if (found)
11172
11247
{
11248
+ if (createIfNotExistsOnly)
11249
+ return;
11173
11250
(Arg::Gds(isc_map_already_exists) << name).raise();
11174
11251
}
11175
11252
// fall through ...
@@ -11417,6 +11494,8 @@ void CreateAlterUserNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
11417
11494
(Arg::Gds(isc_random) << "Missing user name for ALTER CURRENT USER").raise();
11418
11495
}
11419
11496
11497
+ userData->createIfNotExistsOnly = createIfNotExistsOnly;
11498
+
11420
11499
Firebird::LocalStatus s;
11421
11500
CheckStatusWrapper statusWrapper(&s);
11422
11501
0 commit comments