mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Improvement CORE-5430 - Support for INCREMENT option in identity columns.
This commit is contained in:
parent
94bdb099b5
commit
278c993915
@ -25,6 +25,9 @@
|
||||
|
||||
## Improvements
|
||||
|
||||
* [CORE-5430](http://tracker.firebirdsql.org/browse/CORE-5430): Support for INCREMENT option in identity columns
|
||||
Contributor(s): Adriano dos Santos Fernandes
|
||||
|
||||
* [CORE-5119](http://tracker.firebirdsql.org/browse/CORE-5119): Support autocommit mode in SET TRANSACTION statement
|
||||
Contributor(s): Dmitry Yemanov
|
||||
|
||||
|
@ -11,10 +11,15 @@ Description:
|
||||
|
||||
Syntax:
|
||||
<column definition> ::=
|
||||
<name> <type> GENERATED BY DEFAULT AS IDENTITY [ (START WITH <value>) ] <constraints>
|
||||
<name> <type> GENERATED BY DEFAULT AS IDENTITY [ ( <identity column option>... ) ] <constraints>
|
||||
|
||||
<identity column option> ::=
|
||||
START WITH <value> |
|
||||
INCREMENT [ BY ] <value>
|
||||
|
||||
<alter column definition> ::=
|
||||
<name> RESTART [ WITH <value> ]
|
||||
<name> RESTART [ WITH <value> ] |
|
||||
<name> SET INCREMENT [ BY ] <value>
|
||||
|
||||
Syntax rules:
|
||||
- The type of an identity column must be an exact number type with zero scale. That includes:
|
||||
@ -25,6 +30,7 @@ Notes:
|
||||
- You cannot alter a identity column to normal column and vice versa.
|
||||
- Identity columns are implicitly NOT NULL.
|
||||
- Identity columns don't enforce uniqueness automatically. Use UNIQUE or PRIMARY key for that.
|
||||
- Increment value cannot be 0.
|
||||
|
||||
Implementation:
|
||||
Two columns have been inserted in RDB$RELATION_FIELDS: RDB$GENERATOR_NAME and RDB$IDENTITY_TYPE.
|
||||
|
@ -1948,6 +1948,8 @@ C --
|
||||
PARAMETER (GDS__dyn_cant_use_in_foreignkey = 336068897)
|
||||
INTEGER*4 GDS__dyn_defvaldecl_package_func
|
||||
PARAMETER (GDS__dyn_defvaldecl_package_func = 336068898)
|
||||
INTEGER*4 GDS__dyn_cant_use_zero_inc_ident
|
||||
PARAMETER (GDS__dyn_cant_use_zero_inc_ident = 336068904)
|
||||
INTEGER*4 GDS__gbak_unknown_switch
|
||||
PARAMETER (GDS__gbak_unknown_switch = 336330753)
|
||||
INTEGER*4 GDS__gbak_page_size_missing
|
||||
|
@ -1943,6 +1943,8 @@ const
|
||||
gds_dyn_cant_use_in_foreignkey = 336068897;
|
||||
isc_dyn_defvaldecl_package_func = 336068898;
|
||||
gds_dyn_defvaldecl_package_func = 336068898;
|
||||
isc_dyn_cant_use_zero_inc_ident = 336068904;
|
||||
gds_dyn_cant_use_zero_inc_ident = 336068904;
|
||||
isc_gbak_unknown_switch = 336330753;
|
||||
gds_gbak_unknown_switch = 336330753;
|
||||
isc_gbak_page_size_missing = 336330754;
|
||||
|
@ -60,6 +60,11 @@ public:
|
||||
return nullable;
|
||||
}
|
||||
|
||||
T orElse(T elseValue) const
|
||||
{
|
||||
return specified ? value : elseValue;
|
||||
}
|
||||
|
||||
bool operator ==(const BaseNullable<T>& o) const
|
||||
{
|
||||
return (!specified && !o.specified) || (specified == o.specified && value == o.value);
|
||||
|
@ -6279,6 +6279,13 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
||||
|
||||
if (clause->identity)
|
||||
{
|
||||
if (clause->identity->increment.orElse(1) == 0)
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) <<
|
||||
Arg::Str(field->fld_name) <<
|
||||
Arg::Str(name));
|
||||
}
|
||||
|
||||
dsc desc;
|
||||
MET_get_domain(tdbb, *tdbb->getDefaultPool(), fieldDefinition.fieldSource, &desc, NULL);
|
||||
|
||||
@ -6291,7 +6298,9 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
||||
DYN_UTIL_generate_generator_name(tdbb, fieldDefinition.identitySequence);
|
||||
|
||||
CreateAlterSequenceNode::store(tdbb, transaction, fieldDefinition.identitySequence,
|
||||
fb_sysflag_identity_generator, clause->identityStart, 1);
|
||||
fb_sysflag_identity_generator,
|
||||
clause->identity->start.orElse(0),
|
||||
clause->identity->increment.orElse(1));
|
||||
}
|
||||
|
||||
BlrDebugWriter::BlrData defaultValue;
|
||||
@ -7838,7 +7847,7 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
|
||||
}
|
||||
END_MODIFY
|
||||
}
|
||||
else if (clause->identityRestart)
|
||||
else if (clause->identityRestart || clause->identityIncrement.specified)
|
||||
{
|
||||
bool found = false;
|
||||
AutoRequest request2;
|
||||
@ -7849,11 +7858,29 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
|
||||
{
|
||||
const SLONG id = GEN.RDB$GENERATOR_ID;
|
||||
const MetaName genName(RFR.RDB$GENERATOR_NAME);
|
||||
const SINT64 val = clause->identityRestartValue.specified ?
|
||||
clause->identityRestartValue.value :
|
||||
(!GEN.RDB$INITIAL_VALUE.NULL ? GEN.RDB$INITIAL_VALUE : 0);
|
||||
|
||||
transaction->getGenIdCache()->put(id, val);
|
||||
if (clause->identityRestart)
|
||||
{
|
||||
const SINT64 val = clause->identityRestartValue.specified ?
|
||||
clause->identityRestartValue.value :
|
||||
(!GEN.RDB$INITIAL_VALUE.NULL ? GEN.RDB$INITIAL_VALUE : 0);
|
||||
|
||||
transaction->getGenIdCache()->put(id, val);
|
||||
}
|
||||
else if (clause->identityIncrement.specified)
|
||||
{
|
||||
if (clause->identityIncrement.value == 0)
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) <<
|
||||
Arg::Str(field->fld_name) <<
|
||||
Arg::Str(name));
|
||||
}
|
||||
|
||||
MET_update_generator_increment(tdbb, id, clause->identityIncrement.value);
|
||||
}
|
||||
else
|
||||
fb_assert(false);
|
||||
|
||||
dsc desc;
|
||||
desc.makeText((USHORT) genName.length(), ttype_metadata,
|
||||
(UCHAR*) genName.c_str());
|
||||
|
@ -1304,6 +1304,16 @@ public:
|
||||
NestConst<BoolSourceClause> check;
|
||||
};
|
||||
|
||||
struct IdentityOptions
|
||||
{
|
||||
IdentityOptions(MemoryPool&)
|
||||
{
|
||||
}
|
||||
|
||||
Nullable<SINT64> start;
|
||||
Nullable<SLONG> increment;
|
||||
};
|
||||
|
||||
struct AddColumnClause : public Clause
|
||||
{
|
||||
explicit AddColumnClause(MemoryPool& p)
|
||||
@ -1313,8 +1323,7 @@ public:
|
||||
constraints(p),
|
||||
collate(p),
|
||||
computed(NULL),
|
||||
identity(false),
|
||||
identityStart(0),
|
||||
identity(NULL),
|
||||
notNullSpecified(false)
|
||||
{
|
||||
}
|
||||
@ -1324,8 +1333,7 @@ public:
|
||||
Firebird::ObjectsArray<AddConstraintClause> constraints;
|
||||
Firebird::MetaName collate;
|
||||
NestConst<ValueSourceClause> computed;
|
||||
bool identity;
|
||||
SINT64 identityStart;
|
||||
NestConst<IdentityOptions> identity;
|
||||
bool notNullSpecified;
|
||||
};
|
||||
|
||||
@ -1385,6 +1393,7 @@ public:
|
||||
bool dropDefault;
|
||||
bool identityRestart;
|
||||
Nullable<SINT64> identityRestartValue;
|
||||
Nullable<SINT64> identityIncrement;
|
||||
NestConst<ValueSourceClause> computed;
|
||||
};
|
||||
|
||||
|
@ -698,9 +698,9 @@ public:
|
||||
const bool dialect1;
|
||||
GeneratorItem generator;
|
||||
NestConst<ValueExprNode> arg;
|
||||
SLONG step;
|
||||
|
||||
private:
|
||||
SLONG step;
|
||||
bool sysGen;
|
||||
const bool implicit;
|
||||
const bool identity;
|
||||
|
@ -6839,17 +6839,13 @@ void StoreNode::makeDefaults(thread_db* tdbb, CompilerScratch* csb)
|
||||
|
||||
if (generatorName.hasData())
|
||||
{
|
||||
// Make a gen_id(<generator name>, 1) expression.
|
||||
// Make a (next value for <generator name>) expression.
|
||||
|
||||
LiteralNode* literal = FB_NEW_POOL(csb->csb_pool) LiteralNode(csb->csb_pool);
|
||||
SLONG* increment = FB_NEW_POOL(csb->csb_pool) SLONG(1);
|
||||
literal->litDesc.makeLong(0, increment);
|
||||
|
||||
GenIdNode* const genNode = FB_NEW_POOL(csb->csb_pool)
|
||||
GenIdNode(csb->csb_pool, (csb->blrVersion == 4), generatorName, literal, false, true);
|
||||
GenIdNode* const genNode = FB_NEW_POOL(csb->csb_pool) GenIdNode(
|
||||
csb->csb_pool, (csb->blrVersion == 4), generatorName, NULL, true, true);
|
||||
|
||||
bool sysGen = false;
|
||||
if (!MET_load_generator(tdbb, genNode->generator, &sysGen))
|
||||
if (!MET_load_generator(tdbb, genNode->generator, &sysGen, &genNode->step))
|
||||
PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(generatorName));
|
||||
|
||||
if (sysGen)
|
||||
|
@ -722,6 +722,7 @@ using namespace Firebird;
|
||||
Jrd::RelationNode::AddColumnClause* addColumnClause;
|
||||
Jrd::RelationNode::RefActionClause* refActionClause;
|
||||
Jrd::RelationNode::IndexConstraintClause* indexConstraintClause;
|
||||
Jrd::RelationNode::IdentityOptions* identityOptions;
|
||||
Jrd::CreateRelationNode* createRelationNode;
|
||||
Jrd::CreateAlterViewNode* createAlterViewNode;
|
||||
Jrd::CreateIndexNode* createIndexNode;
|
||||
@ -2148,8 +2149,7 @@ column_def($relationNode)
|
||||
newNode<RelationNode::AddColumnClause>();
|
||||
clause->field = $2;
|
||||
clause->field->fld_name = *$1;
|
||||
clause->identity = true;
|
||||
clause->identityStart = $3;
|
||||
clause->identity = $3;
|
||||
$relationNode->clauses.add(clause);
|
||||
}
|
||||
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
|
||||
@ -2177,15 +2177,32 @@ column_def($relationNode)
|
||||
}
|
||||
;
|
||||
|
||||
%type <int64Val> identity_clause
|
||||
%type <identityOptions> identity_clause
|
||||
identity_clause
|
||||
: GENERATED BY DEFAULT AS IDENTITY identity_clause_options { $$ = $6; }
|
||||
: GENERATED BY DEFAULT AS IDENTITY
|
||||
{ $$ = newNode<RelationNode::IdentityOptions>(); }
|
||||
identity_clause_options_opt($6)
|
||||
{ $$ = $6; }
|
||||
;
|
||||
|
||||
%type <int64Val> identity_clause_options
|
||||
identity_clause_options
|
||||
: /* nothing */ { $$ = 0; }
|
||||
| '(' START WITH sequence_value ')' { $$ = $4; }
|
||||
%type identity_clause_options_opt(<identityOptions>)
|
||||
identity_clause_options_opt($identityOptions)
|
||||
: // nothing
|
||||
| '(' identity_clause_options($identityOptions) ')'
|
||||
;
|
||||
|
||||
%type identity_clause_options(<identityOptions>)
|
||||
identity_clause_options($identityOptions)
|
||||
: identity_clause_options identity_clause_option($identityOptions)
|
||||
| identity_clause_option($identityOptions)
|
||||
;
|
||||
|
||||
%type identity_clause_option(<identityOptions>)
|
||||
identity_clause_option($identityOptions)
|
||||
: START WITH sequence_value
|
||||
{ setClause($identityOptions->start, "START WITH", $3); }
|
||||
| INCREMENT by_noise signed_long_integer
|
||||
{ setClause($identityOptions->increment, "INCREMENT BY", $3); }
|
||||
;
|
||||
|
||||
// value does allow parens around it, but there is a problem getting the source text.
|
||||
@ -3919,6 +3936,14 @@ alter_op($relationNode)
|
||||
clause->identityRestartValue = $4;
|
||||
$relationNode->clauses.add(clause);
|
||||
}
|
||||
| col_opt symbol_column_name SET INCREMENT by_noise signed_long_integer
|
||||
{
|
||||
RelationNode::AlterColTypeClause* clause = newNode<RelationNode::AlterColTypeClause>();
|
||||
clause->field = newNode<dsql_fld>();
|
||||
clause->field->fld_name = *$2;
|
||||
clause->identityIncrement = $6;
|
||||
$relationNode->clauses.add(clause);
|
||||
}
|
||||
| ALTER SQL SECURITY DEFINER
|
||||
{
|
||||
RelationNode::AlterSqlSecurityClause* clause =
|
||||
|
@ -970,6 +970,7 @@ static const struct {
|
||||
{"dyn_cant_use_zero_increment", 336068896},
|
||||
{"dyn_cant_use_in_foreignkey", 336068897},
|
||||
{"dyn_defvaldecl_package_func", 336068898},
|
||||
{"dyn_cant_use_zero_inc_ident", 336068904},
|
||||
{"gbak_unknown_switch", 336330753},
|
||||
{"gbak_page_size_missing", 336330754},
|
||||
{"gbak_page_size_toobig", 336330755},
|
||||
|
@ -1004,6 +1004,7 @@ const ISC_STATUS isc_dyn_cant_modify_sysobj = 336068895L;
|
||||
const ISC_STATUS isc_dyn_cant_use_zero_increment = 336068896L;
|
||||
const ISC_STATUS isc_dyn_cant_use_in_foreignkey = 336068897L;
|
||||
const ISC_STATUS isc_dyn_defvaldecl_package_func = 336068898L;
|
||||
const ISC_STATUS isc_dyn_cant_use_zero_inc_ident = 336068904L;
|
||||
const ISC_STATUS isc_gbak_unknown_switch = 336330753L;
|
||||
const ISC_STATUS isc_gbak_page_size_missing = 336330754L;
|
||||
const ISC_STATUS isc_gbak_page_size_toobig = 336330755L;
|
||||
@ -1334,7 +1335,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
|
||||
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
||||
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
||||
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
||||
const ISC_STATUS isc_err_max = 1278;
|
||||
const ISC_STATUS isc_err_max = 1279;
|
||||
|
||||
#else /* c definitions */
|
||||
|
||||
@ -2308,6 +2309,7 @@ const ISC_STATUS isc_err_max = 1278;
|
||||
#define isc_dyn_cant_use_zero_increment 336068896L
|
||||
#define isc_dyn_cant_use_in_foreignkey 336068897L
|
||||
#define isc_dyn_defvaldecl_package_func 336068898L
|
||||
#define isc_dyn_cant_use_zero_inc_ident 336068904L
|
||||
#define isc_gbak_unknown_switch 336330753L
|
||||
#define isc_gbak_page_size_missing 336330754L
|
||||
#define isc_gbak_page_size_toobig 336330755L
|
||||
@ -2638,7 +2640,7 @@ const ISC_STATUS isc_err_max = 1278;
|
||||
#define isc_trace_switch_param_miss 337182758L
|
||||
#define isc_trace_param_act_notcompat 337182759L
|
||||
#define isc_trace_mandatory_switch_miss 337182760L
|
||||
#define isc_err_max 1278
|
||||
#define isc_err_max 1279
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -973,6 +973,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{336068896, "INCREMENT BY 0 is an illegal option for sequence @1"}, /* dyn_cant_use_zero_increment */
|
||||
{336068897, "Can't use @1 in FOREIGN KEY constraint"}, /* dyn_cant_use_in_foreignkey */
|
||||
{336068898, "Default values for parameters are allowed only in declaration of packaged function @1.@2"}, /* dyn_defvaldecl_package_func */
|
||||
{336068904, "INCREMENT BY 0 is an illegal option for identity column @1 of table @2"}, /* dyn_cant_use_zero_inc_ident */
|
||||
{336330753, "found unknown switch"}, /* gbak_unknown_switch */
|
||||
{336330754, "page size parameter missing"}, /* gbak_page_size_missing */
|
||||
{336330755, "Page size specified (@1) greater than limit (32768 bytes)"}, /* gbak_page_size_toobig */
|
||||
|
@ -969,6 +969,7 @@ static const struct {
|
||||
{336068896, -901}, /* 288 dyn_cant_use_zero_increment */
|
||||
{336068897, -901}, /* 289 dyn_cant_use_in_foreignkey */
|
||||
{336068898, -901}, /* 290 dyn_defvaldecl_package_func */
|
||||
{336068904, -901}, /* 296 dyn_cant_use_zero_inc_ident */
|
||||
{336330753, -901}, /* 1 gbak_unknown_switch */
|
||||
{336330754, -901}, /* 2 gbak_page_size_missing */
|
||||
{336330755, -901}, /* 3 gbak_page_size_toobig */
|
||||
|
@ -969,6 +969,7 @@ static const struct {
|
||||
{336068896, "42000"}, // 288 dyn_cant_use_zero_increment
|
||||
{336068897, "42000"}, // 289 dyn_cant_use_in_foreignkey
|
||||
{336068898, "42000"}, // 290 dyn_defvaldecl_package_func
|
||||
{336068904, "42000"}, // 296 dyn_cant_use_zero_inc_ident
|
||||
{336330753, "00000"}, // 1 gbak_unknown_switch
|
||||
{336330754, "00000"}, // 2 gbak_page_size_missing
|
||||
{336330755, "00000"}, // 3 gbak_page_size_toobig
|
||||
|
@ -6,7 +6,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
|
||||
('2015-01-07 18:01:51', 'GFIX', 3, 134)
|
||||
('1996-11-07 13:39:40', 'GPRE', 4, 1)
|
||||
('2016-02-23 00:00:00', 'DSQL', 7, 40)
|
||||
('2016-05-30 17:56:47', 'DYN', 8, 296)
|
||||
('2016-12-27 12:30:00', 'DYN', 8, 297)
|
||||
('1996-11-07 13:39:40', 'INSTALL', 10, 1)
|
||||
('1996-11-07 13:38:41', 'TEST', 11, 4)
|
||||
('2015-07-23 14:20:00', 'GBAK', 12, 370)
|
||||
|
@ -1992,6 +1992,7 @@ COMMIT WORK;
|
||||
(NULL, 'CreateAlterRoleNode::execute', 'DdlNodes.epp', NULL, 8, 293, NULL, 'DROP SYSTEM PRIVILEGES should not be used in CREATE ROLE operator', NULL, NULL);
|
||||
(NULL, 'CreateAlterRoleNode::execute', 'DdlNodes.epp', NULL, 8, 294, NULL, 'Access to SYSTEM PRIVILEGES in ROLES denied to @1', NULL, NULL);
|
||||
(NULL, 'grant/revoke', 'DdlNode.epp', NULL, 8, 295, NULL, 'Only @1, DB owner @2 or user with privilege USE_GRANTED_BY_CLAUSE can use GRANTED BY clause', NULL, NULL);
|
||||
('dyn_cant_use_zero_inc_ident', NULL, 'DdlNodes.epp', NULL, 8, 296, NULL, 'INCREMENT BY 0 is an illegal option for identity column @1 of table @2', NULL, NULL);
|
||||
COMMIT WORK;
|
||||
-- TEST
|
||||
(NULL, 'main', 'test.c', NULL, 11, 0, NULL, 'This is a modified text message', NULL, NULL);
|
||||
|
@ -958,6 +958,7 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
|
||||
(-901, '42', '000', 8, 288, 'dyn_cant_use_zero_increment', NULL, NULL)
|
||||
(-901, '42', '000', 8, 289, 'dyn_cant_use_in_foreignkey', NULL, NULL)
|
||||
(-901, '42', '000', 8, 290, 'dyn_defvaldecl_package_func', NULL, NULL)
|
||||
(-901, '42', '000', 8, 296, 'dyn_cant_use_zero_inc_ident', NULL, NULL)
|
||||
-- GBAK
|
||||
(-901, '00', '000', 12, 1, 'gbak_unknown_switch', NULL, NULL)
|
||||
(-901, '00', '000', 12, 2, 'gbak_page_size_missing', NULL, NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user