mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 03:23:04 +01:00
Proposed solution for CORE-2245 in HEAD:
- create recovery routine for corrupt backups from FB2.0 and FB2.1. - create new function to store text with length between 256 and 64K bytes. - other related adjustments.
This commit is contained in:
parent
398d23313a
commit
297055ab15
@ -80,7 +80,7 @@ namespace // unnamed, private
|
||||
// VERBOSE INTERVAL WHEN BACKING RECORDS
|
||||
const ULONG BACKUP_VERBOSE_INTERVAL = 20000;
|
||||
|
||||
#define PUT_MESSAGE(attribute, message) put_message ((attribute), (message), sizeof(message))
|
||||
#define PUT_MESSAGE(attrib, attrib2, message) put_message((attrib), (attrib2), (message), sizeof(message))
|
||||
#define PUT_TEXT(attribute, text) put_text ((attribute), (text), sizeof(text))
|
||||
#define COPY(source, target) copy ((source), (target), sizeof(target))
|
||||
|
||||
@ -109,8 +109,9 @@ void put_blob(burp_fld*, ISC_QUAD&, ULONG);
|
||||
bool put_blr_blob(SCHAR, ISC_QUAD&);
|
||||
void put_data(burp_rel*);
|
||||
void put_index(burp_rel*);
|
||||
int put_message(SCHAR, const TEXT *, ULONG);
|
||||
int put_message(SCHAR, SCHAR, const TEXT*, const ULONG);
|
||||
void put_numeric(SCHAR, SLONG);
|
||||
void put_int64( SCHAR attribute, SINT64 value);
|
||||
void put_relation(burp_rel*);
|
||||
bool put_source_blob(SCHAR, SCHAR, ISC_QUAD&);
|
||||
int put_text(SCHAR, const TEXT *, SSHORT);
|
||||
@ -159,6 +160,7 @@ enum backup_capabilities
|
||||
BCK_ods10 = 8192, // FIELD_PRECISION
|
||||
BCK_ods11 = 16384,// rdb$description in rdb$roles and rdb$generators
|
||||
// rdb$base_collation_name and rdb$specific_attributes in rdb$collations
|
||||
// rdb$message enlarged to 1021.
|
||||
BCK_ods11_1 = 32768,// rdb$relation_type in rdb$relations
|
||||
// rdb$procedure_type in rdb$procedures
|
||||
// rdb$valid_blr in rdb$triggers
|
||||
@ -167,6 +169,7 @@ enum backup_capabilities
|
||||
// rdb$null_flag and rdb$parameter_mechanism in rdb$procedure_parameters
|
||||
BCK_ods11_2 = 65536 // rdb$field_name and rdb$relation_name in rdb$procedure_parameters
|
||||
// rdb$admin system role
|
||||
// rdb$message enlarged to 1023.
|
||||
};
|
||||
// ASF: Engine that works with ODS11.1 supports access to non-existent system fields.
|
||||
// Reads returns NULL and writes do nothing.
|
||||
@ -616,7 +619,7 @@ int copy( const TEXT* from, TEXT* to, ULONG size_len)
|
||||
const ULONG l = (ULONG) MISC_symbol_length(from, size_len);
|
||||
|
||||
memcpy(to, from, l);
|
||||
*(to + l) = '\0';
|
||||
to[l] = '\0';
|
||||
|
||||
return (int) l;
|
||||
}
|
||||
@ -2105,7 +2108,7 @@ void put_index( burp_rel* relation)
|
||||
}
|
||||
|
||||
|
||||
int put_message( SCHAR attribute, const TEXT* text, ULONG length)
|
||||
int put_message( SCHAR attribute, SCHAR attribute2, const TEXT* text, const ULONG length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2122,6 +2125,8 @@ int put_message( SCHAR attribute, const TEXT* text, ULONG length)
|
||||
* used for exception & trigger's messages (plus update/delete
|
||||
* rules for FKs and constraint types, where it's irrelevant
|
||||
* which function of the two you use).
|
||||
* CVC: Responsability for FKs and constraint types transferred to put_text.
|
||||
* This functions tries to maintain backwards compatibility where possible.
|
||||
*
|
||||
**************************************/
|
||||
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
||||
@ -2130,13 +2135,31 @@ int put_message( SCHAR attribute, const TEXT* text, ULONG length)
|
||||
for (const TEXT* p = text; *p && l < length; p++)
|
||||
l++;
|
||||
|
||||
l = length = MIN(l, length);
|
||||
put(tdgbl, (UCHAR) (attribute));
|
||||
put(tdgbl, (UCHAR) (l));
|
||||
if (l)
|
||||
put_block(tdgbl, reinterpret_cast<const UCHAR*>(text), l);
|
||||
const ULONG newlen = MIN(l, length);
|
||||
fb_assert(newlen <= MAX_USHORT);
|
||||
|
||||
return length;
|
||||
// If we can store the message using the old format, we do it.
|
||||
if (newlen <= MAX_UCHAR)
|
||||
{
|
||||
put(tdgbl, (UCHAR) attribute);
|
||||
put(tdgbl, (UCHAR) newlen);
|
||||
}
|
||||
else if (newlen <= MAX_USHORT)
|
||||
{
|
||||
if (!attribute2) // In theory, this never happens, because the caller knows what it's doing.
|
||||
BURP_error(314, "");
|
||||
put(tdgbl, (UCHAR) attribute2);
|
||||
USHORT vax_value = (USHORT) newlen;
|
||||
vax_value = (USHORT) gds__vax_integer((const UCHAR*) &vax_value, sizeof(vax_value));
|
||||
put_block(tdgbl, (const UCHAR*) &vax_value, sizeof(vax_value));
|
||||
}
|
||||
else
|
||||
BURP_error(315, "");
|
||||
|
||||
if (newlen)
|
||||
put_block(tdgbl, reinterpret_cast<const UCHAR*>(text), newlen);
|
||||
|
||||
return newlen;
|
||||
}
|
||||
|
||||
|
||||
@ -2157,7 +2180,7 @@ void put_numeric( SCHAR attribute, SLONG value)
|
||||
|
||||
const SLONG vax_value = (SLONG) isc_vax_integer((const char*) &value, sizeof(value));
|
||||
|
||||
put(tdgbl, (UCHAR) (attribute));
|
||||
put(tdgbl, (UCHAR) attribute);
|
||||
put(tdgbl, (UCHAR) sizeof(value));
|
||||
put_block(tdgbl, (const UCHAR*) &vax_value, sizeof(vax_value));
|
||||
}
|
||||
@ -2514,11 +2537,13 @@ int put_text( SCHAR attribute, const TEXT* text, SSHORT size_len)
|
||||
* Now this routine does not truncate trailing spaces, 3-2002 MOD
|
||||
* transfering changes from fb1, I believe this is to do with problems
|
||||
* with quoted names and embedded spaces.
|
||||
* CVC: This routine does trailing spaces truncation, but correctly.
|
||||
*
|
||||
**************************************/
|
||||
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
||||
|
||||
const SSHORT l = (SSHORT) MISC_symbol_length(text, (ULONG) size_len);
|
||||
fb_assert(l <= MAX_UCHAR);
|
||||
|
||||
put(tdgbl, (UCHAR) (attribute));
|
||||
put(tdgbl, (UCHAR) (l));
|
||||
@ -2914,7 +2939,7 @@ void write_exceptions()
|
||||
MISC_terminate (X.RDB$EXCEPTION_NAME, temp, l, sizeof(temp));
|
||||
BURP_verbose (198, temp);
|
||||
// msg 198 writing exception %s
|
||||
PUT_MESSAGE(att_exception_msg, X.RDB$MESSAGE);
|
||||
PUT_MESSAGE(att_exception_msg, att_exception_msg2, X.RDB$MESSAGE);
|
||||
put_source_blob (att_exception_description2, att_procedure_description, X.RDB$DESCRIPTION);
|
||||
put(tdgbl, att_end);
|
||||
END_FOR;
|
||||
@ -3588,8 +3613,8 @@ void write_ref_constraints()
|
||||
PUT_TEXT (att_ref_constraint_name, X.RDB$CONSTRAINT_NAME);
|
||||
PUT_TEXT (att_ref_unique_const_name, X.RDB$CONST_NAME_UQ);
|
||||
PUT_TEXT (att_ref_match_option, X.RDB$MATCH_OPTION);
|
||||
PUT_MESSAGE (att_ref_update_rule, X.RDB$UPDATE_RULE);
|
||||
PUT_MESSAGE (att_ref_delete_rule, X.RDB$DELETE_RULE);
|
||||
PUT_TEXT (att_ref_update_rule, X.RDB$UPDATE_RULE);
|
||||
PUT_TEXT (att_ref_delete_rule, X.RDB$DELETE_RULE);
|
||||
put(tdgbl, att_end);
|
||||
END_FOR;
|
||||
ON_ERROR
|
||||
@ -3624,7 +3649,7 @@ void write_rel_constraints()
|
||||
MISC_terminate (X.RDB$CONSTRAINT_NAME, temp, l, sizeof(temp));
|
||||
BURP_verbose (207, temp);
|
||||
// msg 207 writing constraint %s
|
||||
PUT_MESSAGE (att_rel_constraint_type, X.RDB$CONSTRAINT_TYPE);
|
||||
PUT_TEXT (att_rel_constraint_type, X.RDB$CONSTRAINT_TYPE);
|
||||
PUT_TEXT (att_rel_constraint_rel_name, X.RDB$RELATION_NAME);
|
||||
PUT_TEXT (att_rel_constraint_defer, X.RDB$DEFERRABLE);
|
||||
PUT_TEXT (att_rel_constraint_init, X.RDB$INITIALLY_DEFERRED);
|
||||
@ -4146,7 +4171,7 @@ void write_trigger_messages()
|
||||
BURP_verbose (157, temp);
|
||||
/* msg 157 writing trigger message for *s */
|
||||
put_numeric (att_trigmsg_number, X.RDB$MESSAGE_NUMBER);
|
||||
PUT_MESSAGE (att_trigmsg_text, X.RDB$MESSAGE);
|
||||
PUT_MESSAGE (att_trigmsg_text, 0, X.RDB$MESSAGE);
|
||||
put(tdgbl, att_end);
|
||||
END_FOR;
|
||||
ON_ERROR
|
||||
|
@ -167,35 +167,45 @@ and trigger-new is:
|
||||
|
||||
// Attributes within major record
|
||||
|
||||
/* CAREFUL not to pull the lastest version into maint version without
|
||||
modifying the att_backup_format to be one version back */
|
||||
/*
|
||||
CAREFUL not to pull the lastest version into maint version without
|
||||
modifying the att_backup_format to be one version back
|
||||
|
||||
/* ATT_BACKUP_FORMAT has been increased to 5. It allows us to distinguish
|
||||
ATT_BACKUP_FORMAT has been increased to 5. It allows us to distinguish
|
||||
backup format between IB3.3/IB4.0 and IB4.5 in case of migration
|
||||
problem */
|
||||
problem
|
||||
|
||||
/* Version 6: Supports SQL Time & Date columns.
|
||||
RDB$FIELD_PRECISION
|
||||
SQL Dialect from database header
|
||||
SQL_INT64 columns and generator values
|
||||
*/
|
||||
|
||||
/* Version 7: RDB$DESCRIPTION in roles and generators.
|
||||
RDB$FILE_NAME in character_sets and collations
|
||||
RDB$BASE_COLLATION_NAME and RDB$SPECIFIC_ATTRIBUTES in collations
|
||||
*/
|
||||
Version 6: IB6, FB1, FB1.5.
|
||||
Supports SQL Time & Date columns.
|
||||
RDB$FIELD_PRECISION
|
||||
SQL Dialect from database header
|
||||
SQL_INT64 columns and generator values
|
||||
|
||||
/* Version 8: RDB$RELATION_TYPE in relations
|
||||
RDB$PROCEDURE_TYPE and RDB$VALID_BLR in procedures
|
||||
RDB$VALID_BLR in triggers
|
||||
RDB$DEFAULT_VALUE, RDB$DEFAULT_SOURCE and RDB$COLLATION_ID in procedure_parameters
|
||||
Version 7: FB2.0.
|
||||
RDB$DESCRIPTION in roles and generators.
|
||||
RDB$FILE_NAME in character_sets and collations
|
||||
RDB$BASE_COLLATION_NAME and RDB$SPECIFIC_ATTRIBUTES in collations
|
||||
|
||||
*/
|
||||
const int ATT_BACKUP_FORMAT = 8; // ASF: when change this, change the text of the message gbak_inv_bkup_ver too
|
||||
Version 8: FB2.1.
|
||||
RDB$RELATION_TYPE in relations
|
||||
RDB$PROCEDURE_TYPE and RDB$VALID_BLR in procedures
|
||||
RDB$VALID_BLR in triggers
|
||||
RDB$DEFAULT_VALUE, RDB$DEFAULT_SOURCE and RDB$COLLATION_ID in procedure_parameters
|
||||
|
||||
Version 9: FB2.5.
|
||||
RDB$MESSAGE domain was enlarged from 78 to 1021 in FB2.0 and to 1023 in FB2.5,
|
||||
but gbak wasn't adjusted accordingly and thus it cannot store reliably text that's
|
||||
longer than 255 bytes.
|
||||
We anyway tried a recovery routine in v2.5 that may be backported.
|
||||
*/
|
||||
|
||||
// ASF: when change this, change the text of the message gbak_inv_bkup_ver, too.
|
||||
const int ATT_BACKUP_FORMAT = 9;
|
||||
|
||||
// format version number for ranges for arrays
|
||||
|
||||
const int GDS_NDA_VERSION = 1;
|
||||
//const int GDS_NDA_VERSION = 1; // Not used
|
||||
|
||||
// max array dimension
|
||||
|
||||
@ -488,6 +498,7 @@ enum att_type {
|
||||
att_exception_msg,
|
||||
att_exception_description,
|
||||
att_exception_description2,
|
||||
att_exception_msg2,
|
||||
|
||||
// Relation constraints attributes
|
||||
|
||||
|
@ -75,14 +75,15 @@ namespace // unnamed, private
|
||||
|
||||
const int DB_VERSION_DDL4 = 40; // ods4 db
|
||||
const int DB_VERSION_DDL5 = 50; // ods5 db
|
||||
const int DB_VERSION_DDL8 = 80; // ods8 db
|
||||
const int DB_VERSION_CURRENT = DB_VERSION_DDL8; // IB4.0 is ods8
|
||||
const int DB_VERSION_DDL8 = 80; // ods8 db, IB4
|
||||
const int DB_VERSION_DDL9 = 90; // ods9 db, IB5
|
||||
const int DB_VERSION_DDL10 = 100; // ods10 db, IB6, FB1, FB1.5
|
||||
const int DB_VERSION_DDL11 = 110; // ods11 db, FB2
|
||||
const int DB_VERSION_DDL11_1 = 111; // ods11.1 db, FB2.1
|
||||
const int DB_VERSION_DDL11_2 = 112; // ods11.2 db, FB2.5
|
||||
|
||||
const int DB_VERSION_OLDEST_SUPPORTED = DB_VERSION_DDL8; // IB4.0 is ods8
|
||||
|
||||
const int DEFERRED_ACTIVE = 3; /* RDB$INDEX_INACTIVE setting for Foreign Keys
|
||||
* This setting is used temporarily while
|
||||
* restoring a database. This was required
|
||||
@ -110,6 +111,7 @@ void create_database(BurpGlobals* tdgbl, const TEXT*);
|
||||
void decompress(BurpGlobals* tdgbl, UCHAR*, USHORT);
|
||||
void eat_blob(BurpGlobals* tdgbl);
|
||||
void eat_text(BurpGlobals* tdgbl);
|
||||
void eat_text2(BurpGlobals* tdgbl);
|
||||
burp_rel* find_relation(BurpGlobals* tdgbl, const TEXT*);
|
||||
// CVC: when do these functions return false indeed???
|
||||
// get_acl and get_index are the only exceptions but ironically their
|
||||
@ -145,7 +147,8 @@ bool get_sql_roles(BurpGlobals* tdgbl);
|
||||
bool get_mapping(BurpGlobals* tdgbl);
|
||||
bool get_security_class(BurpGlobals* tdgbl);
|
||||
void get_source_blob(BurpGlobals* tdgbl, ISC_QUAD&, bool);
|
||||
USHORT get_text (BurpGlobals* tdgbl, TEXT*, ULONG);
|
||||
USHORT get_text(BurpGlobals* tdgbl, TEXT*, ULONG);
|
||||
USHORT get_text2(BurpGlobals* tdgbl, TEXT* text, ULONG length);
|
||||
bool get_trigger(BurpGlobals* tdgbl);
|
||||
bool get_trigger_message(BurpGlobals* tdgbl);
|
||||
bool get_trigger_old (BurpGlobals* tdgbl, burp_rel*);
|
||||
@ -195,6 +198,7 @@ static inline rec_type get_record(rec_type *rec, BurpGlobals* tdgbl)
|
||||
}
|
||||
|
||||
#define GET_TEXT(text) get_text(tdgbl, (text), sizeof(text))
|
||||
#define GET_TEXT2(text) get_text2(tdgbl, (text), sizeof(text))
|
||||
|
||||
static inline void get_skip(BurpGlobals* tdgbl, ULONG n)
|
||||
{
|
||||
@ -1137,6 +1141,19 @@ void eat_text(BurpGlobals* tdgbl)
|
||||
MVOL_skip_block(tdgbl, l);
|
||||
}
|
||||
|
||||
// *****************************
|
||||
// e a t _ t e x t 2
|
||||
// *****************************
|
||||
// Discard a text field from the backup file, using USHORT length indicator.
|
||||
void eat_text2(BurpGlobals* tdgbl)
|
||||
{
|
||||
UCHAR lenstr[sizeof(USHORT)] = "";
|
||||
get_block(tdgbl, lenstr, sizeof(lenstr));
|
||||
USHORT len = (USHORT) gds__vax_integer(lenstr, sizeof(lenstr));
|
||||
if (len)
|
||||
MVOL_skip_block(tdgbl, len);
|
||||
}
|
||||
|
||||
burp_rel* find_relation(BurpGlobals* tdgbl, const TEXT* name)
|
||||
{
|
||||
/**************************************
|
||||
@ -2039,7 +2056,7 @@ bool get_character_set(BurpGlobals* tdgbl)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g e t _ c h a r a c t e r _ s e t s
|
||||
* g e t _ c h a r a c t e r _ s e t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
@ -2840,49 +2857,138 @@ bool get_exception(BurpGlobals* tdgbl)
|
||||
**************************************/
|
||||
ATT_TYPE attribute;
|
||||
TEXT temp[GDS_NAME_LEN];
|
||||
ULONG l;
|
||||
ULONG l2 = 0;
|
||||
scan_attr_t scan_next_attr;
|
||||
|
||||
STORE (REQUEST_HANDLE tdgbl->handles_get_exception_req_handle1)
|
||||
X IN RDB$EXCEPTIONS
|
||||
X.RDB$EXCEPTION_NAME.NULL = TRUE;
|
||||
X.RDB$DESCRIPTION.NULL = TRUE;
|
||||
X.RDB$MESSAGE.NULL = TRUE;
|
||||
X.RDB$SYSTEM_FLAG = 0;
|
||||
X.RDB$SYSTEM_FLAG.NULL = FALSE;
|
||||
|
||||
att_type failed_attrib = att_end;
|
||||
bool msg_seen = false; // only for att_exception_msg, not att_exception_msg2
|
||||
UCHAR* msg_ptr = reinterpret_cast<UCHAR*>(X.RDB$MESSAGE);
|
||||
|
||||
skip_init(&scan_next_attr);
|
||||
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
|
||||
{
|
||||
switch (attribute)
|
||||
{
|
||||
case att_exception_name:
|
||||
l = GET_TEXT(X.RDB$EXCEPTION_NAME);
|
||||
MISC_terminate (X.RDB$EXCEPTION_NAME, temp, l, sizeof(temp));
|
||||
BURP_verbose (199, temp);
|
||||
// msg 199 restoring exception %s
|
||||
if (!X.RDB$EXCEPTION_NAME.NULL)
|
||||
BURP_error(311, true, SafeArg() << att_exception_name << X.RDB$EXCEPTION_NAME);
|
||||
else
|
||||
{
|
||||
const ULONG l = GET_TEXT(X.RDB$EXCEPTION_NAME);
|
||||
X.RDB$EXCEPTION_NAME.NULL = FALSE;
|
||||
MISC_terminate (X.RDB$EXCEPTION_NAME, temp, l, sizeof(temp));
|
||||
BURP_verbose (199, temp);
|
||||
// msg 199 restoring exception %s
|
||||
}
|
||||
break;
|
||||
|
||||
case att_exception_description:
|
||||
get_misc_blob (tdgbl, X.RDB$DESCRIPTION, 0, false);
|
||||
X.RDB$DESCRIPTION.NULL = FALSE;
|
||||
if (!X.RDB$DESCRIPTION.NULL)
|
||||
BURP_error(311, true, SafeArg() << att_exception_description << X.RDB$EXCEPTION_NAME);
|
||||
else
|
||||
{
|
||||
msg_seen = false;
|
||||
get_misc_blob (tdgbl, X.RDB$DESCRIPTION, 0, false);
|
||||
X.RDB$DESCRIPTION.NULL = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case att_exception_description2:
|
||||
get_source_blob (tdgbl, X.RDB$DESCRIPTION, false);
|
||||
X.RDB$DESCRIPTION.NULL = FALSE;
|
||||
if (!X.RDB$DESCRIPTION.NULL)
|
||||
BURP_error(311, true, SafeArg() << att_exception_description2 << X.RDB$EXCEPTION_NAME);
|
||||
else
|
||||
{
|
||||
msg_seen = false;
|
||||
get_source_blob (tdgbl, X.RDB$DESCRIPTION, false);
|
||||
X.RDB$DESCRIPTION.NULL = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case att_exception_msg:
|
||||
GET_TEXT(X.RDB$MESSAGE);
|
||||
X.RDB$MESSAGE.NULL = FALSE;
|
||||
if (msg_seen)
|
||||
BURP_error(311, true, SafeArg() << att_exception_msg << X.RDB$EXCEPTION_NAME);
|
||||
else if (!X.RDB$MESSAGE.NULL)
|
||||
{
|
||||
msg_seen = true;
|
||||
BURP_print(312, SafeArg() << att_exception_msg << X.RDB$EXCEPTION_NAME);
|
||||
eat_text(tdgbl);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_seen = true;
|
||||
l2 = GET_TEXT(X.RDB$MESSAGE);
|
||||
msg_ptr += l2;
|
||||
X.RDB$MESSAGE.NULL = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case att_exception_msg2:
|
||||
if (msg_seen)
|
||||
BURP_error(311, true, SafeArg() << att_exception_msg2 << X.RDB$EXCEPTION_NAME);
|
||||
else if (!X.RDB$MESSAGE.NULL)
|
||||
{
|
||||
BURP_print(312, SafeArg() << att_exception_msg2 << X.RDB$EXCEPTION_NAME);
|
||||
eat_text2(tdgbl);
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_TEXT2(X.RDB$MESSAGE);
|
||||
X.RDB$MESSAGE.NULL = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
bad_attribute (scan_next_attr, attribute, 287);
|
||||
// msg 287 exception
|
||||
if (msg_seen && (tdgbl->RESTORE_format == 7 || tdgbl->RESTORE_format == 8))
|
||||
{
|
||||
// we have a corrup backup
|
||||
if (!failed_attrib)
|
||||
{
|
||||
failed_attrib = attribute;
|
||||
BURP_print(313, SafeArg() << failed_attrib << X.RDB$EXCEPTION_NAME);
|
||||
}
|
||||
|
||||
// Notice we use 1021 instead of 1023 because this is the maximum length
|
||||
// for this field in v2.0 and v2.1 and they produce the corrupt backups.
|
||||
const int FIELD_LIMIT = 1021;
|
||||
|
||||
const int remaining = FIELD_LIMIT - l2;
|
||||
if (remaining < 1) // not enough space
|
||||
{
|
||||
bad_attribute (scan_next_attr, failed_attrib, 287);
|
||||
break;
|
||||
}
|
||||
*msg_ptr++ = char(attribute); // (1)
|
||||
UCHAR* rc_ptr = get_block(tdgbl, msg_ptr, min(remaining - 1, 255));
|
||||
if (remaining > 1 && rc_ptr == msg_ptr) // we couldn't read anything
|
||||
{
|
||||
bad_attribute (scan_next_attr, failed_attrib, 287);
|
||||
break;
|
||||
}
|
||||
l2 += rc_ptr - msg_ptr + 1; // + 1 because (1)
|
||||
msg_ptr = rc_ptr;
|
||||
*msg_ptr = 0;
|
||||
if (l2 == FIELD_LIMIT)
|
||||
msg_seen = false;
|
||||
}
|
||||
else
|
||||
bad_attribute (scan_next_attr, attribute, 287); // msg 287 exception
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Versions prior to FB2.0 don't support a field longer than varchar(78).
|
||||
// Versions prior to FB2.5 use a field length of 1021, not 1023.
|
||||
if (tdgbl->RESTORE_ods < DB_VERSION_DDL11)
|
||||
X.RDB$MESSAGE[78] = 0;
|
||||
else if (tdgbl->RESTORE_ods < DB_VERSION_DDL11_2)
|
||||
X.RDB$MESSAGE[1021] = 0;
|
||||
END_STORE;
|
||||
ON_ERROR
|
||||
general_on_error ();
|
||||
@ -6093,6 +6199,34 @@ USHORT get_text(BurpGlobals* tdgbl,
|
||||
return (USHORT) l;
|
||||
}
|
||||
|
||||
USHORT get_text2(BurpGlobals* tdgbl, TEXT* text, ULONG length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g e t _ t e x t 2
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Move a text attribute to a string and fill, using USHORT as length indicator.
|
||||
*
|
||||
**************************************/
|
||||
UCHAR lenstr[sizeof(USHORT)] = "";
|
||||
get_block(tdgbl, lenstr, sizeof(lenstr));
|
||||
const USHORT len = (USHORT) gds__vax_integer(lenstr, sizeof(lenstr));
|
||||
|
||||
if (length <= len)
|
||||
BURP_error_redirect (NULL, 46);
|
||||
// msg 46 string truncated
|
||||
|
||||
if (len)
|
||||
text = (TEXT*) get_block(tdgbl, (UCHAR*) text, len);
|
||||
|
||||
*text = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool get_trigger_old (BurpGlobals* tdgbl,
|
||||
burp_rel* relation)
|
||||
{
|
||||
@ -6475,7 +6609,7 @@ bool get_trigger_message(BurpGlobals* tdgbl)
|
||||
BASED_ON RDB$TRIGGER_MESSAGES.RDB$MESSAGE_NUMBER number = -1;
|
||||
BASED_ON RDB$TRIGGER_MESSAGES.RDB$MESSAGE message;
|
||||
|
||||
bool flag = false;
|
||||
bool sysflag = false;
|
||||
skip_init(&scan_next_attr);
|
||||
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
|
||||
{
|
||||
@ -6483,11 +6617,11 @@ bool get_trigger_message(BurpGlobals* tdgbl)
|
||||
{
|
||||
case att_trigmsg_name:
|
||||
GET_TEXT(name);
|
||||
flag = false;
|
||||
sysflag = false;
|
||||
FOR (REQUEST_HANDLE tdgbl->handles_get_trigger_message_req_handle1)
|
||||
FIRST 1 X IN RDB$TRIGGERS WITH
|
||||
X.RDB$SYSTEM_FLAG EQ 1 AND X.RDB$TRIGGER_NAME EQ name
|
||||
flag = true;
|
||||
sysflag = true;
|
||||
END_FOR;
|
||||
ON_ERROR
|
||||
general_on_error ();
|
||||
@ -6511,9 +6645,14 @@ bool get_trigger_message(BurpGlobals* tdgbl)
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
if (sysflag)
|
||||
return true;
|
||||
|
||||
// Versions prior to FB2.0 don't support a field longer than varchar(78).
|
||||
if (tdgbl->RESTORE_ods < DB_VERSION_DDL11)
|
||||
message[78] = 0;
|
||||
|
||||
|
||||
isc_tr_handle local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;
|
||||
|
||||
STORE (TRANSACTION_HANDLE local_trans
|
||||
@ -7278,7 +7417,7 @@ bool restore(BurpGlobals* tdgbl,
|
||||
EXEC SQL SET TRANSACTION NAME tdgbl->global_trans ISOLATION LEVEL READ COMMITTED;
|
||||
|
||||
check_db_version(tdgbl);
|
||||
if (tdgbl->RESTORE_ods < DB_VERSION_CURRENT)
|
||||
if (tdgbl->RESTORE_ods < DB_VERSION_OLDEST_SUPPORTED)
|
||||
{
|
||||
BURP_error(51, true, SafeArg() << tdgbl->RESTORE_ods);
|
||||
// msg 51 database format %ld is too old to restore to
|
||||
@ -7511,8 +7650,8 @@ bool restore(BurpGlobals* tdgbl,
|
||||
general_on_error ();
|
||||
END_ERROR;
|
||||
EXEC SQL SET TRANSACTION NO_AUTO_UNDO;
|
||||
if (gds_status[1])
|
||||
EXEC SQL SET TRANSACTION;
|
||||
if (gds_status[1])
|
||||
EXEC SQL SET TRANSACTION;
|
||||
flag = false;
|
||||
}
|
||||
if (!get_relation_data(tdgbl))
|
||||
@ -7648,10 +7787,10 @@ bool restore(BurpGlobals* tdgbl,
|
||||
|
||||
FOR (REQUEST_HANDLE req_handle5)
|
||||
IND IN RDB$INDICES WITH IND.RDB$SYSTEM_FLAG EQ 1
|
||||
MODIFY IND;
|
||||
MODIFY IND
|
||||
IND.RDB$STATISTICS.NULL = FALSE;
|
||||
IND.RDB$STATISTICS = -1;
|
||||
END_MODIFY;
|
||||
END_MODIFY
|
||||
ON_ERROR
|
||||
general_on_error ();
|
||||
END_ERROR;
|
||||
|
@ -803,7 +803,7 @@ Data source : @4"}, /* 606, eds_statement */
|
||||
{336330793, "expected data attribute"}, /* 776, gbak_exp_data_type */
|
||||
{336330794, "Failed in store_blr_gen_id"}, /* 777, gbak_gen_id_failed */
|
||||
{336330795, "do not recognize record type @1"}, /* 778, gbak_unk_rec_type */
|
||||
{336330796, "Expected backup version 1..8. Found @1"}, /* 779, gbak_inv_bkup_ver */
|
||||
{336330796, "Expected backup version 1..9. Found @1"}, /* 779, gbak_inv_bkup_ver */
|
||||
{336330797, "expected backup description record"}, /* 780, gbak_missing_bkup_desc */
|
||||
{336330798, "string truncated"}, /* 781, gbak_string_trunc */
|
||||
{336330799, "warning -- record could not be restored"}, /* 782, gbak_cant_rest_record */
|
||||
|
@ -17,7 +17,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
|
||||
--
|
||||
('1996-11-07 13:39:40', 'INSTALL', 10, 1)
|
||||
('1996-11-07 13:38:41', 'TEST', 11, 4)
|
||||
('2008-11-28 15:09:27', 'GBAK', 12, 310)
|
||||
('2009-02-01 05:22:26', 'GBAK', 12, 316)
|
||||
('2008-09-26 07:37:16', 'SQLERR', 13, 969)
|
||||
('1996-11-07 13:38:42', 'SQLWARN', 14, 613)
|
||||
('2006-09-10 03:04:31', 'JRD_BUGCHK', 15, 307)
|
||||
|
@ -2184,7 +2184,7 @@ COMMIT WORK;
|
||||
('gbak_exp_data_type', NULL, 'burp.c', NULL, 12, 41, NULL, 'expected data attribute', NULL, NULL);
|
||||
('gbak_gen_id_failed', NULL, 'burp.c', NULL, 12, 42, NULL, 'Failed in store_blr_gen_id', NULL, NULL);
|
||||
('gbak_unk_rec_type', NULL, 'burp.c', NULL, 12, 43, NULL, 'do not recognize record type @1', NULL, NULL);
|
||||
('gbak_inv_bkup_ver', NULL, 'burp.c', NULL, 12, 44, NULL, 'Expected backup version 1..8. Found @1', NULL, NULL);
|
||||
('gbak_inv_bkup_ver', NULL, 'burp.c', NULL, 12, 44, NULL, 'Expected backup version 1..9. Found @1', NULL, NULL);
|
||||
('gbak_missing_bkup_desc', NULL, 'burp.c', NULL, 12, 45, NULL, 'expected backup description record', NULL, NULL);
|
||||
('gbak_string_trunc', NULL, 'burp.c', NULL, 12, 46, NULL, 'string truncated', NULL, NULL);
|
||||
('gbak_cant_rest_record', NULL, 'burp.c', NULL, 12, 47, NULL, 'warning -- record could not be restored', NULL, NULL);
|
||||
@ -2460,6 +2460,11 @@ ERROR: Backup incomplete', NULL, NULL);
|
||||
(NULL, 'BURP_gbak', 'burp.cpp', NULL, 12, 308, NULL, 'could not open password file @1, errno @2', NULL, NULL);
|
||||
(NULL, 'BURP_gbak', 'burp.cpp', NULL, 12, 309, NULL, 'could not read password file @1, errno @2', NULL, NULL);
|
||||
(NULL, 'BURP_gbak', 'burp.cpp', NULL, 12, 310, NULL, 'empty password file @1', NULL, NULL);
|
||||
(NULL, 'get_exception', 'restore.epp', NULL, 12, 311, NULL, 'Attribute @1 was already processed for exception @2', NULL, NULL)
|
||||
(NULL, 'get_exception', 'restore.epp', NULL, 12, 312, NULL, 'Skipping attribute @1 because the message already exists for exception @2 ', NULL, NULL)
|
||||
(NULL, 'get_exception', 'restore.epp', NULL, 12, 313, NULL, 'Trying to recover from unexpected attribute @1 due to wrong message length for exception @2', NULL, NULL)
|
||||
(NULL, 'put_exception', 'backup.epp', NULL, 12, 314, NULL, 'Attribute not specified for storing text bigger than 255 bytes', NULL, NULL)
|
||||
(NULL, 'put_exception', 'backup.epp', NULL, 12, 315, NULL, 'Unable to store text bigger than 65536 bytes', NULL, NULL)
|
||||
-- SQLERR
|
||||
(NULL, NULL, NULL, NULL, 13, 1, NULL, 'Firebird error', NULL, NULL);
|
||||
(NULL, NULL, NULL, NULL, 13, 74, NULL, 'Rollback not performed', NULL, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user