Skip to content

Commit e23f030

Browse files
authored
Allow collation to be a part of data type (#7748)
1 parent a263a19 commit e23f030

File tree

6 files changed

+54
-29
lines changed

6 files changed

+54
-29
lines changed

doc/sql.extensions/README.ddl.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,3 +624,8 @@ ALTER PACKAGE <name> SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY
624624

625625
<db_initial_option> list is expanded by "OWNER username" clause which allows to set an owner user name for the created database.
626626
Only users with administrator rights can use this option.
627+
628+
28) COLLATE clause can be used as a part of character data type as per SQL standard.
629+
(Dmitry Sibiryakov)
630+
631+
If is used twice, an error is returned.

src/dsql/DdlNodes.epp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,14 +1119,13 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName&
11191119
//----------------------
11201120

11211121

1122-
ParameterClause::ParameterClause(MemoryPool& pool, dsql_fld* field, const MetaName& aCollate,
1122+
ParameterClause::ParameterClause(MemoryPool& pool, dsql_fld* field,
11231123
ValueSourceClause* aDefaultClause, ValueExprNode* aParameterExpr)
11241124
: name(pool, field ? field->fld_name : ""),
11251125
type(field),
11261126
defaultClause(aDefaultClause),
11271127
parameterExpr(aParameterExpr)
11281128
{
1129-
type->collate = aCollate;
11301129
}
11311130

11321131
string ParameterClause::internalPrint(NodePrinter& printer) const
@@ -6454,13 +6453,18 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
64546453
computedSource, computedValue);
64556454
}
64566455

6457-
field->collate = clause->collate;
64586456
field->resolve(dsqlScratch);
64596457

64606458
// Generate a domain.
64616459
storeGlobalField(tdbb, transaction, fieldDefinition.fieldSource, field,
64626460
computedSource, computedValue);
64636461
}
6462+
else
6463+
{
6464+
// Resolve possible additional collation for domains. For plain types it is already resolved above.
6465+
if (field->collate.hasData())
6466+
DDL_resolve_intl_type(dsqlScratch, field, field->collate);
6467+
}
64646468

64656469
if ((relation->rel_flags & REL_external) &&
64666470
(field->dtype == dtype_blob || field->dtype == dtype_array || field->dimensions))
@@ -6473,9 +6477,6 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
64736477
Arg::Gds(isc_dsql_type_not_supp_ext_tab) << typeName << name << field->fld_name);
64746478
}
64756479

6476-
if (clause->collate.hasData())
6477-
DDL_resolve_intl_type(dsqlScratch, field, clause->collate);
6478-
64796480
if (clause->identityOptions)
64806481
{
64816482
if (clause->identityOptions->increment.value_or(1) == 0)
@@ -6519,10 +6520,7 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
65196520
}
65206521

65216522
fieldDefinition.defaultValue = defaultValue;
6522-
6523-
if (clause->collate.hasData())
6524-
fieldDefinition.collationId = field->collationId;
6525-
6523+
fieldDefinition.collationId = field->collationId;
65266524
fieldDefinition.store(tdbb, transaction);
65276525

65286526
// Define the field constraints.

src/dsql/DdlNodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class ExternalClause : public Printable
171171
class ParameterClause : public Printable
172172
{
173173
public:
174-
ParameterClause(MemoryPool& pool, dsql_fld* field, const MetaName& aCollate,
174+
ParameterClause(MemoryPool& pool, dsql_fld* field,
175175
ValueSourceClause* aDefaultClause = NULL, ValueExprNode* aParameterExpr = NULL);
176176

177177
public:

src/dsql/Parser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@ class Parser : public Firebird::PermanentStorage
340340
return clause.hasData();
341341
}
342342

343+
void setCollate(TypeClause* fld, MetaName* name)
344+
{
345+
if (name)
346+
setClause(fld->collate, "COLLATE", *name);
347+
}
343348
void checkTimeDialect();
344349

345350
// start - defined in btyacc_fb.ske

src/dsql/parse-conflicts.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
69 shift/reduce conflicts, 22 reduce/reduce conflicts.
1+
71 shift/reduce conflicts, 22 reduce/reduce conflicts.

src/dsql/parse.y

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,7 @@ arg_desc_list($parameters)
14571457
arg_desc($parameters)
14581458
: udf_data_type param_mechanism
14591459
{
1460-
$parameters->add(newNode<ParameterClause>($1, MetaName()));
1460+
$parameters->add(newNode<ParameterClause>($1));
14611461
$parameters->back()->udfMechanism = $2;
14621462
}
14631463
;
@@ -1480,7 +1480,7 @@ return_value1($function)
14801480
return_value($function)
14811481
: udf_data_type return_mechanism
14821482
{
1483-
$function->returnType = newNode<ParameterClause>($1, MetaName());
1483+
$function->returnType = newNode<ParameterClause>($1);
14841484
$function->returnType->udfMechanism = $2;
14851485
}
14861486
| PARAMETER pos_short_integer
@@ -1748,13 +1748,12 @@ domain_clause
17481748
{
17491749
$3->fld_name = *$1;
17501750
$<createDomainNode>$ = newNode<CreateDomainNode>(
1751-
newNode<ParameterClause>($3, MetaName(), $4));
1751+
newNode<ParameterClause>($3, $4));
17521752
}
17531753
domain_constraints_opt($5) collate_clause
17541754
{
17551755
$$ = $5;
1756-
if ($7)
1757-
$$->nameType->type->collate = *$7;
1756+
setCollate($3, $7);
17581757
}
17591758
;
17601759

@@ -2356,8 +2355,7 @@ column_def($relationNode)
23562355
}
23572356
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
23582357
{
2359-
if ($6)
2360-
$<addColumnClause>4->collate = *$6;
2358+
setCollate($2, $6);
23612359
}
23622360
| symbol_column_name data_type_or_domain identity_clause
23632361
{
@@ -2370,8 +2368,7 @@ column_def($relationNode)
23702368
}
23712369
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
23722370
{
2373-
if ($6)
2374-
$<addColumnClause>4->collate = *$6;
2371+
setCollate($2, $6);
23752372
}
23762373
| symbol_column_name non_array_type def_computed
23772374
{
@@ -2807,7 +2804,10 @@ input_proc_parameters($parameters)
28072804
%type input_proc_parameter(<parametersClause>)
28082805
input_proc_parameter($parameters)
28092806
: column_domain_or_non_array_type collate_clause default_par_opt
2810-
{ $parameters->add(newNode<ParameterClause>($1, optName($2), $3)); }
2807+
{
2808+
setCollate($1, $2);
2809+
$parameters->add(newNode<ParameterClause>($1, $3));
2810+
}
28112811
;
28122812

28132813
%type output_proc_parameters(<parametersClause>)
@@ -2819,7 +2819,10 @@ output_proc_parameters($parameters)
28192819
%type output_proc_parameter(<parametersClause>)
28202820
output_proc_parameter($parameters)
28212821
: column_domain_or_non_array_type collate_clause
2822-
{ $parameters->add(newNode<ParameterClause>($1, optName($2))); }
2822+
{
2823+
setCollate($1, $2);
2824+
$parameters->add(newNode<ParameterClause>($1));
2825+
}
28232826
;
28242827

28252828
%type <legacyField> column_domain_or_non_array_type
@@ -2891,7 +2894,8 @@ function_clause_start
28912894
RETURNS domain_or_non_array_type collate_clause deterministic_clause_opt
28922895
{
28932896
$$ = $2;
2894-
$$->returnType = newNode<ParameterClause>($5, optName($6));
2897+
$$->returnType = newNode<ParameterClause>($5);
2898+
setCollate($5, $6);
28952899
$$->deterministic = $7;
28962900
}
28972901
;
@@ -3230,7 +3234,8 @@ local_declaration_subfunc_start
32303234
RETURNS domain_or_non_array_type collate_clause deterministic_clause_opt
32313235
{
32323236
$$ = $4;
3233-
$$->dsqlBlock->returns.add(newNode<ParameterClause>($<legacyField>7, optName($8)));
3237+
setCollate($7, $8);
3238+
$$->dsqlBlock->returns.add(newNode<ParameterClause>($<legacyField>7));
32343239
$$->dsqlDeterministic = $9;
32353240
}
32363241
;
@@ -3245,8 +3250,10 @@ local_declaration_item
32453250
var_declaration_item
32463251
: column_domain_or_non_array_type collate_clause var_declaration_initializer
32473252
{
3253+
// Set collate before node allocation to prevent memory leak on throw
3254+
setCollate($1, $2);
32483255
DeclareVariableNode* node = newNode<DeclareVariableNode>();
3249-
node->dsqlDef = newNode<ParameterClause>($1, optName($2), $3);
3256+
node->dsqlDef = newNode<ParameterClause>($1, $3);
32503257
$$ = node;
32513258
}
32523259
;
@@ -3926,7 +3933,10 @@ block_parameters($parameters)
39263933
%type block_parameter(<parametersClause>)
39273934
block_parameter($parameters)
39283935
: column_domain_or_non_array_type collate_clause '=' parameter
3929-
{ $parameters->add(newNode<ParameterClause>($1, optName($2), (ValueSourceClause*) NULL, $4)); }
3936+
{
3937+
setCollate($1, $2);
3938+
$parameters->add(newNode<ParameterClause>($1, (ValueSourceClause*) NULL, $4));
3939+
}
39303940
;
39313941

39323942
// CREATE VIEW
@@ -4909,20 +4919,27 @@ array_range
49094919
%type <legacyField> simple_type
49104920
simple_type
49114921
: non_charset_simple_type
4912-
| character_type charset_clause
4922+
| character_type charset_clause collate_clause
49134923
{
49144924
$$ = $1;
49154925
if ($2)
49164926
{
49174927
$$->charSet = *$2;
49184928
$$->flags |= FLD_has_chset;
49194929
}
4930+
if ($3)
4931+
$$->collate = *$3;
49204932
}
49214933
;
49224934

49234935
%type <legacyField> non_charset_simple_type
49244936
non_charset_simple_type
4925-
: national_character_type
4937+
: national_character_type collate_clause
4938+
{
4939+
$$ = $1;
4940+
if ($2)
4941+
$$->collate = *$2;
4942+
}
49264943
| binary_character_type
49274944
| numeric_type
49284945
| float_type

0 commit comments

Comments
 (0)