8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:43:02 +01:00

Feature CORE-1385 Identity columns - in its basic form

This commit is contained in:
asfernandes 2010-01-13 19:14:15 +00:00
parent e36d3ed494
commit 9c1bab1793
36 changed files with 1080 additions and 347 deletions

View File

@ -0,0 +1,51 @@
----------------
Identity Columns
----------------
Author:
Adriano dos Santos Fernandes <adrianosf@gmail.com>
Description:
An identity column is a column associated with an internal sequence generator and has it value
automatically set when omitted in an INSERT statement.
Syntax:
<column definition> ::=
<name> <type> GENERATED BY DEFAULT AS IDENTITY <constaints>
Syntax rules:
- The type of an identity column must be an exact number type with zero scale. That includes:
smallint, integer, bigint, numeric(x, 0) and decimal(x, 0).
- Identity columns can't have DEFAULT or COMPUTED value.
Notes:
- You cannot alter a identity column to normal column and vice versa.
- Identity columns are implicitly NOT NULL.
- Identity columns doesn't enforce uniqueness automatically. Use UNIQUE or PRIMARY key for that.
Implementation:
Two columns has been inserted in RDB$RELATION_FIELDS: RDB$GENERATOR_NAME and RDB$IDENTITY_TYPE.
RDB$GENERATOR_NAME stores the automatically created generator for the column. In RDB$GENERATORS,
the value of RDB$SYSTEM_FLAG of that generator will be 6. RDB$IDENTITY_TYPE will currently
always store the value 0 (by default) for identity columns and NULL for non-identity columns.
In the future this column will can store the value 1 (always) when Firebird support this type
of identity column.
Example:
create table objects (
id integer generated by default as identity primary key,
name varchar(15)
);
insert into objects (name) values ('Table');
insert into objects (name) values ('Book');
insert into objects (id, name) values (10, 'Computer');
select * from objects;
ID NAME
============ ===============
1 Table
2 Book
10 Computer

View File

@ -565,116 +565,239 @@ burp_fld* get_fields( burp_rel* relation)
// requests--this requires more code but it is well worth it
// for the performance benefits, especially remotely--deej
FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle1)
X IN RDB$RELATION_FIELDS CROSS
Y IN RDB$FIELDS WITH
X.RDB$FIELD_SOURCE = Y.RDB$FIELD_NAME AND
X.RDB$RELATION_NAME EQ relation->rel_name
field = (burp_fld*) BURP_alloc_zero(sizeof(burp_fld));
field->fld_number = count++;
field->fld_type = Y.RDB$FIELD_TYPE;
field->fld_sub_type = Y.RDB$FIELD_SUB_TYPE;
field->fld_length = Y.RDB$FIELD_LENGTH;
field->fld_scale = Y.RDB$FIELD_SCALE;
field->fld_id = X.RDB$FIELD_ID;
if (!X.RDB$DESCRIPTION.NULL)
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle1)
X IN RDB$RELATION_FIELDS CROSS
Y IN RDB$FIELDS WITH
X.RDB$FIELD_SOURCE = Y.RDB$FIELD_NAME AND
X.RDB$RELATION_NAME EQ relation->rel_name
{
blob_id = &X.RDB$DESCRIPTION;
if (blob_id->gds_quad_low || blob_id->gds_quad_high)
field->fld_description = X.RDB$DESCRIPTION;
}
field = (burp_fld*) BURP_alloc_zero(sizeof(burp_fld));
field->fld_number = count++;
field->fld_type = Y.RDB$FIELD_TYPE;
field->fld_sub_type = Y.RDB$FIELD_SUB_TYPE;
field->fld_length = Y.RDB$FIELD_LENGTH;
field->fld_scale = Y.RDB$FIELD_SCALE;
field->fld_id = X.RDB$FIELD_ID;
if (!X.RDB$QUERY_HEADER.NULL)
{
blob_id = &X.RDB$QUERY_HEADER;
if (blob_id->gds_quad_low || blob_id->gds_quad_high)
field->fld_query_header = X.RDB$QUERY_HEADER;
}
if (X.RDB$FIELD_POSITION.NULL)
field->fld_flags |= FLD_position_missing;
else
field->fld_position = X.RDB$FIELD_POSITION;
field->fld_view_context = X.RDB$VIEW_CONTEXT;
if (X.RDB$UPDATE_FLAG.NULL)
field->fld_flags |= FLD_update_missing;
else
field->fld_update_flag = X.RDB$UPDATE_FLAG;
COPY (X.RDB$FIELD_NAME, field->fld_name);
COPY (X.RDB$FIELD_SOURCE, field->fld_source);
COPY (X.RDB$BASE_FIELD, field->fld_base);
COPY (X.RDB$QUERY_NAME, field->fld_query_name);
COPY (X.RDB$EDIT_STRING, field->fld_edit_string);
COPY (X.RDB$COMPLEX_NAME, field->fld_complex_name);
blob_id = &Y.RDB$COMPUTED_BLR;
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_flags |= FLD_computed;
}
field->fld_system_flag = X.RDB$SYSTEM_FLAG;
COPY (X.RDB$SECURITY_CLASS, field->fld_security_class);
// use the fld_flags to mark the field as an array and
// to differentiate it from other blobs
if (Y.RDB$DIMENSIONS)
{
field->fld_flags |= FLD_array;
field->fld_dimensions = Y.RDB$DIMENSIONS;
if (field->fld_dimensions < 0) {
BURP_error_redirect (NULL, 52, SafeArg() << field->fld_name);
if (!X.RDB$DESCRIPTION.NULL)
{
blob_id = &X.RDB$DESCRIPTION;
if (blob_id->gds_quad_low || blob_id->gds_quad_high)
field->fld_description = X.RDB$DESCRIPTION;
}
// msg 52 array dimension for field %s is invalid
get_ranges (field);
}
if (!X.RDB$NULL_FLAG.NULL)
{
field->fld_null_flag = X.RDB$NULL_FLAG;
field->fld_flags |= FLD_null_flag;
}
if (!X.RDB$QUERY_HEADER.NULL)
{
blob_id = &X.RDB$QUERY_HEADER;
if (blob_id->gds_quad_low || blob_id->gds_quad_high)
field->fld_query_header = X.RDB$QUERY_HEADER;
}
if (X.RDB$FIELD_POSITION.NULL)
field->fld_flags |= FLD_position_missing;
else
field->fld_position = X.RDB$FIELD_POSITION;
field->fld_view_context = X.RDB$VIEW_CONTEXT;
if (X.RDB$UPDATE_FLAG.NULL)
field->fld_flags |= FLD_update_missing;
else
field->fld_update_flag = X.RDB$UPDATE_FLAG;
COPY (X.RDB$FIELD_NAME, field->fld_name);
COPY (X.RDB$FIELD_SOURCE, field->fld_source);
COPY (X.RDB$BASE_FIELD, field->fld_base);
COPY (X.RDB$QUERY_NAME, field->fld_query_name);
COPY (X.RDB$EDIT_STRING, field->fld_edit_string);
COPY (X.RDB$COMPLEX_NAME, field->fld_complex_name);
blob_id = &Y.RDB$COMPUTED_BLR;
if (!X.RDB$DEFAULT_VALUE.NULL)
{
blob_id = &X.RDB$DEFAULT_VALUE;
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_default_value = X.RDB$DEFAULT_VALUE;
field->fld_flags |= FLD_computed;
}
field->fld_system_flag = X.RDB$SYSTEM_FLAG;
COPY (X.RDB$SECURITY_CLASS, field->fld_security_class);
// use the fld_flags to mark the field as an array and
// to differentiate it from other blobs
if (Y.RDB$DIMENSIONS)
{
field->fld_flags |= FLD_array;
field->fld_dimensions = Y.RDB$DIMENSIONS;
if (field->fld_dimensions < 0) {
BURP_error_redirect (NULL, 52, SafeArg() << field->fld_name);
}
// msg 52 array dimension for field %s is invalid
get_ranges (field);
}
if (!X.RDB$NULL_FLAG.NULL)
{
field->fld_null_flag = X.RDB$NULL_FLAG;
field->fld_flags |= FLD_null_flag;
}
if (!X.RDB$DEFAULT_VALUE.NULL)
{
blob_id = &X.RDB$DEFAULT_VALUE;
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_default_value = X.RDB$DEFAULT_VALUE;
}
}
if (!X.RDB$DEFAULT_SOURCE.NULL)
{
blob_id = &X.RDB$DEFAULT_SOURCE;
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_default_source = X.RDB$DEFAULT_SOURCE;
}
}
if (!Y.RDB$CHARACTER_SET_ID.NULL)
{
field->fld_character_set_id = Y.RDB$CHARACTER_SET_ID;
field->fld_flags |= FLD_charset_flag;
}
if (!X.RDB$COLLATION_ID.NULL)
{
field->fld_collation_id = X.RDB$COLLATION_ID;
field->fld_flags |= FLD_collate_flag;
}
field->fld_next = fields;
fields = field;
// ODS 12
if (!X.RDB$GENERATOR_NAME.NULL)
{
COPY(X.RDB$GENERATOR_NAME, field->fld_generator);
field->fld_identity_type = X.RDB$IDENTITY_TYPE;
}
}
if (!X.RDB$DEFAULT_SOURCE.NULL)
END_FOR
ON_ERROR
general_on_error();
END_ERROR
}
else
{
FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle1)
X IN RDB$RELATION_FIELDS CROSS
Y IN RDB$FIELDS WITH
X.RDB$FIELD_SOURCE = Y.RDB$FIELD_NAME AND
X.RDB$RELATION_NAME EQ relation->rel_name
{
blob_id = &X.RDB$DEFAULT_SOURCE;
field = (burp_fld*) BURP_alloc_zero(sizeof(burp_fld));
field->fld_number = count++;
field->fld_type = Y.RDB$FIELD_TYPE;
field->fld_sub_type = Y.RDB$FIELD_SUB_TYPE;
field->fld_length = Y.RDB$FIELD_LENGTH;
field->fld_scale = Y.RDB$FIELD_SCALE;
field->fld_id = X.RDB$FIELD_ID;
if (!X.RDB$DESCRIPTION.NULL)
{
blob_id = &X.RDB$DESCRIPTION;
if (blob_id->gds_quad_low || blob_id->gds_quad_high)
field->fld_description = X.RDB$DESCRIPTION;
}
if (!X.RDB$QUERY_HEADER.NULL)
{
blob_id = &X.RDB$QUERY_HEADER;
if (blob_id->gds_quad_low || blob_id->gds_quad_high)
field->fld_query_header = X.RDB$QUERY_HEADER;
}
if (X.RDB$FIELD_POSITION.NULL)
field->fld_flags |= FLD_position_missing;
else
field->fld_position = X.RDB$FIELD_POSITION;
field->fld_view_context = X.RDB$VIEW_CONTEXT;
if (X.RDB$UPDATE_FLAG.NULL)
field->fld_flags |= FLD_update_missing;
else
field->fld_update_flag = X.RDB$UPDATE_FLAG;
COPY (X.RDB$FIELD_NAME, field->fld_name);
COPY (X.RDB$FIELD_SOURCE, field->fld_source);
COPY (X.RDB$BASE_FIELD, field->fld_base);
COPY (X.RDB$QUERY_NAME, field->fld_query_name);
COPY (X.RDB$EDIT_STRING, field->fld_edit_string);
COPY (X.RDB$COMPLEX_NAME, field->fld_complex_name);
blob_id = &Y.RDB$COMPUTED_BLR;
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_default_source = X.RDB$DEFAULT_SOURCE;
field->fld_flags |= FLD_computed;
}
field->fld_system_flag = X.RDB$SYSTEM_FLAG;
COPY (X.RDB$SECURITY_CLASS, field->fld_security_class);
// use the fld_flags to mark the field as an array and
// to differentiate it from other blobs
if (Y.RDB$DIMENSIONS)
{
field->fld_flags |= FLD_array;
field->fld_dimensions = Y.RDB$DIMENSIONS;
if (field->fld_dimensions < 0) {
BURP_error_redirect (NULL, 52, SafeArg() << field->fld_name);
}
// msg 52 array dimension for field %s is invalid
get_ranges (field);
}
if (!X.RDB$NULL_FLAG.NULL)
{
field->fld_null_flag = X.RDB$NULL_FLAG;
field->fld_flags |= FLD_null_flag;
}
if (!X.RDB$DEFAULT_VALUE.NULL)
{
blob_id = &X.RDB$DEFAULT_VALUE;
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_default_value = X.RDB$DEFAULT_VALUE;
}
}
if (!X.RDB$DEFAULT_SOURCE.NULL)
{
blob_id = &X.RDB$DEFAULT_SOURCE;
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_default_source = X.RDB$DEFAULT_SOURCE;
}
}
if (!Y.RDB$CHARACTER_SET_ID.NULL)
{
field->fld_character_set_id = Y.RDB$CHARACTER_SET_ID;
field->fld_flags |= FLD_charset_flag;
}
if (!X.RDB$COLLATION_ID.NULL)
{
field->fld_collation_id = X.RDB$COLLATION_ID;
field->fld_flags |= FLD_collate_flag;
}
field->fld_next = fields;
fields = field;
}
if (!Y.RDB$CHARACTER_SET_ID.NULL)
{
field->fld_character_set_id = Y.RDB$CHARACTER_SET_ID;
field->fld_flags |= FLD_charset_flag;
}
if (!X.RDB$COLLATION_ID.NULL)
{
field->fld_collation_id = X.RDB$COLLATION_ID;
field->fld_flags |= FLD_collate_flag;
}
field->fld_next = fields;
fields = field;
END_FOR;
ON_ERROR
general_on_error();
END_ERROR;
END_FOR
ON_ERROR
general_on_error();
END_ERROR
}
return fields;
}
@ -1996,14 +2119,17 @@ void put_relation( burp_rel* relation)
put_numeric(att_field_collation_id, field->fld_collation_id);
put_blr_blob(att_field_default_value, field->fld_default_value);
put_source_blob(att_field_default_source, att_field_default_source, field->fld_default_source);
if (relation->rel_flags & REL_view)
{
put_numeric(att_view_context, field->fld_view_context);
if (field->fld_base[0])
PUT_TEXT(att_base_field, field->fld_base);
}
if (field->fld_flags & FLD_computed)
put_numeric(att_field_computed_flag, TRUE);
if (field->fld_flags & FLD_array)
{
put_numeric(att_field_dimensions, field->fld_dimensions);
@ -2014,6 +2140,13 @@ void put_relation( burp_rel* relation)
put_numeric(att_field_range_high, *(rp + 1));
}
}
if (field->fld_generator[0])
{
PUT_TEXT(att_field_generator_name, field->fld_generator);
put_numeric(att_field_identity_type, field->fld_identity_type);
}
put(tdgbl, att_end);
}
@ -2995,6 +3128,9 @@ void write_generators()
put_source_blob (att_gen_description, att_gen_description, X.RDB$DESCRIPTION);
}
if (X.RDB$SYSTEM_FLAG)
put_numeric(att_gen_sysflag, X.RDB$SYSTEM_FLAG);
if (!X.RDB$SECURITY_CLASS.NULL)
PUT_TEXT(att_gen_security_class, X.RDB$SECURITY_CLASS);
if (!X.RDB$OWNER_NAME.NULL)

View File

@ -323,6 +323,8 @@ enum att_type {
// hence the new atributes for rdb$fields may be already present
// att_field_security_class, // already used for relation_fields
att_field_owner_name, // FB3.0, ODS12_0,
att_field_generator_name,
att_field_identity_type,
// Index attributes
@ -491,6 +493,7 @@ enum att_type {
att_gen_description,
att_gen_security_class, // FB3.0, ODS12_0
att_gen_owner_name,
att_gen_sysflag,
// Stored procedure attributes
@ -651,6 +654,8 @@ struct burp_fld
TEXT fld_base [GDS_NAME_LEN];
TEXT fld_query_name [GDS_NAME_LEN];
TEXT fld_security_class [GDS_NAME_LEN];
TEXT fld_generator[GDS_NAME_LEN];
SSHORT fld_identity_type;
//SSHORT fld_edit_length;
SSHORT fld_view_context;
SSHORT fld_update_flag;

View File

@ -155,7 +155,7 @@ bool restore(BurpGlobals* tdgbl, const TEXT*, const TEXT*);
void restore_security_class(BurpGlobals* tdgbl, const TEXT*, const TEXT*);
USHORT get_view_base_relation_count(BurpGlobals* tdgbl, const TEXT*, USHORT, bool* error);
void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value,
const ISC_QUAD* gen_desc, const char* secclass, const char* ownername);
const ISC_QUAD* gen_desc, const char* secclass, const char* ownername, fb_sysflag sysFlag);
void update_global_field(BurpGlobals* tdgbl);
void update_view_dbkey_lengths(BurpGlobals* tdgbl);
void general_on_error();
@ -3570,198 +3570,411 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
burp_fld* field = (burp_fld*) BURP_alloc_zero (sizeof(burp_fld));
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_field_req_handle1)
X IN RDB$RELATION_FIELDS
strcpy (X.RDB$RELATION_NAME, relation->rel_name);
X.RDB$FIELD_POSITION = 0;
memset (X.RDB$QUERY_NAME, ' ', sizeof(X.RDB$QUERY_NAME));
X.RDB$VIEW_CONTEXT.NULL = TRUE;
X.RDB$BASE_FIELD.NULL = TRUE;
X.RDB$SECURITY_CLASS.NULL = TRUE;
X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$QUERY_HEADER.NULL = TRUE;
X.RDB$EDIT_STRING.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$FIELD_POSITION.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
X.RDB$COMPLEX_NAME.NULL = TRUE;
X.RDB$UPDATE_FLAG.NULL = TRUE;
X.RDB$DEFAULT_SOURCE.NULL = TRUE;
X.RDB$DEFAULT_VALUE.NULL = TRUE;
X.RDB$NULL_FLAG.NULL = TRUE;
X.RDB$COLLATION_ID.NULL = TRUE;
skip_init(&scan_next_attr);
while (get_attribute(&attribute, tdgbl) != att_end)
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
STORE (TRANSACTION_HANDLE local_trans REQUEST_HANDLE tdgbl->handles_get_field_req_handle1)
X IN RDB$RELATION_FIELDS
{
switch (skip_scan(&scan_next_attr), attribute)
strcpy (X.RDB$RELATION_NAME, relation->rel_name);
X.RDB$FIELD_POSITION = 0;
memset (X.RDB$QUERY_NAME, ' ', sizeof(X.RDB$QUERY_NAME));
X.RDB$VIEW_CONTEXT.NULL = TRUE;
X.RDB$BASE_FIELD.NULL = TRUE;
X.RDB$SECURITY_CLASS.NULL = TRUE;
X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$QUERY_HEADER.NULL = TRUE;
X.RDB$EDIT_STRING.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$FIELD_POSITION.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
X.RDB$COMPLEX_NAME.NULL = TRUE;
X.RDB$UPDATE_FLAG.NULL = TRUE;
X.RDB$DEFAULT_SOURCE.NULL = TRUE;
X.RDB$DEFAULT_VALUE.NULL = TRUE;
X.RDB$NULL_FLAG.NULL = TRUE;
X.RDB$COLLATION_ID.NULL = TRUE;
// ODS 12
X.RDB$GENERATOR_NAME.NULL = TRUE;
X.RDB$IDENTITY_TYPE.NULL = TRUE;
skip_init(&scan_next_attr);
while (get_attribute(&attribute, tdgbl) != att_end)
{
case att_field_name:
field->fld_name_length = GET_TEXT(field->fld_name);
BURP_verbose (115, field->fld_name);
// msg 115 restoring field %s
strcpy (X.RDB$FIELD_NAME, field->fld_name);
break;
case att_field_source:
GET_TEXT(X.RDB$FIELD_SOURCE);
break;
case att_field_security_class:
GET_TEXT(X.RDB$SECURITY_CLASS);
fix_security_class_name(tdgbl, X.RDB$SECURITY_CLASS, true);
X.RDB$SECURITY_CLASS.NULL = FALSE;
break;
case att_field_query_name:
GET_TEXT(X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
break;
case att_field_query_header:
X.RDB$QUERY_HEADER.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$QUERY_HEADER, global_tr);
break;
case att_field_edit_string:
GET_TEXT(X.RDB$EDIT_STRING);
X.RDB$EDIT_STRING.NULL = FALSE;
break;
case att_field_position:
X.RDB$FIELD_POSITION.NULL = FALSE;
X.RDB$FIELD_POSITION = (USHORT) get_numeric(tdgbl);
break;
case att_field_number:
field->fld_number = (USHORT) get_numeric(tdgbl);
break;
case att_field_type:
field->fld_type = (USHORT) get_numeric(tdgbl);
break;
case att_field_length:
field->fld_length = (USHORT) get_numeric(tdgbl);
break;
case att_field_scale:
field->fld_scale = (USHORT) get_numeric(tdgbl);
break;
case att_field_sub_type:
field->fld_sub_type = (USHORT) get_numeric(tdgbl);
break;
case att_field_system_flag:
X.RDB$SYSTEM_FLAG = (USHORT) get_numeric(tdgbl);
X.RDB$SYSTEM_FLAG.NULL = FALSE;
break;
case att_view_context:
X.RDB$VIEW_CONTEXT = (USHORT) get_numeric(tdgbl);
X.RDB$VIEW_CONTEXT.NULL = FALSE;
break;
case att_field_computed_flag:
if (get_numeric(tdgbl))
field->fld_flags |= FLD_computed;
break;
case att_base_field:
GET_TEXT(X.RDB$BASE_FIELD);
X.RDB$BASE_FIELD.NULL = FALSE;
break;
case att_field_description:
X.RDB$DESCRIPTION.NULL = FALSE;
get_misc_blob (tdgbl, X.RDB$DESCRIPTION, global_tr);
break;
case att_field_description2:
X.RDB$DESCRIPTION.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$DESCRIPTION, global_tr);
break;
case att_field_complex_name:
GET_TEXT(X.RDB$COMPLEX_NAME);
X.RDB$COMPLEX_NAME.NULL = FALSE;
break;
case att_field_dimensions:
switch (skip_scan(&scan_next_attr), attribute)
{
field->fld_dimensions = (USHORT) get_numeric(tdgbl);
field->fld_flags |= FLD_array;
USHORT n = field->fld_dimensions;
for (SLONG* rp = field->fld_ranges; n; rp += 2, n--)
case att_field_name:
field->fld_name_length = GET_TEXT(field->fld_name);
BURP_verbose (115, field->fld_name);
// msg 115 restoring field %s
strcpy (X.RDB$FIELD_NAME, field->fld_name);
break;
case att_field_source:
GET_TEXT(X.RDB$FIELD_SOURCE);
break;
case att_field_security_class:
GET_TEXT(X.RDB$SECURITY_CLASS);
fix_security_class_name(tdgbl, X.RDB$SECURITY_CLASS, true);
X.RDB$SECURITY_CLASS.NULL = FALSE;
break;
case att_field_query_name:
GET_TEXT(X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
break;
case att_field_query_header:
X.RDB$QUERY_HEADER.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$QUERY_HEADER, global_tr);
break;
case att_field_edit_string:
GET_TEXT(X.RDB$EDIT_STRING);
X.RDB$EDIT_STRING.NULL = FALSE;
break;
case att_field_position:
X.RDB$FIELD_POSITION.NULL = FALSE;
X.RDB$FIELD_POSITION = (USHORT) get_numeric(tdgbl);
break;
case att_field_number:
field->fld_number = (USHORT) get_numeric(tdgbl);
break;
case att_field_type:
field->fld_type = (USHORT) get_numeric(tdgbl);
break;
case att_field_length:
field->fld_length = (USHORT) get_numeric(tdgbl);
break;
case att_field_scale:
field->fld_scale = (USHORT) get_numeric(tdgbl);
break;
case att_field_sub_type:
field->fld_sub_type = (USHORT) get_numeric(tdgbl);
break;
case att_field_system_flag:
X.RDB$SYSTEM_FLAG = (USHORT) get_numeric(tdgbl);
X.RDB$SYSTEM_FLAG.NULL = FALSE;
break;
case att_view_context:
X.RDB$VIEW_CONTEXT = (USHORT) get_numeric(tdgbl);
X.RDB$VIEW_CONTEXT.NULL = FALSE;
break;
case att_field_computed_flag:
if (get_numeric(tdgbl))
field->fld_flags |= FLD_computed;
break;
case att_base_field:
GET_TEXT(X.RDB$BASE_FIELD);
X.RDB$BASE_FIELD.NULL = FALSE;
break;
case att_field_description:
X.RDB$DESCRIPTION.NULL = FALSE;
get_misc_blob (tdgbl, X.RDB$DESCRIPTION, global_tr);
break;
case att_field_description2:
X.RDB$DESCRIPTION.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$DESCRIPTION, global_tr);
break;
case att_field_complex_name:
GET_TEXT(X.RDB$COMPLEX_NAME);
X.RDB$COMPLEX_NAME.NULL = FALSE;
break;
case att_field_dimensions:
{
if (get_attribute(&attribute, tdgbl) != att_field_range_low)
bad_attribute(scan_next_attr, attribute, 58);
// msg 58 array
else
*rp = get_numeric(tdgbl);
if (get_attribute(&attribute, tdgbl) != att_field_range_high)
bad_attribute(scan_next_attr, attribute, 58);
field->fld_dimensions = (USHORT) get_numeric(tdgbl);
field->fld_flags |= FLD_array;
USHORT n = field->fld_dimensions;
for (SLONG* rp = field->fld_ranges; n; rp += 2, n--)
{
if (get_attribute(&attribute, tdgbl) != att_field_range_low)
bad_attribute(scan_next_attr, attribute, 58);
// msg 58 array
else
*(rp + 1) = get_numeric(tdgbl);
else
*rp = get_numeric(tdgbl);
if (get_attribute(&attribute, tdgbl) != att_field_range_high)
bad_attribute(scan_next_attr, attribute, 58);
// msg 58 array
else
*(rp + 1) = get_numeric(tdgbl);
}
}
break;
case att_field_update_flag:
X.RDB$UPDATE_FLAG.NULL = FALSE;
X.RDB$UPDATE_FLAG = (USHORT) get_numeric(tdgbl);
break;
case att_field_character_length:
field->fld_character_length = (USHORT) get_numeric(tdgbl);
break;
case att_field_default_source:
X.RDB$DEFAULT_SOURCE.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$DEFAULT_SOURCE, global_tr);
break;
case att_field_default_value:
X.RDB$DEFAULT_VALUE.NULL = FALSE;
get_blr_blob (tdgbl, X.RDB$DEFAULT_VALUE, global_tr);
break;
case att_field_null_flag:
if (tdgbl->gbl_sw_novalidity) {
get_numeric(tdgbl); // skip
}
else
{
X.RDB$NULL_FLAG.NULL = FALSE;
X.RDB$NULL_FLAG = (USHORT) get_numeric(tdgbl);
}
break;
case att_field_character_set:
field->fld_character_set_id = (USHORT) get_numeric(tdgbl);
break;
case att_field_collation_id:
field->fld_collation_id = (USHORT) get_numeric(tdgbl);
X.RDB$COLLATION_ID.NULL = FALSE;
X.RDB$COLLATION_ID = field->fld_collation_id;
break;
// ODS 12
case att_field_generator_name:
GET_TEXT(X.RDB$GENERATOR_NAME);
X.RDB$GENERATOR_NAME.NULL = FALSE;
break;
case att_field_identity_type:
X.RDB$IDENTITY_TYPE.NULL = FALSE;
X.RDB$IDENTITY_TYPE = (SSHORT) get_numeric(tdgbl);
break;
default:
bad_attribute(scan_next_attr, attribute, 84);
// msg 84 column
break;
}
break;
case att_field_update_flag:
X.RDB$UPDATE_FLAG.NULL = FALSE;
X.RDB$UPDATE_FLAG = (USHORT) get_numeric(tdgbl);
break;
case att_field_character_length:
field->fld_character_length = (USHORT) get_numeric(tdgbl);
break;
case att_field_default_source:
X.RDB$DEFAULT_SOURCE.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$DEFAULT_SOURCE, global_tr);
break;
case att_field_default_value:
X.RDB$DEFAULT_VALUE.NULL = FALSE;
get_blr_blob (tdgbl, X.RDB$DEFAULT_VALUE, global_tr);
break;
case att_field_null_flag:
if (tdgbl->gbl_sw_novalidity) {
get_numeric(tdgbl); // skip
}
else
{
X.RDB$NULL_FLAG.NULL = FALSE;
X.RDB$NULL_FLAG = (USHORT) get_numeric(tdgbl);
}
break;
case att_field_character_set:
field->fld_character_set_id = (USHORT) get_numeric(tdgbl);
break;
case att_field_collation_id:
field->fld_collation_id = (USHORT) get_numeric(tdgbl);
X.RDB$COLLATION_ID.NULL = FALSE;
X.RDB$COLLATION_ID = field->fld_collation_id;
break;
default:
bad_attribute(scan_next_attr, attribute, 84);
// msg 84 column
break;
}
}
END_STORE
ON_ERROR
general_on_error();
END_ERROR
}
else
{
STORE (TRANSACTION_HANDLE local_trans REQUEST_HANDLE tdgbl->handles_get_field_req_handle1)
X IN RDB$RELATION_FIELDS
{
strcpy (X.RDB$RELATION_NAME, relation->rel_name);
X.RDB$FIELD_POSITION = 0;
memset (X.RDB$QUERY_NAME, ' ', sizeof(X.RDB$QUERY_NAME));
X.RDB$VIEW_CONTEXT.NULL = TRUE;
X.RDB$BASE_FIELD.NULL = TRUE;
X.RDB$SECURITY_CLASS.NULL = TRUE;
X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$QUERY_HEADER.NULL = TRUE;
X.RDB$EDIT_STRING.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$FIELD_POSITION.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
X.RDB$COMPLEX_NAME.NULL = TRUE;
X.RDB$UPDATE_FLAG.NULL = TRUE;
X.RDB$DEFAULT_SOURCE.NULL = TRUE;
X.RDB$DEFAULT_VALUE.NULL = TRUE;
X.RDB$NULL_FLAG.NULL = TRUE;
X.RDB$COLLATION_ID.NULL = TRUE;
END_STORE;
ON_ERROR
general_on_error ();
END_ERROR;
skip_init(&scan_next_attr);
while (get_attribute(&attribute, tdgbl) != att_end)
{
switch (skip_scan(&scan_next_attr), attribute)
{
case att_field_name:
field->fld_name_length = GET_TEXT(field->fld_name);
BURP_verbose (115, field->fld_name);
// msg 115 restoring field %s
strcpy (X.RDB$FIELD_NAME, field->fld_name);
break;
case att_field_source:
GET_TEXT(X.RDB$FIELD_SOURCE);
break;
case att_field_security_class:
GET_TEXT(X.RDB$SECURITY_CLASS);
fix_security_class_name(tdgbl, X.RDB$SECURITY_CLASS, true);
X.RDB$SECURITY_CLASS.NULL = FALSE;
break;
case att_field_query_name:
GET_TEXT(X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
break;
case att_field_query_header:
X.RDB$QUERY_HEADER.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$QUERY_HEADER, global_tr);
break;
case att_field_edit_string:
GET_TEXT(X.RDB$EDIT_STRING);
X.RDB$EDIT_STRING.NULL = FALSE;
break;
case att_field_position:
X.RDB$FIELD_POSITION.NULL = FALSE;
X.RDB$FIELD_POSITION = (USHORT) get_numeric(tdgbl);
break;
case att_field_number:
field->fld_number = (USHORT) get_numeric(tdgbl);
break;
case att_field_type:
field->fld_type = (USHORT) get_numeric(tdgbl);
break;
case att_field_length:
field->fld_length = (USHORT) get_numeric(tdgbl);
break;
case att_field_scale:
field->fld_scale = (USHORT) get_numeric(tdgbl);
break;
case att_field_sub_type:
field->fld_sub_type = (USHORT) get_numeric(tdgbl);
break;
case att_field_system_flag:
X.RDB$SYSTEM_FLAG = (USHORT) get_numeric(tdgbl);
X.RDB$SYSTEM_FLAG.NULL = FALSE;
break;
case att_view_context:
X.RDB$VIEW_CONTEXT = (USHORT) get_numeric(tdgbl);
X.RDB$VIEW_CONTEXT.NULL = FALSE;
break;
case att_field_computed_flag:
if (get_numeric(tdgbl))
field->fld_flags |= FLD_computed;
break;
case att_base_field:
GET_TEXT(X.RDB$BASE_FIELD);
X.RDB$BASE_FIELD.NULL = FALSE;
break;
case att_field_description:
X.RDB$DESCRIPTION.NULL = FALSE;
get_misc_blob (tdgbl, X.RDB$DESCRIPTION, global_tr);
break;
case att_field_description2:
X.RDB$DESCRIPTION.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$DESCRIPTION, global_tr);
break;
case att_field_complex_name:
GET_TEXT(X.RDB$COMPLEX_NAME);
X.RDB$COMPLEX_NAME.NULL = FALSE;
break;
case att_field_dimensions:
{
field->fld_dimensions = (USHORT) get_numeric(tdgbl);
field->fld_flags |= FLD_array;
USHORT n = field->fld_dimensions;
for (SLONG* rp = field->fld_ranges; n; rp += 2, n--)
{
if (get_attribute(&attribute, tdgbl) != att_field_range_low)
bad_attribute(scan_next_attr, attribute, 58);
// msg 58 array
else
*rp = get_numeric(tdgbl);
if (get_attribute(&attribute, tdgbl) != att_field_range_high)
bad_attribute(scan_next_attr, attribute, 58);
// msg 58 array
else
*(rp + 1) = get_numeric(tdgbl);
}
}
break;
case att_field_update_flag:
X.RDB$UPDATE_FLAG.NULL = FALSE;
X.RDB$UPDATE_FLAG = (USHORT) get_numeric(tdgbl);
break;
case att_field_character_length:
field->fld_character_length = (USHORT) get_numeric(tdgbl);
break;
case att_field_default_source:
X.RDB$DEFAULT_SOURCE.NULL = FALSE;
get_source_blob (tdgbl, X.RDB$DEFAULT_SOURCE, global_tr);
break;
case att_field_default_value:
X.RDB$DEFAULT_VALUE.NULL = FALSE;
get_blr_blob (tdgbl, X.RDB$DEFAULT_VALUE, global_tr);
break;
case att_field_null_flag:
if (tdgbl->gbl_sw_novalidity) {
get_numeric(tdgbl); // skip
}
else
{
X.RDB$NULL_FLAG.NULL = FALSE;
X.RDB$NULL_FLAG = (USHORT) get_numeric(tdgbl);
}
break;
case att_field_character_set:
field->fld_character_set_id = (USHORT) get_numeric(tdgbl);
break;
case att_field_collation_id:
field->fld_collation_id = (USHORT) get_numeric(tdgbl);
X.RDB$COLLATION_ID.NULL = FALSE;
X.RDB$COLLATION_ID = field->fld_collation_id;
break;
default:
bad_attribute(scan_next_attr, attribute, 84);
// msg 84 column
break;
}
}
}
END_STORE
ON_ERROR
general_on_error();
END_ERROR
}
return field;
}
@ -4832,6 +5045,7 @@ bool get_generator(BurpGlobals* tdgbl)
BASED_ON RDB$GENERATORS.RDB$GENERATOR_NAME name = "";
BASED_ON RDB$GENERATORS.RDB$SECURITY_CLASS secclass = "";
BASED_ON RDB$GENERATORS.RDB$OWNER_NAME ownername = "";
fb_sysflag sysFlag = fb_sysflag_user;
att_type attribute;
scan_attr_t scan_next_attr;
@ -4871,6 +5085,10 @@ bool get_generator(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 289);
break;
case att_gen_sysflag:
sysFlag = (fb_sysflag) get_numeric(tdgbl);
break;
case att_gen_security_class:
if (tdgbl->RESTORE_format >= 10)
{
@ -4903,7 +5121,7 @@ bool get_generator(BurpGlobals* tdgbl)
value = 0;
}
store_blr_gen_id(tdgbl, name, value, descPtr, secPtr, ownerPtr);
store_blr_gen_id(tdgbl, name, value, descPtr, secPtr, ownerPtr, sysFlag);
return true;
}
@ -7429,7 +7647,7 @@ bool get_relation_data(BurpGlobals* tdgbl)
case rec_gen_id:
gen_id = get_numeric(tdgbl);
store_blr_gen_id(tdgbl, name, gen_id, NULL, NULL, NULL);
store_blr_gen_id(tdgbl, name, gen_id, NULL, NULL, NULL, fb_sysflag_user);
get_record(&record, tdgbl);
break;
@ -9776,7 +9994,7 @@ USHORT get_view_base_relation_count(BurpGlobals* tdgbl,
void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value,
const ISC_QUAD* gen_desc, const char* secclass, const char* ownername)
const ISC_QUAD* gen_desc, const char* secclass, const char* ownername, fb_sysflag sysFlag)
{
/**************************************
*
@ -9795,8 +10013,7 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value,
strcpy (X.RDB$GENERATOR_NAME, gen_name);
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
X.RDB$SYSTEM_FLAG = (SSHORT) sysFlag;
X.RDB$SECURITY_CLASS.NULL = TRUE;
X.RDB$OWNER_NAME.NULL = TRUE;
if (gen_desc)

View File

@ -2800,7 +2800,14 @@ void CreateSequenceNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
void CreateSequenceNode::execute(thread_db* tdbb, jrd_tra* transaction)
{
executeDdlTrigger(tdbb, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE, name);
store(tdbb, transaction, name, fb_sysflag_user);
executeDdlTrigger(tdbb, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE, name);
}
void CreateSequenceNode::store(thread_db* tdbb, jrd_tra* transaction, const MetaName& name,
fb_sysflag sysFlag)
{
bool endStore = false;
try
@ -2824,7 +2831,7 @@ void CreateSequenceNode::execute(thread_db* tdbb, jrd_tra* transaction)
X IN RDB$GENERATORS
{
X.RDB$GENERATOR_ID = id;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG = (SSHORT) sysFlag;
strcpy(X.RDB$GENERATOR_NAME, name.c_str());
endStore = true;
@ -2850,8 +2857,6 @@ void CreateSequenceNode::execute(thread_db* tdbb, jrd_tra* transaction)
{
rethrowMetaException(ex, ENCODE_ISC_MSG(8, DYN_MSG_FAC), endStore); // DEFINE GENERATOR failed
}
executeDdlTrigger(tdbb, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE, name);
}

View File

@ -609,6 +609,10 @@ public:
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
public:
static void store(thread_db* tdbb, jrd_tra* transaction, const Firebird::MetaName& name,
fb_sysflag sysFlag);
private:
Firebird::MetaName name;
};

View File

@ -1913,6 +1913,15 @@ static void define_field(DsqlCompilerScratch* dsqlScratch,
define_dimensions(dsqlScratch, field);
}
// check for constraints
bool not_null_flag = false;
if (element->nod_arg[e_dfl_identity])
{
not_null_flag = true; // identity columns are implicitly not null
statement->append_uchar(isc_dyn_fld_identity);
}
// dimitr: store the final position of the vector to insert a not null
// item later, if required. This is a kind of a hack, but I see
// no other way to ensure that NOT NULL is properly understood
@ -1924,8 +1933,6 @@ static void define_field(DsqlCompilerScratch* dsqlScratch,
const size_t end = statement->getBlrData().getCount();
statement->append_uchar(isc_dyn_end);
// check for constraints
bool not_null_flag = false;
if ( (node = element->nod_arg[e_dfl_constraint]) )
{
const dsql_nod* const* const end_ptr = node->nod_arg + node->nod_count;

View File

@ -210,6 +210,7 @@ static const TOK tokens[] =
{HASH, "HASH", 2, false},
{HAVING, "HAVING", 1, false},
{HOUR, "HOUR", 2, false},
{IDENTITY, "IDENTITY", 2, false},
{IF, "IF", 1, false},
{KW_IGNORE, "IGNORE", 2, true},
{IIF, "IIF", 2, true},

View File

@ -628,6 +628,7 @@ enum node_args {
e_dfl_collate,
e_dfl_domain,
e_dfl_computed,
e_dfl_identity,
e_dfl_count,
e_view_name = 0, // nod_def_view

View File

@ -573,6 +573,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%token <legacyNode> ATANH
%token <legacyNode> RETURN
%token <legacyNode> DETERMINISTIC
%token <legacyNode> IDENTITY
// precedence declarations for expression evaluation
@ -688,14 +689,14 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyStr> firstname_opt
%type <int32Val> first_file_length
%type <legacyNode> grant grant_option granted_by granted_by_text grantee grantee_list
%type <legacyNode> generated_always_clause grant grant_option granted_by granted_by_text grantee grantee_list
%type <legacyNode> grantor group_by_item group_by_list group_clause gtt_recreate_clause gtt_scope
%type <legacyNode> gtt_table_clause
%type <legacyStr> grant_admin grant_admin_opt
%type <legacyNode> having_clause
%type <legacyNode> in_predicate in_predicate_value
%type <legacyNode> identity_clause in_predicate in_predicate_value
%type <legacyNode> index_definition index_list init_alter_db
%type <legacyNode> ins_column_list ins_column_parens
%type <legacyNode> ins_column_parens_opt insert integer_keyword internal_info
@ -1642,17 +1643,21 @@ table_element : column_def
// column definition
column_def : column_def_name data_type_or_domain domain_default_opt
column_constraint_clause collate_clause
{ $$ = make_node (nod_def_field, (int) e_dfl_count,
$1, $3, make_list ($4), $5, $2, NULL); }
| column_def_name non_array_type def_computed
{ $$ = make_node (nod_def_field, (int) e_dfl_count,
$1, NULL, NULL, NULL, NULL, $3); }
| column_def_name def_computed
{ $$ = make_node (nod_def_field, (int) e_dfl_count,
$1, NULL, NULL, NULL, NULL, $2); }
;
column_def
: column_def_name data_type_or_domain domain_default_opt column_constraint_clause collate_clause
{ $$ = make_node(nod_def_field, (int) e_dfl_count, $1, $3, make_list($4), $5, $2, NULL, NULL); }
| column_def_name data_type_or_domain identity_clause column_constraint_clause collate_clause
{ $$ = make_node(nod_def_field, (int) e_dfl_count, $1, NULL, make_list($4), $5, $2, NULL, $3); }
| column_def_name non_array_type def_computed
{ $$ = make_node(nod_def_field, (int) e_dfl_count, $1, NULL, NULL, NULL, NULL, $3, NULL); }
| column_def_name def_computed
{ $$ = make_node(nod_def_field, (int) e_dfl_count, $1, NULL, NULL, NULL, NULL, $2, NULL); }
;
identity_clause
: GENERATED BY DEFAULT AS IDENTITY
{ $$ = make_node(nod_flag, 0, NULL); }
;
// value does allow parens around it, but there is a problem getting the source text.
@ -1663,13 +1668,19 @@ def_computed : computed_clause '(' begin_trigger value end_trigger ')'
}
;
computed_clause : computed_by
| GENERATED ALWAYS AS
;
computed_clause
: computed_by
| generated_always_clause
;
computed_by : COMPUTED BY
| COMPUTED
;
generated_always_clause
: GENERATED ALWAYS AS
;
computed_by
: COMPUTED BY
| COMPUTED
;
data_type_or_domain : data_type
{ $$ = NULL; }
@ -2157,7 +2168,7 @@ local_declaration_item : var_declaration_item
;
var_declaration_item : column_def_name domain_or_non_array_type collate_clause default_par_opt
{ $$ = make_node (nod_def_field, (int) e_dfl_count, $1, $4, NULL, $3, NULL, NULL); }
{ $$ = make_node (nod_def_field, (int) e_dfl_count, $1, $4, NULL, $3, NULL, NULL, NULL); }
;
var_decl_opt : VARIABLE
@ -2623,7 +2634,7 @@ block_parameter
block_proc_parameter
: simple_column_def_name domain_or_non_array_type collate_clause
{ $$ = make_node (nod_def_field, (int) e_dfl_count, $1, NULL, NULL, $3, NULL, NULL); }
{ $$ = make_node (nod_def_field, (int) e_dfl_count, $1, NULL, NULL, $3, NULL, NULL, NULL); }
;
// CREATE VIEW
@ -5920,6 +5931,7 @@ non_reserved_word :
| CONTINUE
| DDL
| ENGINE
| IDENTITY
| NAME
| PACKAGE
| PRIOR

View File

@ -202,6 +202,7 @@
#define isc_dyn_fld_base_fld 91
#define isc_dyn_fld_position 92
#define isc_dyn_fld_update_flag 93
#define isc_dyn_fld_identity 253
/*****************************/
/* Index specific attributes */
@ -420,6 +421,6 @@
/****************************/
/* Last $dyn value assigned */
/****************************/
//#define isc_dyn_last_dyn_value 253
//#define isc_dyn_last_dyn_value 254
#endif // INCLUDE_DYN_CONSTS_H

View File

@ -121,6 +121,8 @@
const USHORT f_rfr_null_flag = 16;
const USHORT f_rfr_dsource = 17;
const USHORT f_rfr_coll_id = 18;
const USHORT f_rfr_gen_name = 19;
const USHORT f_rfr_identity_type = 20;
// Relation 6 (RDB$RELATIONS)

View File

@ -506,6 +506,22 @@ int EXTRACT_list_table(const SCHAR* relation_name,
SHOW_print_metadata_text_blob (isqlGlob.Out, &RFR.RDB$DEFAULT_SOURCE);
}
if (ENCODE_ODS(isqlGlob.major_ods, isqlGlob.minor_ods) >= ODS_12_0)
{
FOR RFR2 IN RDB$RELATION_FIELDS
WITH RFR2.RDB$RELATION_NAME = RFR.RDB$RELATION_NAME AND
RFR2.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME
{
if (!RFR2.RDB$GENERATOR_NAME.NULL)
isqlGlob.printf(" GENERATED BY DEFAULT AS IDENTITY");
}
END_FOR
ON_ERROR
ISQL_errmsg(isc_status);
return ps_ERR;
END_ERROR
}
/* The null flag is either 1 or null (for nullable) . if there is
** a constraint name, print that too. Domains cannot have named
** constraints. The column name is in rdb$trigger_name in

View File

@ -4463,6 +4463,22 @@ static processing_state show_table(const SCHAR* relation_name, bool isView)
isqlGlob.printf(" Nullable ");
}
if (ENCODE_ODS(isqlGlob.major_ods, isqlGlob.minor_ods) >= ODS_12_0)
{
FOR RFR2 IN RDB$RELATION_FIELDS
WITH RFR2.RDB$RELATION_NAME = RFR.RDB$RELATION_NAME AND
RFR2.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME
{
if (!RFR2.RDB$GENERATOR_NAME.NULL)
isqlGlob.printf("Identity (by default)");
}
END_FOR
ON_ERROR
ISQL_errmsg(isc_status);
return ps_ERR;
END_ERROR
}
// Handle defaults for columns
if (!RFR.RDB$DEFAULT_SOURCE.NULL)

View File

@ -336,10 +336,11 @@ public:
ArrayField* fld_array; // array description, if array
Firebird::MetaName fld_name; // Field name
Firebird::MetaName fld_security_name; // security class name for field
Firebird::MetaName fld_generator_name; // identity generator name
public:
explicit jrd_fld(MemoryPool& p)
: fld_name(p), fld_security_name(p)
: fld_name(p), fld_security_name(p), fld_generator_name(p)
{ }
};

View File

@ -3057,7 +3057,7 @@ static jrd_nod* copy(thread_db* tdbb,
node->nod_type = input->nod_type;
node->nod_arg[e_gen_value] =
copy(tdbb, csb, input->nod_arg[e_gen_value], remap, field_id, message, remap_fld);
node->nod_arg[e_gen_relation] = input->nod_arg[e_gen_relation];
node->nod_arg[e_gen_id] = input->nod_arg[e_gen_id];
return (node);
case nod_cast:
@ -3571,51 +3571,77 @@ static jrd_nod* make_defaults(thread_db* tdbb, CompilerScratch* csb, USHORT stre
for (const vec<jrd_fld*>::const_iterator end = vector->end(); ptr1 < end; ++ptr1, ++field_id)
{
jrd_nod* value;
if (*ptr1 && (value = (*ptr1)->fld_default_value))
if (!*ptr1 || !((*ptr1)->fld_generator_name.hasData() || (value = (*ptr1)->fld_default_value)))
continue;
fb_assert(statement->nod_type == nod_list);
if (statement->nod_type == nod_list)
{
fb_assert(statement->nod_type == nod_list);
if (statement->nod_type == nod_list)
bool inList = false;
for (unsigned i = 0; i < statement->nod_count; ++i)
{
bool inList = false;
const jrd_nod* assign = statement->nod_arg[i];
for (unsigned i = 0; i < statement->nod_count; ++i)
fb_assert(assign->nod_type == nod_assignment);
if (assign->nod_type == nod_assignment)
{
const jrd_nod* assign = statement->nod_arg[i];
const jrd_nod* to = assign->nod_arg[e_asgn_to];
fb_assert(assign->nod_type == nod_assignment);
if (assign->nod_type == nod_assignment)
fb_assert(to->nod_type == nod_field);
if (to->nod_type == nod_field &&
(USHORT)(IPTR) to->nod_arg[e_fld_stream] == stream &&
(USHORT)(IPTR) to->nod_arg[e_fld_id] == field_id)
{
const jrd_nod* to = assign->nod_arg[e_asgn_to];
fb_assert(to->nod_type == nod_field);
if (to->nod_type == nod_field &&
(USHORT)(IPTR) to->nod_arg[e_fld_stream] == stream &&
(USHORT)(IPTR) to->nod_arg[e_fld_id] == field_id)
{
inList = true;
break;
}
inList = true;
break;
}
}
if (inList)
continue;
}
if (inList)
continue;
jrd_nod* node = PAR_make_node(tdbb, e_asgn_length);
node->nod_type = nod_assignment;
node->nod_arg[e_asgn_from] =
copy(tdbb, csb, value, map, (USHORT) (field_id + 1), NULL, false);
node->nod_arg[e_asgn_to] = PAR_gen_field(tdbb, stream, field_id);
stack.push(node);
if ((*ptr1)->fld_generator_name.hasData())
{
// Make a gen_id(<generator name>, 1) expression.
jrd_nod* genNode = PAR_make_node(tdbb, e_gen_length);
genNode->nod_type = nod_gen_id;
genNode->nod_count = 1;
const SLONG tmp = MET_lookup_generator(tdbb, (*ptr1)->fld_generator_name.c_str());
genNode->nod_arg[e_gen_id] = (jrd_nod*)(IPTR) tmp;
const int count = lit_delta + (sizeof(SLONG) + sizeof(jrd_nod*) - 1) / sizeof(jrd_nod*);
jrd_nod* literalNode = genNode->nod_arg[e_gen_value] = PAR_make_node(tdbb, count);
literalNode->nod_type = nod_literal;
literalNode->nod_count = 0;
Literal* literal = (Literal*) literalNode;
literal->lit_desc.makeLong(0, (SLONG*) literal->lit_data);
*(SLONG*) literal->lit_data = 1;
node->nod_arg[e_asgn_from] = genNode;
}
else //if (value)
{
// Clone the field default value.
node->nod_arg[e_asgn_from] = copy(tdbb, csb, value,
map, (USHORT) (field_id + 1), NULL, false);
}
}
}
if (stack.isEmpty())
return statement;
// we have some default - add the original statement and make a list out of
// the whole mess
// We have some default - add the original statement and make a list out of the whole mess.
stack.push(statement);

View File

@ -141,7 +141,8 @@ enum fb_sysflag {
fb_sysflag_qli = 2,
fb_sysflag_check_constraint = 3,
fb_sysflag_referential_constraint = 4,
fb_sysflag_view_check = 5
fb_sysflag_view_check = 5,
fb_sysflag_identity_generator = 6
};
enum ViewContextType {
@ -150,6 +151,11 @@ enum ViewContextType {
VCT_PROCEDURE
};
enum IdentityType {
IDENT_TYPE_ALWAYS,
IDENT_TYPE_BY_DEFAULT
};
// UDF Arguments are numbered from 0 to MAX_UDF_ARGUMENTS --
// argument 0 is reserved for the return-type of the UDF

View File

@ -5320,8 +5320,17 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
n = fb_utils::name_length(RFR.RDB$SECURITY_CLASS);
if (!RFR.RDB$SECURITY_CLASS.NULL && n)
{
put_summary_record(tdbb, blob, RSR_security_class,
(UCHAR*) RFR.RDB$SECURITY_CLASS, n);
}
n = fb_utils::name_length(RFR.RDB$GENERATOR_NAME);
if (!RFR.RDB$GENERATOR_NAME.NULL && n)
{
put_summary_record(tdbb, blob, RSR_field_generator_name,
(UCHAR*) RFR.RDB$GENERATOR_NAME, n);
}
// Make a temporary field block

View File

@ -229,6 +229,10 @@ enum drq_type_t
drq_e_prm_gfld, // erase parameter source
drq_e_prm_gfld2, // erase parameter source
drq_g_nxt_sec_id, // lookup next security class ID
drq_f_nxt_gen, // find next generator name
drq_g_nxt_gen, // generate next generator name
drq_e_ident_gens, // erase generators (identity column)
drq_l_ident_gens, // lookup generators (identity column)
drq_MAX
};

View File

@ -2415,10 +2415,13 @@ void DYN_define_local_field(Global* gbl,
RFR.RDB$DEFAULT_SOURCE.NULL = TRUE;
RFR.RDB$EDIT_STRING.NULL = TRUE;
RFR.RDB$COLLATION_ID.NULL = TRUE;
RFR.RDB$GENERATOR_NAME.NULL = TRUE;
RFR.RDB$IDENTITY_TYPE.NULL = TRUE;
bool has_default = false;
while ((verb = *(*ptr)++) != isc_dyn_end)
{
switch (verb)
{
case isc_dyn_rel_name:
@ -2501,6 +2504,22 @@ void DYN_define_local_field(Global* gbl,
DYN_put_text_blob(gbl, ptr, &RFR.RDB$DEFAULT_SOURCE);
break;
case isc_dyn_fld_identity:
{
MetaName sequenceName;
DYN_UTIL_generate_generator_name(tdbb, sequenceName);
CreateSequenceNode::store(tdbb, gbl->gbl_transaction, sequenceName,
fb_sysflag_identity_generator);
strcpy(RFR.RDB$GENERATOR_NAME, sequenceName.c_str());
RFR.RDB$GENERATOR_NAME.NULL = FALSE;
RFR.RDB$IDENTITY_TYPE = IDENT_TYPE_BY_DEFAULT;
RFR.RDB$IDENTITY_TYPE.NULL = FALSE;
break;
}
case isc_dyn_fld_not_null:
RFR.RDB$NULL_FLAG.NULL = FALSE;
RFR.RDB$NULL_FLAG = TRUE;
@ -2554,6 +2573,7 @@ void DYN_define_local_field(Global* gbl,
MetaTmp(RFR.RDB$FIELD_SOURCE)
DYN_execute(gbl, ptr, relation_name, &tmp, NULL, NULL, NULL);
}
}
if (has_default && DYN_UTIL_is_array(tdbb, gbl, RFR.RDB$FIELD_SOURCE))
{
@ -2561,6 +2581,19 @@ void DYN_define_local_field(Global* gbl,
// msg 226: "Default value is not allowed for array type in domain %s"
}
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
dsc desc;
MET_get_domain(tdbb, RFR.RDB$FIELD_SOURCE, &desc, NULL);
if (!desc.isExact() || desc.dsc_scale != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
DYN_error_punt(false, 273,
SafeArg() << local_field_name.c_str() << relation_name->c_str());
}
}
if (RFR.RDB$FIELD_POSITION.NULL == TRUE)
{
fld_pos = -1;
@ -3102,6 +3135,8 @@ void DYN_define_sql_field(Global* gbl,
RFR.RDB$DEFAULT_SOURCE.NULL = TRUE;
RFR.RDB$DEFAULT_VALUE.NULL = TRUE;
RFR.RDB$COLLATION_ID.NULL = TRUE;
RFR.RDB$GENERATOR_NAME.NULL = TRUE;
RFR.RDB$IDENTITY_TYPE.NULL = TRUE;
old_request = request;
const SSHORT old_id = id;
@ -3134,7 +3169,9 @@ void DYN_define_sql_field(Global* gbl,
DYN_UTIL_generate_field_name(tdbb, gbl, RFR.RDB$FIELD_SOURCE);
strcpy(FLD.RDB$FIELD_NAME, RFR.RDB$FIELD_SOURCE);
while ((verb = *(*ptr)++) != isc_dyn_end)
{
switch (verb)
{
case isc_dyn_rel_name:
@ -3212,6 +3249,22 @@ void DYN_define_sql_field(Global* gbl,
DYN_put_blr_blob(gbl, ptr, &FLD.RDB$VALIDATION_BLR);
break;
case isc_dyn_fld_identity:
{
MetaName sequenceName;
DYN_UTIL_generate_generator_name(tdbb, sequenceName);
CreateSequenceNode::store(tdbb, gbl->gbl_transaction, sequenceName,
fb_sysflag_identity_generator);
strcpy(RFR.RDB$GENERATOR_NAME, sequenceName.c_str());
RFR.RDB$GENERATOR_NAME.NULL = FALSE;
RFR.RDB$IDENTITY_TYPE = IDENT_TYPE_BY_DEFAULT;
RFR.RDB$IDENTITY_TYPE.NULL = FALSE;
break;
}
case isc_dyn_fld_not_null:
RFR.RDB$NULL_FLAG.NULL = FALSE;
RFR.RDB$NULL_FLAG = TRUE;
@ -3307,6 +3360,20 @@ void DYN_define_sql_field(Global* gbl,
MetaTmp(RFR.RDB$FIELD_SOURCE)
DYN_execute(gbl, ptr, relation_name, &tmp, NULL, NULL, NULL);
}
}
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
bool exact = FLD.RDB$FIELD_TYPE == blr_short || FLD.RDB$FIELD_TYPE == blr_long ||
FLD.RDB$FIELD_TYPE == blr_int64;
if (!exact || FLD.RDB$FIELD_SCALE != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
DYN_error_punt(false, 273,
SafeArg() << sql_field_name.c_str() << relation_name->c_str());
}
}
if (RFR.RDB$FIELD_POSITION.NULL == TRUE)
{

View File

@ -74,6 +74,8 @@ static void delete_f_key_constraint(thread_db*, Global*,
const Firebird::MetaName&, const Firebird::MetaName&,
const Firebird::MetaName&, const Firebird::MetaName&);
static void delete_gfield_for_lfield(Global*, const Firebird::MetaName&);
static void delete_identity_generator(thread_db* tdbb, jrd_tra* transaction,
const MetaName& generatorName);
static bool delete_index_segment_records(Global*, const Firebird::MetaName&);
@ -460,6 +462,12 @@ void DYN_delete_generator(Global* gbl, const UCHAR**ptr)
if (!DYN_REQUEST(drq_e_gens))
DYN_REQUEST(drq_e_gens) = request;
if (X.RDB$SYSTEM_FLAG != 0)
{
DYN_rundown_request(request, -1);
DYN_error_punt(false, 272); // msg 272: "Cannot delete system generator"
}
found = true;
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
@ -736,6 +744,7 @@ void DYN_delete_local_field(Global* gbl, const UCHAR** ptr, const Firebird::Meta
GET_STRING(ptr, tbl_nm);
jrd_req* request = CMP_find_request(tdbb, drq_l_dep_flds, DYN_REQUESTS);
jrd_req* request2 = NULL;
USHORT id = drq_l_dep_flds;
bool found;
@ -847,6 +856,9 @@ void DYN_delete_local_field(Global* gbl, const UCHAR** ptr, const Firebird::Meta
if (!DYN_REQUEST(drq_e_lfield))
DYN_REQUEST(drq_e_lfield) = request;
if (!RFR.RDB$GENERATOR_NAME.NULL)
delete_identity_generator(tdbb, gbl->gbl_transaction, RFR.RDB$GENERATOR_NAME);
ERASE RFR;
if (!RFR.RDB$SECURITY_CLASS.NULL &&
@ -893,6 +905,7 @@ void DYN_delete_local_field(Global* gbl, const UCHAR** ptr, const Firebird::Meta
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_rundown_request(request2, -1);
switch (id)
{
@ -940,7 +953,8 @@ void DYN_delete_relation( Global* gbl, const UCHAR** ptr, const Firebird::MetaNa
else
GET_STRING(ptr, relation_name);
jrd_req* req2 = 0;
jrd_req* req2 = NULL;
jrd_req* req3 = NULL;
jrd_req* request = CMP_find_request(tdbb, drq_l_relation, DYN_REQUESTS);
USHORT id = drq_l_relation;
@ -1044,6 +1058,9 @@ void DYN_delete_relation( Global* gbl, const UCHAR** ptr, const Firebird::MetaNa
if (!DYN_REQUEST(drq_e_rel_flds))
DYN_REQUEST(drq_e_rel_flds) = request;
if (!RFR.RDB$GENERATOR_NAME.NULL)
delete_identity_generator(tdbb, gbl->gbl_transaction, RFR.RDB$GENERATOR_NAME);
ERASE RFR;
if (!RFR.RDB$SECURITY_CLASS.NULL &&
@ -1639,7 +1656,21 @@ static void delete_gfield_for_lfield( Global* gbl, const Firebird::MetaName& lfi
if (!DYN_REQUEST(drq_e_l_gfld))
DYN_REQUEST(drq_e_l_gfld) = request;
}
static void delete_identity_generator(thread_db* tdbb, jrd_tra* transaction,
const MetaName& generatorName)
{
AutoCacheRequest request(tdbb, drq_e_ident_gens, DYN_REQUESTS);
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
GEN IN RDB$GENERATORS
WITH GEN.RDB$GENERATOR_NAME EQ generatorName.c_str()
{
ERASE GEN;
}
END_FOR
}

View File

@ -561,7 +561,6 @@ void DYN_modify_global_field(Global* gbl,
switch (new_dom.dyn_dtype)
{
case blr_text:
case blr_text2:
case blr_varying:
@ -747,9 +746,26 @@ void DYN_modify_global_field(Global* gbl,
new_dom.dyn_sub_type,
new_dom.dyn_charset,
new_dom.dyn_collation);
const ULONG retval = check_update_fld_type(orig_dom, new_dom);
if (retval != FB_SUCCESS)
modify_err_punt(tdbb, retval, orig_dom, new_dom);
if (!new_dom.dyn_dsc.isExact() || new_dom.dyn_dsc.dsc_scale != 0)
{
AutoCacheRequest request(tdbb, drq_l_ident_gens, DYN_REQUESTS);
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
RFR IN RDB$RELATION_FIELDS
WITH RFR.RDB$FIELD_SOURCE = FLD.RDB$FIELD_NAME AND
RFR.RDB$GENERATOR_NAME NOT MISSING
{
// Domain @1 must be of exact number type with zero scale because it's used in
// an identity column.
DYN_error_punt(false, 276, SafeArg() << orig_dom.dyn_fld_name.c_str());
}
END_FOR
}
}
MODIFY FLD USING
@ -1194,7 +1210,15 @@ void DYN_modify_local_field(Global* gbl, const UCHAR** ptr, const MetaName* rela
GET_STRING(&new_source, FLD.RDB$FIELD_SOURCE);
if (nullFlag.isAssigned())
{
if (!nullFlag.asBool() && !FLD.RDB$GENERATOR_NAME.NULL)
{
// msg 274: Identity column @1 of table @2 cannot be changed to NULLable
DYN_error_punt(false, 274, SafeArg() << f.c_str() << r.c_str());
}
FLD.RDB$NULL_FLAG = (SSHORT) nullFlag.asBool();
}
END_MODIFY;
END_FOR;
@ -2166,6 +2190,13 @@ void DYN_modify_sql_field(Global* gbl, const UCHAR** ptr, const MetaName* relati
break;
case isc_dyn_fld_default_value:
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
// msg 275: Identity column @1 of table @2 cannot have default value
DYN_error_punt(false, 275,
SafeArg() << orig_fld.dyn_fld_name.c_str() << relation_name->c_str());
}
if (has_dimensions)
{
DYN_error_punt(false, 225, orig_fld.dyn_fld_name.c_str());
@ -2250,6 +2281,16 @@ void DYN_modify_sql_field(Global* gbl, const UCHAR** ptr, const MetaName* relati
if (!domain_is_computed && !is_view)
{
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
if (!dom_fld.dyn_dsc.isExact() || dom_fld.dyn_dsc.dsc_scale != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
DYN_error_punt(false, 273,
SafeArg() << orig_fld.dyn_fld_name.c_str() << relation_name->c_str());
}
}
const ULONG retval = check_update_fld_type(orig_fld, dom_fld);
if (retval != FB_SUCCESS)
modify_err_punt(tdbb, retval, orig_fld, dom_fld);
@ -2334,6 +2375,16 @@ void DYN_modify_sql_field(Global* gbl, const UCHAR** ptr, const MetaName* relati
const ULONG retval = check_update_fld_type(orig_fld, new_fld);
if (retval != FB_SUCCESS)
modify_err_punt(tdbb, retval, orig_fld, new_fld);
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
if (!new_fld.dyn_dsc.isExact() || new_fld.dyn_dsc.dsc_scale != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
DYN_error_punt(false, 273,
SafeArg() << orig_fld.dyn_fld_name.c_str() << relation_name->c_str());
}
}
}
// Check to see if the original data type for the field was based on a domain. If it

View File

@ -37,6 +37,7 @@ bool DYN_UTIL_find_field_source(Jrd::thread_db* tdbb, Jrd::Global* gbl,
TEXT* output_field_name);
bool DYN_UTIL_get_prot(Jrd::thread_db*, Jrd::Global*, const SCHAR*,
const SCHAR*, Jrd::SecurityClass::flags_t*);
void DYN_UTIL_generate_generator_name(Jrd::thread_db*, Firebird::MetaName&);
void DYN_UTIL_generate_trigger_name(Jrd::thread_db*, Jrd::Global*, Firebird::MetaName&);
void DYN_UTIL_generate_index_name(Jrd::thread_db*, Jrd::Global*, Firebird::MetaName&, UCHAR);
void DYN_UTIL_generate_field_position(Jrd::thread_db*, Jrd::Global*,

View File

@ -554,6 +554,42 @@ void DYN_UTIL_generate_index_name(thread_db* tdbb, Global* /*gbl*/,
}
// Generate a name unique to RDB$GENERATORS.
void DYN_UTIL_generate_generator_name(thread_db* tdbb, Firebird::MetaName& buffer)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
AutoCacheRequest request(tdbb, drq_f_nxt_gen, DYN_REQUESTS);
try
{
bool found = false;
do
{
buffer.printf("RDB$%" SQUADFORMAT,
DYN_UTIL_gen_unique_id(tdbb, drq_g_nxt_gen, "RDB$GENERATOR_NAME"));
found = false;
FOR (REQUEST_HANDLE request)
FIRST 1 X IN RDB$GENERATORS WITH X.RDB$GENERATOR_NAME EQ buffer.c_str()
{
found = true;
}
END_FOR
} while (found);
}
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_rundown_request(request, -1);
DYN_error_punt(true, 277); // msg 277: "Generation of generator name failed"
}
}
void DYN_UTIL_generate_trigger_name( thread_db* tdbb, Global* /*gbl*/, Firebird::MetaName& buffer)
{
/**************************************

View File

@ -339,7 +339,6 @@ const int e_fun_length = 2;
// Generate id
const int e_gen_value = 0;
const int e_gen_relation = 1;
const int e_gen_id = 1; // Generator id (replaces e_gen_relation)
const int e_gen_length = 2;

View File

@ -164,3 +164,5 @@
FIELD(fld_fun_blr , nam_fun_blr , dtype_blob , BLOB_SIZE , isc_blob_blr , NULL , true)
FIELD(fld_arg_name , nam_arg_name , dtype_text , MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , true)
FIELD(fld_arg_mechanism , nam_arg_mechanism , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
FIELD(fld_identity_type , nam_identity_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true)

View File

@ -407,6 +407,14 @@ ISC_STATUS filter_runtime(USHORT action, BlobControl* control)
sprintf(line, " trigger_name: %s", p);
break;
case RSR_field_not_null:
sprintf(line, " field_not_null");
break;
case RSR_field_generator_name:
sprintf(line, " field_generator_name: %s", p);
break;
default:
sprintf(line, "*** unknown verb %d ***", (int) buff[0]);
}

View File

@ -4056,6 +4056,10 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
memcpy(&array->arr_desc, p, length);
break;
case RSR_field_generator_name:
field->fld_generator_name = (const TEXT*) p;
break;
default: // Shut up compiler warning
break;
}

View File

@ -49,7 +49,8 @@ enum rsr_t {
RSR_field_scale, // specific and relate to field info
RSR_field_length,
RSR_field_sub_type,
RSR_field_not_null
RSR_field_not_null,
RSR_field_generator_name
};
// Temporary field block

View File

@ -255,6 +255,7 @@ NAME("RDB$LEGACY_FLAG", nam_legacy_flag)
NAME("RDB$INVARIANT_FLAG", nam_invariant_flag)
NAME("RDB$ARGUMENT_MECHANISM", nam_arg_mechanism)
NAME("RDB$ARGUMENT_NAME", nam_arg_name)
NAME("RDB$IDENTITY_TYPE", nam_identity_type)
NAME("MON$ATTACHMENTS", nam_mon_attachments)
NAME("MON$ATTACHMENT_ID", nam_mon_att_id)

View File

@ -3175,7 +3175,7 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
if (tmp < 0) {
PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(name));
}
node->nod_arg[e_gen_relation] = (jrd_nod*) (IPTR) tmp;
node->nod_arg[e_gen_id] = (jrd_nod*)(IPTR) tmp;
node->nod_arg[e_gen_value] = PAR_parse_node(tdbb, csb, VALUE);
// CVC: There're thousand ways to go wrong, but I don't see any value

View File

@ -120,6 +120,8 @@ RELATION(nam_r_fields, rel_rfr, ODS_8_0, rel_persistent)
FIELD(f_rfr_null_flag, nam_null_flag, fld_null_flag, 1, ODS_8_0)
FIELD(f_rfr_dsource, nam_d_source, fld_source, 1, ODS_8_0)
FIELD(f_rfr_coll_id, nam_collate_id, fld_collate_id, 1, ODS_8_0)
FIELD(f_rfr_gen_name, nam_gen_name, fld_gen_name, 1, ODS_12_0)
FIELD(f_rfr_identity_type, nam_identity_type, fld_identity_type, 1, ODS_12_0)
END_RELATION
// Relation 6 (RDB$RELATIONS)

View File

@ -79,6 +79,7 @@ static const Jrd::gen generators[] =
{ "RDB$TRIGGER_NAME", 8, "Implicit trigger name" },
{ "RDB$BACKUP_HISTORY", 9, "Nbackup technology" },
{ "RDB$FUNCTIONS", 10, "Function ID" },
{ "RDB$GENERATOR_NAME", 11, "Implicit generator name" },
{ 0, 0, NULL }
};

View File

@ -143,3 +143,6 @@ TYPE ("ATTACHMENT", stat_attachment, nam_mon_stat_group)
TYPE ("TRANSACTION", stat_transaction, nam_mon_stat_group)
TYPE ("STATEMENT", stat_statement, nam_mon_stat_group)
TYPE ("CALL", stat_call, nam_mon_stat_group)
TYPE ("ALWAYS", IDENT_TYPE_ALWAYS, nam_identity_type)
TYPE ("BY DEFAULT", IDENT_TYPE_BY_DEFAULT, nam_identity_type)

View File

@ -13,7 +13,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
--('1996-11-07 13:39:40', 'GRST', 6, 1)
--
('2005-11-05 13:09:00', 'DSQL', 7, 32)
('2010-01-02 00:26:50', 'DYN', 8, 272)
('2010-01-13 15:04:00', 'DYN', 8, 278)
--
--('1996-11-07 13:39:40', 'FRED', 9, 1)
--

View File

@ -1833,6 +1833,12 @@ COMMIT WORK;
('dyn_package_body_exists', NULL, 'DdlNodes.epp/PackageNodes.epp', NULL, 8, 269, NULL, 'Package body @1 already exists', NULL, NULL);
('dyn_invalid_ddl_func', 'CreateAlterFunctionNode::compile', 'DdlNodes.epp', NULL, 8, 270, NULL, 'Invalid DDL statement for function @1', NULL, NULL);
('dyn_newfc_oldsyntax', 'DYN_modify_function', 'dyn_mod.epp', NULL, 8, 271, NULL, 'Cannot alter new style function @1 with ALTER EXTERNAL FUNCTION. Use ALTER FUNCTION instead.', NULL, NULL);
(NULL, 'DYN_delete_generator', 'dyn_del.epp', NULL, 8, 272, NULL, 'Cannot delete system generator', NULL, NULL);
(NULL, 'DYN_define_sql_field', 'dyn_def.epp', NULL, 8, 273, NULL, 'Identity column @1 of table @2 must be of exact number type with zero scale', NULL, NULL);
(NULL, 'DYN_modify_local_field', 'dyn_mod.epp', NULL, 8, 274, NULL, 'Identity column @1 of table @2 cannot be changed to NULLable', NULL, NULL);
(NULL, 'DYN_modify_sql_field', 'dyn_mod.epp', NULL, 8, 275, NULL, 'Identity column @1 of table @2 cannot have default value', NULL, NULL);
(NULL, 'DYN_modify_global_field', 'dyn_mod.epp', NULL, 8, 276, NULL, 'Domain @1 must be of exact number type with zero scale because it''s used in an identity column', NULL, NULL);
(NULL, NULL, 'dyn_util.epp', NULL, 8, 277, NULL, 'Generation of generator name failed', NULL, NULL);
COMMIT WORK;
-- TEST
(NULL, 'main', 'test.c', NULL, 11, 0, NULL, 'This is a modified text message', NULL, NULL);