Skip to content

Commit e26e3e5

Browse files
committed
Fix problem when CTAS uses NOT NULL domain in outer join context (nullable)
Thanks Pavel Zotov
1 parent ea687ea commit e26e3e5

2 files changed

Lines changed: 18 additions & 15 deletions

File tree

doc/sql.extensions/README.create_table_as_query.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ column's exact datatype instead of one derived only from the query's runtime res
2929
such as declared `NUMERIC`/`DECIMAL` precision).
3030

3131
* If the source column is based on a named domain, the new column references that domain directly, as if it had
32-
been declared `<column name> <domain name>`.
32+
been declared `<column name> <domain name>`. However, if the column appears in an outer join context
33+
where it is nullable and the domain is declared `NOT NULL`, the new column instead uses a copy of the
34+
domain's underlying type (preserving precision, scale, character set, collation, etc.) without
35+
referencing the original domain.
3336
* If the source column is based on an auto-generated (implicit) domain, its exact type (precision/scale, character
3437
set, collation, etc.) is copied.
3538

src/dsql/DdlNodes.epp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10084,23 +10084,23 @@ void CreateRelationNode::defineQueryColumns(thread_db* tdbb, DsqlCompilerScratch
1008410084
sourceField = sourceFieldNode->dsqlField;
1008510085
}
1008610086

10087-
if (sourceField && !fb_utils::implicit_domain(sourceField->fieldSource.object.c_str()))
10087+
if (sourceField)
10088+
{
10089+
METD_get_domain(dsqlScratch->getTransaction(), field, sourceField->fieldSource);
10090+
field->flags &= ~(FLD_computed | FLD_system);
10091+
}
10092+
10093+
if (sourceField &&
10094+
!fb_utils::implicit_domain(sourceField->fieldSource.object.c_str()) &&
10095+
!(!(field->flags & FLD_nullable) && (desc.dsc_flags & DSC_nullable)))
1008810096
{
1008910097
// Named domain: reference it directly, like "<field name> <domain name>".
1009010098
field->typeOfName = sourceField->fieldSource;
1009110099
field->fullDomain = true;
10092-
field->flags |= sourceField->flags & FLD_nullable;
1009310100
}
1009410101
else
1009510102
{
10096-
if (sourceField)
10097-
{
10098-
// Implicit domain: copy its exact stored type (precision, charset, collation,
10099-
// dimensions, etc.) instead of sharing the domain object itself.
10100-
METD_get_domain(dsqlScratch->getTransaction(), field, sourceField->fieldSource);
10101-
field->flags &= ~(FLD_computed | FLD_system);
10102-
}
10103-
else
10103+
if (!sourceField)
1010410104
{
1010510105
field->dtype = desc.dsc_dtype;
1010610106
field->length = desc.dsc_length;
@@ -10128,12 +10128,12 @@ void CreateRelationNode::defineQueryColumns(thread_db* tdbb, DsqlCompilerScratch
1012810128
else if (desc.isExact() && field->subType != dsc_num_type_none)
1012910129
field->setExactPrecision();
1013010130
}
10131-
10132-
field->flags &= ~FLD_nullable;
10133-
if (desc.dsc_flags & DSC_nullable)
10134-
field->flags |= FLD_nullable;
1013510131
}
1013610132

10133+
field->flags &= ~FLD_nullable;
10134+
if (desc.dsc_flags & DSC_nullable)
10135+
field->flags |= FLD_nullable;
10136+
1013710137
if (!(field->flags & FLD_nullable))
1013810138
{
1013910139
auto& notNullConstraint = clause->constraints.add();

0 commit comments

Comments
 (0)