/* * PROGRAM: JRD Backup and Restore Program * MODULE: backup.e * DESCRIPTION: Backup routine * * The contents of this file are subject to the Interbase Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy * of the License at http://www.Inprise.com/IPL.html * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express * or implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code was created by Inprise Corporation * and its predecessors. Portions created by Inprise Corporation are * Copyright (C) Inprise Corporation. * * All Rights Reserved. * Contributor(s): ______________________________________. * * Toni Martir: Added verbose backup records as BACKUP_VERBOSE_INTERVAL * 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE" * conditionals, as the engine now fully supports * readonly databases. * 2001.11.20 Claudio Valderrama: fix problem with embedded blanks in * generators and use symbol_length effective length calculation from put_text. * This minimizes code redundancy and fixes SF Bug #483276. * 2001.12.15 Claudio Valderrama: copy should run through symbol_length instead * of using just another length calculation algorithm. Callers of put_text, copy * and symbol_length (if used directly) should use sizeof. Changed all callers * and sizeof() works because the strings are local to the functions. This * eliminates the problem with harcoded limits in each call. */ /* $Id: backup.epp,v 1.7 2002-10-24 09:01:25 eku Exp $ */ #include "firebird.h" #include "../jrd/ib_stdio.h" #include #include #include "../burp/burp.h" #include "../jrd/ods.h" #include "../jrd/align.h" #include "../jrd/gdsassert.h" #include "../jrd/thd_proto.h" #include "../burp/backu_proto.h" #include "../burp/burp_proto.h" #include "../burp/canon_proto.h" #include "../burp/mvol_proto.h" #include "../remote/protocol.h" /* For netware the follow DB handle is #defined to be a value stored */ /* in thread data. This is also done for other statics generated by */ /* GPRE. This is to avoid multiple threading problems with module */ /* level statics. */ DATABASE DB = STATIC FILENAME "yachts.lnk" RUNTIME * dbb_file; #define DB tdgbl->db_handle #define isc_trans tdgbl->tr_handle #define isc_status tdgbl->status /* #define DEBUG 1 */ /* VERBOSE INTERVAL WHEN BACKING RECORDS */ #define BACKUP_VERBOSE_INTERVAL 20000 #define STUFF(byte) *blr++ = (SCHAR) (byte) #define STUFF_WORD(word) {STUFF (word); STUFF ((word) >> 8);} #define STUFF_LONG(l) {STUFF_WORD (l); STUFF_WORD ((l) >> 16);} #define PUT(c) (--(tdgbl->io_cnt) >= 0 ? *(tdgbl->io_ptr)++ = (UCHAR) (c) : MVOL_write ((UCHAR) (c), &(tdgbl->io_cnt), &(tdgbl->io_ptr))) #define PUT_BLOCK(p,n) MVOL_write_block (tdgbl, p, n) #define PUT_ASCIZ(attribute, string) put_asciz ((attribute), (string)) #define PUT_MESSAGE(attribute, message) put_message ((attribute), (message), sizeof (message)) #define PUT_NUMERIC(attribute, value) put_numeric ((attribute), (value)) #define PUT_INT64(attribute, value) put_int64 ((attribute), (value)) #define PUT_TEXT(attribute, text) put_text ((attribute), (text), sizeof (text)) #define COPY(source, target) copy ((source), (target), sizeof (target)) static void compress(UCHAR *, ULONG); static int copy(TEXT *, TEXT *, ULONG); static FLD get_fields(REL); static SINT64 get_gen_id(TEXT *, SSHORT); static void get_ranges(FLD); static void put_array(FLD, REL, ISC_QUAD *); static void put_asciz(SCHAR, TEXT *); static void put_blob(FLD, ISC_QUAD *, ULONG); static int put_blr_blob(SCHAR, ISC_QUAD *); static void put_data(REL); static void put_index(REL); static int put_message(SCHAR, TEXT *, ULONG); static void put_numeric(SCHAR, SLONG); static void put_relation(REL); static int put_source_blob(SCHAR, SCHAR, ISC_QUAD *); static int put_text(SCHAR, TEXT *, SSHORT); static void put_trigger(enum trig_t, GDS__QUAD *, GDS__QUAD *, GDS_NAME); static void set_capabilities(void); static int symbol_length(TEXT *, ULONG); static void write_character_sets(void); static void write_check_constraints(void); static void write_collations(void); static void write_database(TEXT *); static void write_exceptions(void); static void write_field_dimensions(void); static void write_filters(void); static void write_functions(void); static void write_function_args(GDS_NAME); static void write_generators(void); static void write_sql_roles(void); static void write_global_fields(void); static void write_procedures(void); static void write_procedure_prms(GDS_NAME); static void write_ref_constraints(void); static void write_rel_constraints(void); static void write_relations(void); static void write_shadow_files(void); static void write_triggers(void); static void write_trigger_messages(void); static void write_types(void); static void write_user_privileges(void); static void general_on_error(void); #define BCK_security 1 #define BCK_files 2 #define BCK_external 4 #define BCK_idx_inactive 8 #define BCK_triggers 16 /* Obsolete - 1996-Aug-05 */ #define BCK_context_name 32 #define BCK_db_description 64 #define BCK_ffmptt 128 /* rdb$functions, rdb$filters, rdb$trigger_messages, rdb$user_privileges, rdb$triggers, rdb$types */ #define BCK_attributes_v3 256 /* attributes in various system relations new to v3 */ #define BCK_rfr_sys_flag 512 /* system flag is missing from Rdb/VMS V3 RFR relation */ #define BCK_ods6 1024 /* rdb$field_dimensions and shadow files */ #define BCK_ods8 2048 /* stored procedures & exceptions & constraints */ #define BCK_ods9 4096 /* SQL roles */ #define BCK_ods10 8192 /* FIELD_PRECISION */ #ifdef DEBUG static UCHAR debug_on = 0; /* able to turn this on in debug mode */ #endif /* table used to determine capabilities, checking for specific fields in system relations */ typedef struct rfr_tab_t { CONST TEXT *relation; CONST TEXT *field; int bit_mask; } *RFR_TAB; static CONST struct rfr_tab_t rfr_table[] = { {"RDB$INDICES", "RDB$INDEX_INACTIVE", BCK_idx_inactive}, /* Backup of V2 triggers no longer supported 1996-Aug-05 David Schnepper {"RDB$RELATIONS", "RDB$STORE_TRIGGER", BCK_triggers}, */ {"RDB$RELATIONS", "RDB$EXTERNAL_FILE", BCK_external}, {"RDB$SECURITY_CLASSES", "RDB$SECURITY_CLASS", BCK_security}, {"RDB$FILES", "RDB$FILE_NAME", BCK_files}, {"RDB$VIEW_RELATIONS", "RDB$CONTEXT_NAME", BCK_context_name}, {"RDB$DATABASE", "RDB$DESCRIPTION", BCK_db_description}, {"RDB$FUNCTIONS", "RDB$FUNCTION_NAME", BCK_ffmptt}, {"RDB$FIELDS", "RDB$EXTERNAL_LENGTH", BCK_attributes_v3}, {"RDB$RELATION_FIELDS", "RDB$SYSTEM_FLAG", BCK_rfr_sys_flag}, {"RDB$FIELD_DIMENSIONS", "RDB$DIMENSION", BCK_ods6}, {"RDB$PROCEDURES", "RDB$PROCEDURE_NAME", BCK_ods8}, {"RDB$ROLES", "RDB$ROLE_NAME", BCK_ods9}, {"RDB$FIELDS", "RDB$FIELD_PRECISION", BCK_ods10}, {0, 0, 0} }; static CONST SCHAR blob_items[] = { isc_info_blob_max_segment, isc_info_blob_num_segments }; static CONST SCHAR blr_items[] = { isc_info_blob_max_segment, isc_info_blob_total_length }; static CONST SCHAR source_items[] = { isc_info_blob_max_segment, isc_info_blob_total_length, isc_info_blob_num_segments }; static CONST SCHAR db_info_items[] = { isc_info_db_sql_dialect, isc_info_page_size, isc_info_sweep_interval, isc_info_forced_writes, isc_info_no_reserve, isc_info_set_page_buffers, isc_info_db_read_only, isc_info_end }; static CONST SCHAR limbo_tpb[] = { isc_tpb_version1, isc_tpb_ignore_limbo }; static CONST SCHAR limbo_nau_tpb[] = { isc_tpb_version1, isc_tpb_ignore_limbo, isc_tpb_no_auto_undo }; int BACKUP_backup(TEXT* dbb_file, TEXT* file_name) { /************************************** * * B A C K U P _ b a c k u p * ************************************** * * Functional description * Backup a database. * **************************************/ REL relation; STATUS status_vector[ISC_STATUS_LENGTH]; ULONG l; TEXT temp[GDS_NAME_LEN]; ULONG cumul_count_kb; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; FIL fil; tdgbl = GET_THREAD_DATA; tdgbl->gbl_database_file_name = dbb_file; tdgbl->io_ptr = (UCHAR *) NULL; tdgbl->io_cnt = 0; tdgbl->relations = (REL) NULL; cumul_count_kb = tdgbl->BCK_capabilities = 0; isc_trans = NULL; BURP_verbose(130, NULL, NULL, NULL, NULL, NULL); /* msg 130 starting transaction */ if (tdgbl->gbl_sw_ignore_limbo) { if (isc_start_transaction(status_vector, GDS_REF(isc_trans), 1, GDS_REF(tdgbl->db_handle), sizeof(limbo_nau_tpb), limbo_nau_tpb)) { isc_start_transaction(status_vector, GDS_REF(isc_trans), 1, GDS_REF(tdgbl->db_handle), sizeof(limbo_tpb), limbo_tpb); } } else { EXEC SQL SET TRANSACTION NO_AUTO_UNDO; if (isc_status[1]) EXEC SQL SET TRANSACTION; } if (!isc_trans) { EXEC SQL SET TRANSACTION NAME isc_trans NO_AUTO_UNDO; if (isc_status[1]) EXEC SQL SET TRANSACTION NAME isc_trans; } /* decide what type of database we've got */ set_capabilities(); /* Write burp record first with other valuable information */ /* In case of split operation, write a 'split' header first to all the files */ if (tdgbl->action->act_action == ACT_backup_split) { for (fil = tdgbl->gbl_sw_files; fil; fil = fil->fil_next) { tdgbl->action->act_file = fil; if (MVOL_split_hdr_write() == FALSE) { BURP_error(269, tdgbl->action->act_file->fil_name, 0, 0, 0, 0); /* msg 269 can't write a header record to file %s */ } } tdgbl->action->act_file = tdgbl->gbl_sw_files; } MVOL_init_write((UCHAR*) dbb_file, (UCHAR*) file_name, &tdgbl->io_cnt, &tdgbl->io_ptr); /* Write database record */ write_database(dbb_file); /* Write global fields */ BURP_verbose(150, NULL, NULL, NULL, NULL, NULL); /* msg 150 writing global fields */ write_global_fields(); if (tdgbl->BCK_capabilities & BCK_ods6) { write_field_dimensions(); BURP_verbose(162, NULL, NULL, NULL, NULL, NULL); /* msg 162 writing shadow files */ write_shadow_files(); } /* Write relations */ BURP_verbose(154, NULL, NULL, NULL, NULL, NULL); /* msg 154 writing relations */ write_relations(); if (tdgbl->BCK_capabilities & BCK_ffmptt) { /* Write functions */ BURP_verbose(148, NULL, NULL, NULL, NULL, NULL); /* msg 148 writing functions */ write_functions(); /* Write types */ BURP_verbose(161, NULL, NULL, NULL, NULL, NULL); /* msg 161 writing types */ write_types(); /* Write filters */ BURP_verbose(146, NULL, NULL, NULL, NULL, NULL); /* msg 146 writing filters */ write_filters(); /* Write generators */ BURP_verbose(164, NULL, NULL, NULL, NULL, NULL); /* msg 164 writing id generators */ write_generators(); } if (tdgbl->BCK_capabilities & BCK_ods8) { /* Write procedures */ BURP_verbose(192, NULL, NULL, NULL, NULL, NULL); /* msg 192 writing stored procedures */ write_procedures(); /* Write exceptions */ BURP_verbose(197, NULL, NULL, NULL, NULL, NULL); /* msg 197 writing exceptions */ write_exceptions(); /* Write Character Sets */ BURP_verbose(msgVerbose_write_charsets, NULL, NULL, NULL, NULL, NULL); write_character_sets(); /* Write Collations */ BURP_verbose(msgVerbose_write_collations, NULL, NULL, NULL, NULL, NULL); write_collations(); } /* Now go back and write all data */ for (relation = tdgbl->relations; relation; relation = relation->rel_next) { PUT(rec_relation_data); PUT_TEXT(att_relation_name, relation->rel_name); PUT(att_end); if (!(relation->rel_flags & REL_view) && !(relation->rel_flags & REL_external)) { put_index(relation); if (!tdgbl->gbl_sw_meta) { put_data(relation); } } PUT(rec_relation_end); } /* now for the new triggers in rdb$triggers */ if (tdgbl->BCK_capabilities & BCK_ffmptt) { BURP_verbose(159, NULL, NULL, NULL, NULL, NULL); /* msg 159 writing triggers */ write_triggers(); BURP_verbose(158, NULL, NULL, NULL, NULL, NULL); /* msg 158 writing trigger messages */ write_trigger_messages(); write_user_privileges(); } /* Last, but not least, go back and add any access control lists */ if (tdgbl->BCK_capabilities & BCK_security) FOR (REQUEST_HANDLE req_handle1) X IN RDB$SECURITY_CLASSES WITH X.RDB$SECURITY_CLASS NOT STARTING "SQL$" PUT (rec_security_class); l = PUT_TEXT (att_class_security_class, X.RDB$SECURITY_CLASS); MISC_terminate ((UCHAR*) X.RDB$SECURITY_CLASS, (UCHAR*) temp, l, sizeof(temp)); BURP_verbose (155, temp, NULL, NULL, NULL, NULL); /* msg 155 writing security class %s */ put_blr_blob (att_class_acl, (ISC_QUAD *)&X.RDB$ACL); put_source_blob (att_class_description2, att_class_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); if (tdgbl->BCK_capabilities & BCK_ods8) { /* Write relation constraints */ BURP_verbose(206, NULL, NULL, NULL, NULL, NULL); /* msg 206 writing relation constraints */ write_rel_constraints(); /* Write referential constraints */ BURP_verbose(209, NULL, NULL, NULL, NULL, NULL); /* msg 209 writing referential constraints */ write_ref_constraints(); /* Write check constraints */ BURP_verbose(210, NULL, NULL, NULL, NULL, NULL); /* msg 210 writing check constraints */ write_check_constraints(); } if (tdgbl->BCK_capabilities & BCK_ods9) { /* Write SQL roles */ BURP_verbose(248, NULL, NULL, NULL, NULL, NULL); /* msg 248 writing SQL roles */ write_sql_roles(); } /* Finish up */ PUT(rec_end); MVOL_fini_write(&tdgbl->io_cnt, &tdgbl->io_ptr, (int*) &cumul_count_kb); BURP_verbose(176, (TEXT *) cumul_count_kb, NULL, NULL, NULL, NULL); /* msg 176 closing file, committing, and finishing. %ld bytes written */ COMMIT; ON_ERROR general_on_error (); END_ERROR; if (isc_trans) COMMIT isc_trans; ON_ERROR general_on_error (); END_ERROR; FINISH ON_ERROR general_on_error (); END_ERROR; return FINI_OK; } static void compress(UCHAR * data, ULONG length) { /************************************** * * c o m p r e s s * ************************************** * * Functional description * Write out data in compressed form. * **************************************/ UCHAR *p, *q, *end; USHORT l, run; TGBL tdgbl; tdgbl = GET_THREAD_DATA; p = data; end = p + length; while (p < end) { for (q = p + 2; q < end && (q[-2] != q[-1] || q[-1] != q[0]); q++) ; if (run = (q < end) ? q - p - 2 : end - p) { for (; run > 127; run -= 127) { l = 127; PUT(l); p = PUT_BLOCK(p, l); } if (run) { PUT(run); p = PUT_BLOCK(p, run); } } for (q = p; q < end && *q == *p; q++) ; if (run = q - p) { for (; run > 127; run -= 127) { PUT(-127); PUT(*p); } if (run) { PUT(-run); PUT(*p); } p = q; } } } static int copy( TEXT * from, TEXT * to, ULONG size_len) { /************************************** * * c o p y * ************************************** * * Functional description * Copy a blank or null terminated string into a null terminated * string. * **************************************/ TEXT *p; ULONG l = 0; l = (ULONG) symbol_length (from, size_len); MOVE_FAST(from, to, l); *(to + l) = '\0'; return (int) l; } static void general_on_error(void) { /************************************** * * g e n e r a l _ o n _ e r r o r * ************************************** * * Functional description * Handle any general ON_ERROR clause during backup. * **************************************/ TGBL tdgbl; tdgbl = GET_THREAD_DATA; BURP_print_status(tdgbl->status); BURP_abort(); } static FLD get_fields( REL relation) { /************************************** * * g e t _ f i e l d s * ************************************** * * Functional description * Get fields for a relation. Test * capabilities and get system specific * **************************************/ FLD field, fields; ISC_QUAD *blob_id; USHORT count; TGBL tdgbl; tdgbl = GET_THREAD_DATA; count = 1; fields = NULL; /* if we have all capabilities, use the first request to get the most performance out of the latest engine; if we don't have one of the capabilities we must use the second set of requests--this requires more code but it is well worth it for the performance benefits, especially remotely--deej */ if ((tdgbl->BCK_capabilities & BCK_attributes_v3) && (tdgbl->BCK_capabilities & BCK_ods8) && (tdgbl->BCK_capabilities & BCK_rfr_sys_flag) && (tdgbl->BCK_capabilities & BCK_security)) { 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 = (FLD) BURP_ALLOC_ZERO (sizeof (struct 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_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 ((STATUS*) NULL_PTR, 52, field->fld_name, NULL); } /* 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; 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 field = (FLD) BURP_ALLOC_ZERO (sizeof (struct 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); if (tdgbl->BCK_capabilities & BCK_attributes_v3) FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle2) RFR IN RDB$RELATION_FIELDS WITH RFR.RDB$FIELD_NAME = X.RDB$FIELD_NAME AND RFR.RDB$RELATION_NAME = X.RDB$RELATION_NAME COPY (RFR.RDB$COMPLEX_NAME, field->fld_complex_name); END_FOR; ON_ERROR general_on_error (); END_ERROR; blob_id = &Y.RDB$COMPUTED_BLR; if (blob_id->gds_quad_low || blob_id->gds_quad_high) field->fld_flags |= FLD_computed; if (tdgbl->BCK_capabilities & BCK_rfr_sys_flag) FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle3) RFR IN RDB$RELATION_FIELDS WITH RFR.RDB$RELATION_NAME = relation->rel_name AND RFR.RDB$FIELD_NAME = X.RDB$FIELD_NAME field->fld_system_flag = RFR.RDB$SYSTEM_FLAG; END_FOR; ON_ERROR general_on_error (); END_ERROR; if (tdgbl->BCK_capabilities & BCK_security) FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle4) RFR IN RDB$RELATION_FIELDS WITH RFR.RDB$RELATION_NAME = relation->rel_name AND RFR.RDB$FIELD_NAME = X.RDB$FIELD_NAME COPY (RFR.RDB$SECURITY_CLASS, field->fld_security_class); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (tdgbl->BCK_capabilities & BCK_attributes_v3) FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle5) RF IN RDB$FIELDS WITH RF.RDB$FIELD_NAME = X.RDB$FIELD_SOURCE /* use the fld_flags to mark the field as an array and to differentiate it from other blobs */ if (RF.RDB$DIMENSIONS) { field->fld_flags |= FLD_array; field->fld_dimensions = RF.RDB$DIMENSIONS; if (field->fld_dimensions < 0) BURP_error_redirect ((STATUS*) NULL_PTR, 52, field->fld_name, NULL); /* msg 52 array dimension for field %s is invalid */ get_ranges (field); } END_FOR; ON_ERROR general_on_error (); END_ERROR; if (tdgbl->BCK_capabilities & BCK_ods8) FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle6) X2 IN RDB$RELATION_FIELDS CROSS F2 IN RDB$FIELDS WITH X2.RDB$FIELD_NAME = X.RDB$FIELD_NAME AND X2.RDB$RELATION_NAME EQ relation->rel_name AND X2.RDB$FIELD_SOURCE EQ F2.RDB$FIELD_NAME if (!X2.RDB$NULL_FLAG.NULL) { field->fld_null_flag = X2.RDB$NULL_FLAG; field->fld_flags |= FLD_null_flag; } if (!X2.RDB$DEFAULT_VALUE.NULL) { blob_id = &X2.RDB$DEFAULT_VALUE; if (blob_id->gds_quad_low || blob_id->gds_quad_high) field->fld_default_value = X2.RDB$DEFAULT_VALUE; } if (!X2.RDB$DEFAULT_SOURCE.NULL) { blob_id = &X2.RDB$DEFAULT_SOURCE; if (blob_id->gds_quad_low || blob_id->gds_quad_high) field->fld_default_source = X2.RDB$DEFAULT_SOURCE; } if (!(F2.RDB$CHARACTER_SET_ID.NULL)) { field->fld_character_set_id = F2.RDB$CHARACTER_SET_ID; field->fld_flags |= FLD_charset_flag; } if (!X2.RDB$COLLATION_ID.NULL) { field->fld_collation_id = X2.RDB$COLLATION_ID; field->fld_flags |= FLD_collate_flag; } END_FOR; ON_ERROR general_on_error (); END_ERROR; field->fld_next = fields; fields = field; END_FOR; ON_ERROR general_on_error (); END_ERROR; } return fields; } static SINT64 get_gen_id( TEXT * name, SSHORT name_len) { /************************************** * * g e t _ g e n _ i d * ************************************** * * Functional description * Read id for a generator; * **************************************/ UCHAR c, *blr, blr_buffer[100]; /* enough to fit blr */ SLONG *gen_id_reqh, read_msg0; SINT64 read_msg1; SSHORT blr_length; STATUS status_vector[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; gen_id_reqh = NULL; blr = blr_buffer; /* If this is ODS 10 (IB version 6.0) or greater, build BLR to retrieve the 64-bit value of the generator. If not, build BLR to retrieve the 32-bit value, which we will cast to the expected INT64 format. */ if (tdgbl->BCK_capabilities & BCK_ods10) { /* build the blr with the right relation name and 64-bit results. */ STUFF(blr_version5); STUFF(blr_begin); STUFF(blr_message); STUFF(0); STUFF_WORD(1); STUFF(blr_int64); STUFF(0); STUFF(blr_send); STUFF(0); STUFF(blr_assignment); STUFF(blr_gen_id); STUFF(name_len); while (name_len--) { c = *name++; STUFF(c); } STUFF(blr_literal); STUFF(blr_long); STUFF(0); STUFF_WORD(0); STUFF_WORD(0); STUFF(blr_parameter); STUFF(0); STUFF_WORD(0); STUFF(blr_end); STUFF(blr_eoc); } else { /* build the blr with the right relation name and 32-bit results */ STUFF(blr_version4); STUFF(blr_begin); STUFF(blr_message); STUFF(0); STUFF_WORD(1); STUFF(blr_long); STUFF(0); STUFF(blr_send); STUFF(0); STUFF(blr_assignment); STUFF(blr_gen_id); STUFF(name_len); while (name_len--) { c = *name++; STUFF(c); } STUFF(blr_literal); STUFF(blr_long); STUFF(0); STUFF_WORD(0); STUFF_WORD(0); STUFF(blr_parameter); STUFF(0); STUFF_WORD(0); STUFF(blr_end); STUFF(blr_eoc); } #ifdef DEBUG if (debug_on) isc_print_blr(blr_buffer, NULL_PTR, NULL_PTR, 0); #endif blr_length = blr - blr_buffer; if (isc_compile_request(status_vector, GDS_REF(tdgbl->db_handle), (void**) GDS_REF(gen_id_reqh), blr_length, (char*) GDS_VAL(blr_buffer))) /* if there's no gen_id, never mind ... */ return 0; if (isc_start_request(status_vector, (void**) GDS_REF(gen_id_reqh), GDS_REF(isc_trans), /* use the same one generated by gpre */ 0)) BURP_error_redirect(status_vector, 25, NULL, NULL); /* msg 25 Failed in put_blr_gen_id */ if (tdgbl->BCK_capabilities & BCK_ods10) { if (isc_receive(status_vector, (void**) GDS_REF(gen_id_reqh), 0, sizeof(read_msg1), GDS_REF(read_msg1), 0)) BURP_error_redirect(status_vector, 25, NULL, NULL); /* msg 25 Failed in put_blr_gen_id */ } else { if (isc_receive(status_vector, (void**) GDS_REF(gen_id_reqh), 0, sizeof(read_msg0), GDS_REF(read_msg0), 0)) BURP_error_redirect(status_vector, 25, NULL, NULL); /* msg 25 Failed in put_blr_gen_id */ read_msg1 = (SINT64) read_msg0; } isc_release_request(status_vector, (void**) GDS_REF(gen_id_reqh)); return read_msg1; } static void get_ranges( FLD field) { /************************************** * * g e t _ r a n g e s * ************************************** * * Functional description * Fill in the range low and high bounds by reading * the ranges in rdb$field_dimensions. * **************************************/ SLONG *rp; USHORT count; TGBL tdgbl; tdgbl = GET_THREAD_DATA; rp = field->fld_ranges; count = 0; /* Get the array dimensions in the rdb$field_dimensions */ FOR (REQUEST_HANDLE tdgbl->handles_get_ranges_req_handle1) X IN RDB$FIELD_DIMENSIONS WITH X.RDB$FIELD_NAME EQ field->fld_source SORTED BY X.RDB$DIMENSION if (count != X.RDB$DIMENSION) BURP_error_redirect ((STATUS*) NULL_PTR, 52, field->fld_name, NULL); /* msg 52 array dimension for field %s is invalid */ *rp++ = X.RDB$LOWER_BOUND; *rp++ = X.RDB$UPPER_BOUND; count++; END_FOR; ON_ERROR general_on_error (); END_ERROR; if (count != field->fld_dimensions) BURP_error_redirect((STATUS*) NULL_PTR, 52, field->fld_name, NULL); /* msg 52 array dimension for field %s is invalid */ } static void put_array( FLD field, REL relation, ISC_QUAD * blob_id) { /************************************** * * p u t _ a r r a y * ************************************** * * Functional description * Write out an array. If, however, it's null, don't even bother. * **************************************/ STATUS status_vector[ISC_STATUS_LENGTH]; SLONG *range, *end_ranges, returned_elements; ULONG return_length, slice_length; SLONG *returned_range, range_buffer[16]; /* enough for 16 dimensions */ LSTRING xdr_buffer, xdr_slice; UCHAR blr_buffer[200]; /* enough for a sdl with 16 dimensions */ UCHAR *blr, *slice, *p; USHORT blr_length, count, field_length; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* If the array is null, don't store it. It will be restored as null. */ if (!blob_id->gds_quad_low && !blob_id->gds_quad_high) return; xdr_buffer.lstr_allocated = 0; blr = blr_buffer; end_ranges = field->fld_ranges + 2 * field->fld_dimensions; field_length = field->fld_length; if (tdgbl->gbl_sw_transportable) xdr_buffer.lstr_length = field_length + 3; /* build the sdl */ STUFF(isc_sdl_version1); STUFF(isc_sdl_struct); STUFF(1); STUFF(field->fld_type); if (field->fld_type == blr_short || field->fld_type == blr_long || field->fld_type == blr_quad || field->fld_type == blr_int64) STUFF(field->fld_scale); if (field->fld_type == blr_text || field->fld_type == blr_varying) STUFF_WORD(field->fld_length); if (field->fld_type == blr_varying) field_length += sizeof(USHORT); STUFF(isc_sdl_rid); STUFF_WORD(relation->rel_id); STUFF(isc_sdl_fid); STUFF_WORD(field->fld_id); for (range = field->fld_ranges, count = 0; range < end_ranges; range += 2, count++) { STUFF(isc_sdl_do2); STUFF(count); STUFF(isc_sdl_long_integer); STUFF_LONG(range[0]); STUFF(isc_sdl_long_integer); STUFF_LONG(range[1]); } STUFF(isc_sdl_element); STUFF(1); STUFF(isc_sdl_scalar); STUFF(0); STUFF(field->fld_dimensions); for (count = 0; count < field->fld_dimensions; count++) { STUFF(isc_sdl_variable); STUFF(count); } STUFF(isc_sdl_eoc); #ifdef DEBUG if (debug_on) PRETTY_print_sdl(blr_buffer, NULL_PTR, NULL_PTR, NULL_PTR); #endif blr_length = blr - blr_buffer; /* compute the range size for each dimension = high_range - low_range */ slice_length = field_length; for (range = field->fld_ranges; range < end_ranges; range += 2) { slice_length *= (range[1] - range[0] + 1); if (tdgbl->gbl_sw_transportable) xdr_buffer.lstr_length *= (range[1] - range[0] + 1); } slice = BURP_ALLOC(slice_length); /* allocate space for the XDR representation */ if (tdgbl->gbl_sw_transportable) { xdr_buffer.lstr_address = BURP_ALLOC(xdr_buffer.lstr_length); xdr_buffer.lstr_allocated = xdr_buffer.lstr_length; } if (isc_get_slice(status_vector, GDS_REF(tdgbl->db_handle), GDS_REF(isc_trans), GDS_VAL(blob_id), blr_length, (char*) blr_buffer, 0, /* param length for subset of an array handling */ (SLONG *) 0, /* param for subset of an array handling */ slice_length, GDS_VAL(slice), (SLONG*) GDS_REF(return_length))) { BURP_print(81, field->fld_name, NULL, NULL, NULL, NULL); /* msg 81 error accessing blob field %s -- continuing */ BURP_print_status(status_vector); #ifdef DEBUG PRETTY_print_sdl(blr_buffer, NULL_PTR, NULL_PTR, NULL_PTR); #endif return; } if (return_length != slice_length) { int divisor, i1, i2, i3; /* Ugh. The full array wasn't returned. We must recompute the top element to backup. */ returned_elements = (return_length / field_length) - 1; returned_range = range_buffer; for (i1 = 0, i3 = 0, range = end_ranges - 2; range >= field->fld_ranges; range -= 2, returned_range++, i1++) { divisor = 1; for (i2 = (2 * (i1 + 1) + 1); i2 <= field->fld_dimensions * 2; i2 += 2) divisor *= (field->fld_ranges[i2] - field->fld_ranges[i2 - 1] + 1); *returned_range = (returned_elements - 1) / divisor + field->fld_ranges[i3]; returned_elements -= (*returned_range - field->fld_ranges[i3]) * divisor; i3 += 2; } } PUT(rec_array); PUT_NUMERIC(att_blob_field_number, field->fld_number); PUT_NUMERIC(att_array_dimensions, field->fld_dimensions); returned_range = range_buffer; for (range = field->fld_ranges; range < end_ranges; range += 2, returned_range++) { PUT_NUMERIC(att_array_range_low, (int) range[0]); if (return_length == slice_length) PUT_NUMERIC(att_array_range_high, (int) range[1]); else PUT_NUMERIC(att_array_range_high, (int) *returned_range); } PUT(att_blob_data); PUT(return_length); PUT(return_length >> 8); PUT(return_length >> 16); PUT(return_length >> 24); if (return_length) { if (tdgbl->gbl_sw_transportable) { xdr_slice.lstr_allocated = xdr_slice.lstr_length = return_length; xdr_slice.lstr_address = slice; return_length = CAN_slice(&xdr_buffer, &xdr_slice, TRUE, blr_length, blr_buffer); PUT(att_xdr_array); PUT(return_length); PUT(return_length >> 8); PUT(return_length >> 16); PUT(return_length >> 24); p = xdr_buffer.lstr_address; } else p = slice; (void) PUT_BLOCK(p, return_length); } BURP_FREE(slice); if (xdr_buffer.lstr_allocated) BURP_FREE(xdr_buffer.lstr_address); } static void put_asciz( SCHAR attribute, TEXT * string) { /************************************** * * p u t _ a s c i z * ************************************** * * Functional description * Write an attribute starting with a null terminated string. * **************************************/ ULONG l; TGBL tdgbl; tdgbl = GET_THREAD_DATA; l = strlen(string); PUT(attribute); PUT(l); if (l) (void) PUT_BLOCK((UCHAR*) string, l); } static void put_blob( FLD field, ISC_QUAD * blob_id, ULONG count) { /************************************** * * p u t _ b l o b * ************************************** * * Functional description * Write out a blob. If, however, it's null, don't even bother. * **************************************/ STATUS status_vector[ISC_STATUS_LENGTH]; void *blob; ULONG segments; UCHAR *p, blob_info[32], item, *buffer, static_buffer[1024]; USHORT l, max_segment, n; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* If the blob is null, don't store it. It will be restored as null. */ if (!blob_id->gds_quad_high && !blob_id->gds_quad_low) return; /* Open the blob and get it's vital statistics */ blob = NULL; if (isc_open_blob(status_vector, GDS_REF(tdgbl->db_handle), GDS_REF(isc_trans), GDS_REF(blob), GDS_VAL(blob_id))) { BURP_print(81, field->fld_name, NULL, NULL, NULL, NULL); /* msg 81 error accessing blob field %s -- continuing */ BURP_print_status(status_vector); return; } if (isc_blob_info(status_vector, GDS_REF(blob), sizeof(blob_items), (SCHAR *) blob_items, sizeof(blob_info), (char*) blob_info)) { BURP_error_redirect(status_vector, 20, NULL, NULL); /* msg 20 isc_blob_info failed */ } PUT(rec_blob); PUT_NUMERIC(att_blob_field_number, field->fld_number); segments = max_segment = 0; p = blob_info; while ((item = *p++) != isc_info_end) { l = (USHORT) isc_vax_integer((char*) p, 2); p += 2; n = (USHORT) isc_vax_integer((char*) p, l); p += l; switch (item) { case isc_info_blob_max_segment: PUT_NUMERIC(att_blob_max_segment, (int) n); max_segment = n; break; case isc_info_blob_type: PUT_NUMERIC(att_blob_type, (int) n); break; case isc_info_blob_num_segments: PUT_NUMERIC(att_blob_number_segments, (int) n); segments = n; break; default: BURP_error_redirect((STATUS*) NULL_PTR, 21, (void *) item, NULL); /* msg 21 don't understand blob info item %ld */ } } /* Allocate a buffer large enough for the largest segment and start grinding. */ if (!max_segment || max_segment <= sizeof(static_buffer)) buffer = static_buffer; else buffer = BURP_ALLOC(max_segment); PUT(att_blob_data); while (segments > 0) { if (isc_get_segment(status_vector, GDS_REF(blob), GDS_REF(l), max_segment, (char*) GDS_VAL(buffer))) { BURP_error_redirect(status_vector, 22, NULL, NULL); } /* msg 22 gds__get_segment failed */ PUT(l); PUT(l >> 8); if (l) { (void) PUT_BLOCK(buffer, l); } --segments; } if (isc_close_blob(status_vector, GDS_REF(blob))) BURP_error_redirect(status_vector, 23, NULL, NULL); /* msg 23 isc_close_blob failed */ if (buffer != static_buffer) BURP_FREE(buffer); } static int put_blr_blob( SCHAR attribute, ISC_QUAD * blob_id) { /************************************** * * p u t _ b l r _ b l o b * ************************************** * * Functional description * Write out a blr blob, if present. Otherwise do nothing. * Return TRUE is there was the blob was present, FALSE otherwise. * **************************************/ STATUS status_vector[ISC_STATUS_LENGTH]; ULONG length, n; void *blob; UCHAR *p, blob_info[32], item, *buffer, static_buffer[1024]; ULONG max_segment; USHORT l; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* If the blob is null, don't store it. It will be restored as null. */ if (!blob_id->gds_quad_high && !blob_id->gds_quad_low) return FALSE; /* Open the blob and get it's vital statistics */ blob = NULL; if (isc_open_blob(status_vector, GDS_REF(tdgbl->db_handle), GDS_REF(isc_trans), GDS_REF(blob), GDS_VAL(blob_id))) { BURP_error_redirect(status_vector, 24, NULL, NULL); /* msg 24 isc_open_blob failed */ } if (isc_blob_info(status_vector, GDS_REF(blob), sizeof(blr_items), (SCHAR *) blr_items, sizeof(blob_info), (char*) blob_info)) { BURP_error_redirect(status_vector, 20, NULL, NULL); /* msg 20 isc_blob_info failed */ } length = 0; p = blob_info; while ((item = *p++) != isc_info_end) { l = (USHORT) isc_vax_integer((char*) p, 2); p += 2; n = (USHORT) isc_vax_integer((char*) p, l); p += l; switch (item) { case isc_info_blob_max_segment: max_segment = n; break; case isc_info_blob_total_length: length = n; break; default: BURP_print(79, (void *) item, NULL, NULL, NULL, NULL); /* msg 79 don't understand blob info item %ld */ return FALSE; } } if (!length) { if (isc_close_blob(status_vector, GDS_REF(blob))) BURP_error_redirect(status_vector, 23, NULL, NULL); /* msg 23 isc_close_blob failed */ return FALSE; } /* Rdb sometimes gets the length messed up */ if (length < max_segment) length = max_segment; PUT_NUMERIC(attribute, (int) length); /* Allocate a buffer large enough for the largest segment and start grinding. */ if (!max_segment || max_segment <= sizeof(static_buffer)) buffer = static_buffer; else buffer = BURP_ALLOC(max_segment); while (!isc_get_segment(status_vector, GDS_REF(blob), GDS_REF(l), (USHORT) max_segment, (char*) GDS_VAL(buffer))) { if (l) { (void) PUT_BLOCK(buffer, l); } } if (isc_close_blob(status_vector, GDS_REF(blob))) { BURP_error_redirect(status_vector, 23, NULL, NULL); } /* msg 23 isc_close_blob failed */ if (buffer != static_buffer) BURP_FREE(buffer); return TRUE; } static void put_data(REL relation) { /************************************** * * p u t _ d a t a * ************************************** * * Functional description * Write relation meta-data and data. * **************************************/ FLD field; int *request, records; UCHAR *p, *blr, *blr_buffer, *buffer; LSTRING xdr_buffer; STATUS status_vector[ISC_STATUS_LENGTH]; RCRD_OFFSET offset, eof_offset, record_length; FLD_LENGTH length; SSHORT alignment, blr_length, count, dtype, *eof, eof_parameter; TGBL tdgbl; tdgbl = GET_THREAD_DATA; count = 1; for (field = relation->rel_fields; field; field = field->fld_next) { if (!(field->fld_flags & FLD_computed)) { count += 2; } } /* Time to generate blr to fetch data. Make sure we allocate a BLR buffer large enough to handle the per field overhead */ blr = blr_buffer = BURP_ALLOC(200 + count * 9); STUFF(blr_version4); STUFF(blr_begin); STUFF(blr_message); STUFF(0); /* Message number */ STUFF_WORD(count); /* Number of fields, counting eof */ offset = count = 0; for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_computed) continue; alignment = 4; length = field->fld_length; dtype = field->fld_type; if (field->fld_flags & FLD_array) { dtype = blr_blob; length = 8; } switch (dtype) { case blr_text: alignment = type_alignments[dtype_text]; STUFF(field->fld_type); STUFF_WORD(field->fld_length); break; case blr_varying: alignment = type_alignments[dtype_varying]; STUFF(field->fld_type); STUFF_WORD(field->fld_length); length += sizeof(USHORT); break; case blr_short: alignment = type_alignments[dtype_short]; STUFF(field->fld_type); STUFF(field->fld_scale); break; case blr_long: alignment = type_alignments[dtype_long]; STUFF(field->fld_type); STUFF(field->fld_scale); break; case blr_quad: alignment = type_alignments[dtype_quad]; STUFF(field->fld_type); STUFF(field->fld_scale); break; case blr_int64: alignment = type_alignments[dtype_int64]; STUFF(field->fld_type); STUFF(field->fld_scale); break; case blr_double: alignment = type_alignments[dtype_double]; STUFF(field->fld_type); break; case blr_timestamp: alignment = type_alignments[dtype_timestamp]; STUFF(field->fld_type); break; case blr_sql_time: alignment = type_alignments[dtype_sql_time]; STUFF(field->fld_type); break; case blr_sql_date: alignment = type_alignments[dtype_sql_date]; STUFF(field->fld_type); break; case blr_float: alignment = type_alignments[dtype_real]; STUFF(field->fld_type); break; case blr_blob: alignment = type_alignments[dtype_blob]; STUFF(blr_quad); STUFF(0); break; default: BURP_error_redirect((STATUS*) NULL_PTR, 26, (void *) field->fld_type, NULL); /* msg 26 datatype %ld not understood */ break; } if (alignment) offset = FB_ALIGN(offset, alignment); field->fld_offset = offset; field->fld_parameter = count++; offset += length; } /* Next, build fields for null flags */ for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_computed) continue; STUFF(blr_short); STUFF(0); offset = FB_ALIGN(offset, sizeof(SSHORT)); field->fld_missing_parameter = count++; offset += sizeof(SSHORT); } /* Finally, make up an EOF field */ STUFF(blr_short); /* eof field */ STUFF(0); /* scale for eof field */ record_length = offset; eof_parameter = count++; eof_offset = FB_ALIGN(offset, sizeof(SSHORT)); length = (USHORT) (eof_offset + sizeof(SSHORT)); /* Build FOR loop, body, and eof handler */ STUFF(blr_for); STUFF(blr_rse); STUFF(1); /* count of relations */ STUFF(blr_rid); STUFF_WORD(relation->rel_id); STUFF(0); /* context variable */ STUFF(blr_end); STUFF(blr_send); STUFF(0); STUFF(blr_begin); STUFF(blr_assignment); STUFF(blr_literal); STUFF(blr_short); STUFF(0); STUFF_WORD(1); STUFF(blr_parameter); STUFF(0); STUFF_WORD(eof_parameter); for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_computed) continue; STUFF(blr_assignment); STUFF(blr_fid); STUFF(0); STUFF_WORD(field->fld_id); STUFF(blr_parameter2); STUFF(0); STUFF_WORD(field->fld_parameter); STUFF_WORD(field->fld_missing_parameter); } STUFF(blr_end); STUFF(blr_send); STUFF(0); STUFF(blr_assignment); STUFF(blr_literal); STUFF(blr_short); STUFF(0); STUFF_WORD(0); STUFF(blr_parameter); STUFF(0); STUFF_WORD(eof_parameter); STUFF(blr_end); STUFF(blr_eoc); #ifdef DEBUG if (debug_on) isc_print_blr(blr_buffer, NULL_PTR, NULL_PTR, 0); #endif /* Compile request */ request = NULL; blr_length = blr - blr_buffer; if (isc_compile_request(status_vector, GDS_REF(tdgbl->db_handle), (void**) GDS_REF(request), blr_length, (SCHAR*) GDS_VAL(blr_buffer))) { BURP_error_redirect(status_vector, 27, NULL, NULL); /* msg 27 isc_compile_request failed */ isc_print_blr((char*) blr_buffer, (isc_callback)NULL_PTR, NULL_PTR, 0); } BURP_FREE(blr_buffer); records = 0; BURP_verbose(142, relation->rel_name, NULL, NULL, NULL, NULL); /* msg 142 writing data for relation %s */ if (isc_start_request(status_vector, (void**) GDS_REF(request), GDS_REF(isc_trans), 0)) { BURP_error_redirect(status_vector, 28, NULL, NULL); /* msg 28 isc_start_request failed */ } /* Here is the crux of the problem -- writing data. All this work for the following small loop. */ buffer = BURP_ALLOC(length); eof = (SSHORT *) (buffer + eof_offset); /* the XDR representation may be even fluffier */ if (tdgbl->gbl_sw_transportable) { xdr_buffer.lstr_length = xdr_buffer.lstr_allocated = length + count * 3; xdr_buffer.lstr_address = BURP_ALLOC(xdr_buffer.lstr_length); } else xdr_buffer.lstr_address = NULL; while (TRUE) { if (isc_receive(status_vector, (void**) GDS_REF(request), 0, length, GDS_VAL(buffer), 0)) { BURP_error_redirect(status_vector, 29, NULL, NULL); /* msg 29 isc_receive failed */ } if (!*eof) break; records++; /* Verbose records */ if ((records % BACKUP_VERBOSE_INTERVAL) == 0) BURP_verbose(108, (void *) records, NULL, NULL, NULL, NULL); PUT(rec_data); PUT_NUMERIC(att_data_length, record_length); if (tdgbl->gbl_sw_transportable) { record_length = CAN_encode_decode(relation, &xdr_buffer, buffer, TRUE); PUT_NUMERIC(att_xdr_length, record_length); p = xdr_buffer.lstr_address; } else p = buffer; PUT(att_data_data); if (tdgbl->gbl_sw_compress) compress(p, record_length); else if (record_length) (void) PUT_BLOCK(p, record_length); /* Look for any blobs to write */ for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_type == blr_blob && !(field->fld_flags & FLD_computed) && !(field->fld_flags & FLD_array)) { put_blob(field, (ISC_QUAD*) (buffer + field-> fld_offset), records); } } /* Look for any array to write */ /* we got back the blob_id for the array from isc_receive in the second param. */ for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_array) { put_array(field, relation, (ISC_QUAD *) (buffer + field->fld_offset)); } } } BURP_FREE(buffer); if (xdr_buffer.lstr_address) BURP_FREE(xdr_buffer.lstr_address); BURP_verbose(108, (void *) records, NULL, NULL, NULL, NULL); /* msg 108 %ld records written */ if (isc_release_request(status_vector, (void**) GDS_REF(request))) BURP_error_redirect(status_vector, 30, NULL, NULL); /* msg 30 isc_release_request failed */ } static void put_index( REL relation) { /************************************** * * p u t _ i n d e x * ************************************** * * Functional description * Write information about an index. First * check that all the segments of the * index exist. * **************************************/ ULONG l, count, match; TEXT temp[GDS_NAME_LEN]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* if we have all capabilities, use the first request to get the most performance out of the latest engine; if we don't have one of the capabilities we must use the second set of requests--this requires more code but it is well worth it for the performance benefits, especially remotely--deej */ if ((tdgbl->BCK_capabilities & BCK_idx_inactive) && (tdgbl->BCK_capabilities & BCK_attributes_v3) && (tdgbl->BCK_capabilities & BCK_ods8)) { FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle1) X IN RDB$INDICES WITH X.RDB$RELATION_NAME EQ relation->rel_name count = 0; FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle2) I_S IN RDB$INDEX_SEGMENTS CROSS RFR IN RDB$RELATION_FIELDS WITH I_S.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME AND I_S.RDB$INDEX_NAME = X.RDB$INDEX_NAME AND RFR.RDB$RELATION_NAME = relation->rel_name count++; END_FOR; ON_ERROR general_on_error (); END_ERROR; if (count != (ULONG) X.RDB$SEGMENT_COUNT) { BURP_print (180, X.RDB$INDEX_NAME, (void*) count, (void*) X.RDB$SEGMENT_COUNT, NULL, NULL); continue; } PUT (rec_index); l = PUT_TEXT (att_index_name, X.RDB$INDEX_NAME); MISC_terminate ((UCHAR*) X.RDB$INDEX_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (151, temp, NULL, NULL, NULL, NULL); /* msg 151 writing index %s */ PUT_NUMERIC (att_segment_count, X.RDB$SEGMENT_COUNT); PUT_NUMERIC (att_index_inactive, X.RDB$INDEX_INACTIVE); PUT_NUMERIC (att_index_unique_flag, X.RDB$UNIQUE_FLAG); FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle5) Y IN RDB$INDEX_SEGMENTS WITH Y.RDB$INDEX_NAME EQ X.RDB$INDEX_NAME SORTED BY Y.RDB$FIELD_POSITION PUT_TEXT (att_index_field_name, Y.RDB$FIELD_NAME); END_FOR; ON_ERROR general_on_error (); END_ERROR; put_source_blob (att_index_description2, att_index_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT_NUMERIC (att_index_type, X.RDB$INDEX_TYPE); if (!X.RDB$EXPRESSION_SOURCE.NULL) put_source_blob (att_index_expression_source, att_index_expression_source, (ISC_QUAD *)&X.RDB$EXPRESSION_SOURCE); if (!X.RDB$EXPRESSION_BLR.NULL) put_blr_blob (att_index_expression_blr, (ISC_QUAD *)&X.RDB$EXPRESSION_BLR); if (!X.RDB$FOREIGN_KEY.NULL) PUT_TEXT (att_index_foreign_key, X.RDB$FOREIGN_KEY); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } else { FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle1) X IN RDB$INDICES WITH X.RDB$RELATION_NAME EQ relation->rel_name count = 0; FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle2) I_S IN RDB$INDEX_SEGMENTS WITH I_S.RDB$INDEX_NAME = X.RDB$INDEX_NAME match = FALSE; FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle3) RFR IN RDB$RELATION_FIELDS WITH I_S.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME AND RFR.RDB$RELATION_NAME = relation->rel_name match = TRUE; END_FOR; ON_ERROR general_on_error (); END_ERROR; if (!match) BURP_print (179, I_S.RDB$FIELD_NAME, X.RDB$INDEX_NAME, NULL, NULL, NULL); else count++; END_FOR; ON_ERROR general_on_error (); END_ERROR; if (count != (ULONG) X.RDB$SEGMENT_COUNT) { BURP_print (180, X.RDB$INDEX_NAME, (void*) count, (void*) X.RDB$SEGMENT_COUNT, NULL, NULL); continue; } PUT (rec_index); l = PUT_TEXT (att_index_name, X.RDB$INDEX_NAME); MISC_terminate ((UCHAR*) X.RDB$INDEX_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (151, temp, NULL, NULL, NULL, NULL); /* msg 151 writing index %s */ PUT_NUMERIC (att_segment_count, X.RDB$SEGMENT_COUNT); if (tdgbl->BCK_capabilities & BCK_idx_inactive) FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle4) I IN RDB$INDICES WITH I.RDB$INDEX_NAME = X.RDB$INDEX_NAME PUT_NUMERIC (att_index_inactive, I.RDB$INDEX_INACTIVE); END_FOR; ON_ERROR general_on_error (); END_ERROR; PUT_NUMERIC (att_index_unique_flag, X.RDB$UNIQUE_FLAG); FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle5) Y IN RDB$INDEX_SEGMENTS WITH Y.RDB$INDEX_NAME EQ X.RDB$INDEX_NAME SORTED BY Y.RDB$FIELD_POSITION PUT_TEXT (att_index_field_name, Y.RDB$FIELD_NAME); END_FOR; ON_ERROR general_on_error (); END_ERROR; put_source_blob (att_index_description2, att_index_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); if (tdgbl->BCK_capabilities & BCK_attributes_v3) FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle6) I IN RDB$INDICES WITH I.RDB$INDEX_NAME = X.RDB$INDEX_NAME PUT_NUMERIC (att_index_type, I.RDB$INDEX_TYPE); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (tdgbl->BCK_capabilities & BCK_ods8) FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle7) I IN RDB$INDICES WITH I.RDB$INDEX_NAME = X.RDB$INDEX_NAME if (!I.RDB$EXPRESSION_SOURCE.NULL) put_source_blob (att_index_expression_source, att_index_expression_source, (ISC_QUAD *)&I.RDB$EXPRESSION_SOURCE); if (!I.RDB$EXPRESSION_BLR.NULL) put_blr_blob (att_index_expression_blr, (ISC_QUAD *)&I.RDB$EXPRESSION_BLR); if (!I.RDB$FOREIGN_KEY.NULL) PUT_TEXT (att_index_foreign_key, I.RDB$FOREIGN_KEY); END_FOR; ON_ERROR general_on_error (); END_ERROR; PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } } static int put_message( SCHAR attribute, TEXT * text, ULONG length) { /************************************** * * p u t _ m e s s a g e * ************************************** * * Functional description * Write a variable length text string, with embedded * blanks. Same as put_text but handles embedded blanks. * CVC: As v6 time, put_text handles embedded blanks, too! * The only difference is that put_text's length is SSHORT, so * in theory put_message can handle much longer input and it's * 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). * **************************************/ TEXT *p; ULONG l; TGBL tdgbl; tdgbl = GET_THREAD_DATA; for (p = text, l = 0; *p && l < length; p++) l++; l = length = MIN(l, length); PUT(attribute); PUT(l); if (l) (void) PUT_BLOCK((UCHAR*) text, l); return length; } static void put_numeric( SCHAR attribute, SLONG value) { /************************************** * * p u t _ n u m e r i c * ************************************** * * Functional description * Write a numeric value as an attribute. The number is represented * low byte first, high byte last, as in VAX. * **************************************/ SLONG vax_value; TGBL tdgbl; tdgbl = GET_THREAD_DATA; vax_value = (SLONG) isc_vax_integer((char *) & value, sizeof(value)); PUT(attribute); PUT(sizeof(value)); (void) PUT_BLOCK((UCHAR *) & vax_value, sizeof(vax_value)); } static void put_int64( SCHAR attribute, SINT64 value) { /************************************** * * p u t _ i n t 6 4 * ************************************** * * Functional description * Write a 64-bit numeric value as an attribute. * The number is represented low byte first, high byte last, as in VAX. * This function is just like put_numeric, except that it handles an * INT64 value, while put_numeric handles a 32-bit value. * **************************************/ UINT64 le_value; TGBL tdgbl; tdgbl = GET_THREAD_DATA; le_value = (UINT64) isc_portable_integer((UCHAR *) (&value), sizeof(value)); PUT(attribute); PUT(sizeof(value)); (void) PUT_BLOCK((UCHAR *) & le_value, sizeof(le_value)); } static void put_relation( REL relation) { /************************************** * * p u t _ r e l a t i o n * ************************************** * * Functional description * Write relation meta-data and data. * **************************************/ FLD fields, field, aligned, unaligned, aligned4, aligned8; TEXT temp[GDS_NAME_LEN]; USHORT l, n; SLONG *rp; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* Write local field information. This is made slightly more complicated by the requirement that computational fields be aligned. */ aligned = unaligned = aligned4 = aligned8 = NULL; fields = get_fields(relation); /* sort the list of fields into three lists, depending on alignment */ for (field = fields; field = fields;) { fields = field->fld_next; l = field->fld_length; if (field->fld_type == blr_varying) l += sizeof(USHORT); if (!(l & 7)) { field->fld_next = aligned8; aligned8 = field; } else if (!(l & 3)) { field->fld_next = aligned4; aligned4 = field; } else if (l & 1) { field->fld_next = unaligned; unaligned = field; } else { field->fld_next = aligned; aligned = field; } } /* Next, merge the aligned and unaligned sub-lists. In the process, re-create (approximately) the original order of the fields. This is not strictly required, but it certainly is polite. */ while (field = unaligned) { unaligned = field->fld_next; field->fld_next = relation->rel_fields; relation->rel_fields = field; } while (field = aligned) { aligned = field->fld_next; field->fld_next = relation->rel_fields; relation->rel_fields = field; } while (field = aligned4) { aligned4 = field->fld_next; field->fld_next = relation->rel_fields; relation->rel_fields = field; } while (field = aligned8) { aligned8 = field->fld_next; field->fld_next = relation->rel_fields; relation->rel_fields = field; } /* Now write the fields in what will become physical backup order */ for (field = relation->rel_fields; field; field = field->fld_next) { PUT(rec_field); l = PUT_TEXT(att_field_name, field->fld_name); MISC_terminate((UCHAR*) field->fld_name, (UCHAR*) temp, l, sizeof(temp)); BURP_verbose(144, temp, NULL, NULL, NULL, NULL); /* msg 144 writing field %s */ PUT_TEXT(att_field_source, field->fld_source); if (field->fld_query_name[0]) PUT_TEXT(att_field_query_name, field->fld_query_name); if (field->fld_complex_name[0]) PUT_TEXT(att_field_complex_name, field->fld_complex_name); if (field->fld_edit_string[0]) PUT_TEXT(att_field_edit_string, field->fld_edit_string); put_source_blob(att_field_description2, att_field_description, (ISC_QUAD *) & field->fld_description); put_source_blob(att_field_query_header, att_field_query_header, (ISC_QUAD *) & field->fld_query_header); if (field->fld_security_class[0]) PUT_TEXT(att_field_security_class, field->fld_security_class); if (!(field->fld_flags & FLD_position_missing)) PUT_NUMERIC(att_field_position, field->fld_position); PUT_NUMERIC(att_field_type, field->fld_type); PUT_NUMERIC(att_field_length, field->fld_length); PUT_NUMERIC(att_field_sub_type, field->fld_sub_type); PUT_NUMERIC(att_field_scale, field->fld_scale); PUT_NUMERIC(att_field_number, field->fld_number); PUT_NUMERIC(att_field_system_flag, field->fld_system_flag); if (!(field->fld_flags & FLD_update_missing)) PUT_NUMERIC(att_field_update_flag, field->fld_update_flag); if (field->fld_flags & FLD_null_flag) PUT_NUMERIC(att_field_null_flag, field->fld_null_flag); if (field->fld_flags & FLD_charset_flag) PUT_NUMERIC(att_field_character_set, field->fld_character_set_id); if (field->fld_flags & FLD_collate_flag) PUT_NUMERIC(att_field_collation_id, field->fld_collation_id); put_blr_blob(att_field_default_value, (ISC_QUAD *) & field->fld_default_value); put_source_blob(att_field_default_source, att_field_default_source, (ISC_QUAD *) & field->fld_default_source); if (relation->rel_flags & REL_view) { PUT_NUMERIC(att_view_context, field->fld_view_context); 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); for (rp = field->fld_ranges, n = field->fld_dimensions; n; rp += 2, n--) { PUT_NUMERIC(att_field_range_low, *rp); PUT_NUMERIC(att_field_range_high, *(rp + 1)); } } PUT(att_end); } /* Write out view relations (if a view, of course) */ if (relation->rel_flags & REL_view) { if (tdgbl->BCK_capabilities & BCK_context_name) { FOR (REQUEST_HANDLE tdgbl->handles_put_relation_req_handle1) X IN RDB$VIEW_RELATIONS WITH X.RDB$VIEW_NAME EQ relation->rel_name PUT (rec_view); PUT_TEXT (att_view_relation_name, X.RDB$RELATION_NAME); PUT_NUMERIC (att_view_context_id, X.RDB$VIEW_CONTEXT); PUT_TEXT (att_view_context_name, X.RDB$CONTEXT_NAME); PUT (att_end); END_FOR ON_ERROR general_on_error (); END_ERROR; } else { FOR (REQUEST_HANDLE tdgbl->handles_put_relation_req_handle2) X IN RDB$VIEW_RELATIONS WITH X.RDB$VIEW_NAME EQ relation->rel_name PUT (rec_view); PUT_TEXT (att_view_relation_name, X.RDB$RELATION_NAME); PUT_NUMERIC (att_view_context_id, X.RDB$VIEW_CONTEXT); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } } PUT(rec_relation_end); } static int put_source_blob(SCHAR attribute, SCHAR old_attribute, ISC_QUAD* blob_id) { /************************************** * * p u t _ s o u r c e _ b l o b * ************************************** * * Functional description * Write out a source blob or query header if present. * Return TRUE is there was the blob was present, FALSE otherwise. * **************************************/ STATUS status_vector[ISC_STATUS_LENGTH]; SLONG length, n; void *blob; UCHAR *p, blob_info[48], item, *buffer, static_buffer[1024]; USHORT l, max_segment, num_seg; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* If the blob is null, don't store it. It will be restored as null. */ if (!blob_id->gds_quad_high && !blob_id->gds_quad_low) return FALSE; if (tdgbl->gbl_sw_old_descriptions && attribute != att_field_query_header) return put_blr_blob(old_attribute, (ISC_QUAD *) blob_id); /* Open the blob and get it's vital statistics */ blob = NULL; if (isc_open_blob(status_vector, GDS_REF(tdgbl->db_handle), GDS_REF(isc_trans), GDS_REF(blob), GDS_VAL(blob_id))) { BURP_error_redirect(status_vector, 24, NULL, NULL); /* msg 24 isc_open_blob failed */ } if (isc_blob_info(status_vector, GDS_REF(blob), sizeof(source_items), (SCHAR *) source_items, sizeof(blob_info), (SCHAR*) blob_info)) { BURP_error_redirect(status_vector, 20, NULL, NULL); /* msg 20 isc_blob_info failed */ } length = 0; p = blob_info; while ((item = *p++) != isc_info_end) { l = (USHORT) isc_vax_integer((SCHAR*) p, 2); p += 2; n = (USHORT) isc_vax_integer((SCHAR*) p, l); p += l; switch (item) { case isc_info_blob_max_segment: max_segment = (USHORT) n; break; case isc_info_blob_total_length: length = n; break; case isc_info_blob_num_segments: num_seg = (USHORT) n; break; default: BURP_print(79, (void *) item, NULL, NULL, NULL, NULL); /* msg 79 don't understand blob info item %ld */ return FALSE; } } if (!length) { if (isc_close_blob(status_vector, GDS_REF(blob))) { BURP_error_redirect(status_vector, 23, NULL, NULL); /* msg 23 isc_close_blob failed */ } return FALSE; } /* Rdb sometimes gets the length messed up */ if (length < max_segment) length = max_segment; PUT_NUMERIC(attribute, length + num_seg); /* Allocate a buffer large enough for the largest segment and start grinding. */ if (!max_segment || max_segment <= sizeof(static_buffer)) buffer = static_buffer; else buffer = BURP_ALLOC(max_segment); while (!isc_get_segment(status_vector, GDS_REF(blob), GDS_REF(l), max_segment, (SCHAR*) GDS_VAL(buffer))) { if (l) { (void) PUT_BLOCK(buffer, l); } PUT(NULL); } if (isc_close_blob(status_vector, GDS_REF(blob))) BURP_error_redirect(status_vector, 23, NULL, NULL); /* msg 23 isc_close_blob failed */ if (buffer != static_buffer) BURP_FREE(buffer); return TRUE; } static int put_text( SCHAR attribute, TEXT * text, SSHORT size_len) { /************************************** * * p u t _ t e x t * ************************************** * * Functional description * Write a variable length text string, with embedded spaces. * Truncate trailing spaces. * 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. * **************************************/ SSHORT l; TGBL tdgbl; tdgbl = GET_THREAD_DATA; l = (SSHORT) symbol_length (text, (ULONG) size_len); PUT(attribute); PUT(l); if (l) (void) PUT_BLOCK((UCHAR*) text, l); return l; } static void put_trigger(enum trig_t type, GDS__QUAD * blob_ident, GDS__QUAD * source_blob, GDS_NAME rel_name) { /************************************** * * p u t _ t r i g g e r * ************************************** * * Functional description * Write a trigger to the output file. * NOTE: This is used backup pre-V3 triggers only * **************************************/ TGBL tdgbl; tdgbl = GET_THREAD_DATA; if (!blob_ident->gds_quad_low) return; PUT(rec_trigger); PUT_NUMERIC(att_trig_type, type); put_blr_blob(att_trig_blr, (ISC_QUAD *) blob_ident); put_source_blob(att_trig_source2, att_trig_source, (ISC_QUAD *) source_blob); PUT(att_end); } static void set_capabilities(void) { /************************************** * * s e t _ c a p a b i l i t i e s * ************************************** * * Functional description * * set the capabilities bits for the * database being extracted to avoid * unpleasantness later. * **************************************/ ULONG *req; RFR_TAB rel_field_table; TEXT *relation, *field; TGBL tdgbl; tdgbl = GET_THREAD_DATA; req = NULL; /* Look for desireable fields in system relations */ for (rel_field_table = (RFR_TAB) rfr_table; rel_field_table->relation; rel_field_table++) { field = (TEXT *) rel_field_table->field; relation = (TEXT *) rel_field_table->relation; FOR (REQUEST_HANDLE req) x IN RDB$RELATION_FIELDS WITH x.RDB$RELATION_NAME = relation AND x.RDB$FIELD_NAME = field tdgbl->BCK_capabilities |= rel_field_table->bit_mask; END_FOR; ON_ERROR general_on_error (); END_ERROR; } isc_release_request(isc_status, (void**) GDS_REF(req)); } static int symbol_length( TEXT * symbol, ULONG size_len) { /************************************** * * s y m b o l _ l e n g t h * ************************************** * * Functional description * Compute length of null terminated symbol. * CVC: This function should acknowledge embedded blanks. * **************************************/ TEXT *p, *q; if (size_len < 2) { return 0; } --size_len; p = symbol; q = p + size_len; while (*p && p < q) { // find end of string (null or end). p++; } --p; while (p >= symbol && *p == ' ') { // skip trailing blanks --p; } return p + 1 - symbol; } static void write_character_sets(void) { /************************************** * * w r i t e _ c h a r a c t e r _ s e t s * ************************************** * * Functional description * write a record in the burp file for * each user defined character set. * **************************************/ isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$CHARACTER_SETS WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1 PUT (rec_charset); PUT_TEXT (att_charset_name, X.RDB$CHARACTER_SET_NAME); if (!X.RDB$FORM_OF_USE.NULL) PUT_TEXT (att_charset_form, X.RDB$FORM_OF_USE); if (!X.RDB$NUMBER_OF_CHARACTERS.NULL) PUT_NUMERIC (att_charset_numchar, X.RDB$NUMBER_OF_CHARACTERS); PUT_TEXT (att_charset_coll, X.RDB$DEFAULT_COLLATE_NAME); PUT_NUMERIC (att_charset_id, X.RDB$CHARACTER_SET_ID); if (X.RDB$SYSTEM_FLAG) PUT_NUMERIC (att_charset_sysflag, X.RDB$SYSTEM_FLAG); if (!X.RDB$DESCRIPTION.NULL) put_source_blob (att_charset_description, att_charset_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); if (!X.RDB$FUNCTION_NAME.NULL) PUT_TEXT (att_charset_funct, X.RDB$FUNCTION_NAME); PUT_NUMERIC (att_charset_bytes_char, X.RDB$BYTES_PER_CHARACTER); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_check_constraints(void) { /************************************** * * w r i t e _ c h e c k _ c o n s t r a i n t s * ************************************** * * Functional description * write a record in the burp file for * each check constraint. * **************************************/ isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$CHECK_CONSTRAINTS PUT (rec_chk_constraint); PUT_TEXT (att_chk_constraint_name, X.RDB$CONSTRAINT_NAME); if (!(X.RDB$TRIGGER_NAME.NULL)) PUT_TEXT (att_chk_trigger_name, X.RDB$TRIGGER_NAME); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_collations(void) { /************************************** * * w r i t e _ c o l l a t i o n s * ************************************** * * Functional description * write a record in the burp file for * each user defined collation * **************************************/ isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$COLLATIONS WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1 PUT (rec_collation); PUT_TEXT (att_coll_name, X.RDB$COLLATION_NAME); PUT_NUMERIC (att_coll_id, X.RDB$COLLATION_ID); PUT_NUMERIC (att_coll_cs_id, X.RDB$CHARACTER_SET_ID); PUT_NUMERIC (att_coll_attr, X.RDB$COLLATION_ATTRIBUTES); if (X.RDB$SYSTEM_FLAG) PUT_NUMERIC (att_coll_sysflag, X.RDB$SYSTEM_FLAG); if (!X.RDB$DESCRIPTION.NULL) put_source_blob (att_coll_description, att_coll_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); if (!X.RDB$FUNCTION_NAME.NULL) PUT_TEXT (att_coll_funct, X.RDB$FUNCTION_NAME); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_database( TEXT * dbb_file) { /************************************** * * w r i t e _ d a t a b a s e * ************************************** * * Functional description * write a physical database record and a * logical database record in the burp file for * the database itself. * **************************************/ STATUS status_vector[ISC_STATUS_LENGTH]; USHORT page_size, forced_writes, no_reserve, length, SQL_dialect, db_read_only; ULONG sweep_interval, page_buffers; SCHAR buffer[256], *d, item; isc_req_handle req_handle1 = NULL, req_handle2 = NULL, req_handle3 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; PUT(rec_physical_db); page_size = 0; if (isc_database_info(status_vector, GDS_REF(tdgbl->db_handle), sizeof(db_info_items), (SCHAR *) db_info_items, sizeof(buffer), buffer)) { BURP_error_redirect(status_vector, 31, NULL, NULL); /* msg 31 isc_database_info failed */ } for (d = buffer; *d != isc_info_end; d += length) { item = *d++; length = (USHORT) isc_vax_integer(d, 2); d += 2; switch (item) { case isc_info_end: break; case isc_info_page_size: page_size = (USHORT) isc_vax_integer(d, length); PUT_NUMERIC(att_page_size, page_size); break; case isc_info_sweep_interval: sweep_interval = isc_vax_integer(d, length); PUT_NUMERIC(att_sweep_interval, sweep_interval); break; case isc_info_forced_writes: forced_writes = (USHORT) isc_vax_integer(d, length); PUT_NUMERIC(att_forced_writes, forced_writes); break; case isc_info_no_reserve: if (no_reserve = (USHORT) isc_vax_integer(d, length)) PUT_NUMERIC(att_no_reserve, no_reserve); break; case isc_info_set_page_buffers: if (page_buffers = isc_vax_integer(d, length)) PUT_NUMERIC(att_page_buffers, page_buffers); break; case isc_info_error: /* old server does not understand new isc_info */ break; /* parametere and returns isc_info_error. skip it */ case isc_info_db_sql_dialect: SQL_dialect = (USHORT) isc_vax_integer(d, length); PUT_NUMERIC(att_SQL_dialect, SQL_dialect); break; case isc_info_db_read_only: if (db_read_only = (USHORT) isc_vax_integer(d, length)) PUT_NUMERIC(att_db_read_only, db_read_only); break; default: BURP_error_redirect(status_vector, 31, NULL, NULL); /* msg 31 isc_database_info failed */ break; } } PUT_ASCIZ(att_file_name, dbb_file); BURP_verbose(77, dbb_file, (void *) page_size, NULL, NULL, NULL); /* msg 77 database %s has a page size of %ld bytes. */ PUT(att_end); PUT(rec_database); /* if we have all capabilities, use the first request to get the most performance out of the latest engine; if we don't have one of the capabilities we must use the second set of requests--this requires more code but it is well worth it for the performance benefits, especially remotely--deej */ if ((tdgbl->BCK_capabilities & BCK_security) && (tdgbl->BCK_capabilities & BCK_db_description) && (tdgbl->BCK_capabilities & BCK_ods8)) { FOR (REQUEST_HANDLE req_handle1) D IN RDB$DATABASE if (!D.RDB$SECURITY_CLASS.NULL) PUT_TEXT (att_database_security_class, D.RDB$SECURITY_CLASS); put_source_blob (att_database_description2, att_database_description, (ISC_QUAD *)&D.RDB$DESCRIPTION); if (!D.RDB$CHARACTER_SET_NAME.NULL) PUT_TEXT (att_database_dfl_charset, D.RDB$CHARACTER_SET_NAME); END_FOR; ON_ERROR general_on_error (); END_ERROR; } else { if (tdgbl->BCK_capabilities & BCK_security) { FOR (REQUEST_HANDLE req_handle1) D IN RDB$DATABASE if (!D.RDB$SECURITY_CLASS.NULL) PUT_TEXT (att_database_security_class, D.RDB$SECURITY_CLASS); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (tdgbl->BCK_capabilities & BCK_db_description) { FOR (REQUEST_HANDLE req_handle2) D IN RDB$DATABASE put_source_blob (att_database_description2, att_database_description, (ISC_QUAD *)&D.RDB$DESCRIPTION); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (tdgbl->BCK_capabilities & BCK_ods8) { FOR (REQUEST_HANDLE req_handle3) D IN RDB$DATABASE if (!D.RDB$CHARACTER_SET_NAME.NULL) PUT_TEXT (att_database_dfl_charset, D.RDB$CHARACTER_SET_NAME); END_FOR; ON_ERROR general_on_error (); END_ERROR; } } if (req_handle1) isc_release_request(req_status, &req_handle1); if (req_handle2) isc_release_request(req_status, &req_handle2); if (req_handle3) isc_release_request(req_status, &req_handle3); PUT(att_end); } static void write_exceptions(void) { /************************************** * * w r i t e _ e x c e p t i o n s * ************************************** * * Functional description * write a record in the burp file for * each exception. * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$EXCEPTIONS PUT (rec_exception); l = PUT_TEXT (att_exception_name, X.RDB$EXCEPTION_NAME); MISC_terminate ((UCHAR*) X.RDB$EXCEPTION_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (198, temp, NULL, NULL, NULL, NULL); /* msg 198 writing exception %s */ PUT_MESSAGE (att_exception_msg, X.RDB$MESSAGE); put_source_blob (att_exception_description2, att_procedure_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_field_dimensions(void) { /************************************** * * w r i t e _ f i e l d _ d i m e n s i o n s * ************************************** * * Functional description * write a record in the burp file for * each array field dimension. * **************************************/ isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$FIELD_DIMENSIONS PUT (rec_field_dimensions); PUT_TEXT (att_field_name, X.RDB$FIELD_NAME); PUT_NUMERIC (att_field_dimensions, X.RDB$DIMENSION); PUT_NUMERIC (att_field_range_low, X.RDB$LOWER_BOUND); PUT_NUMERIC (att_field_range_high, X.RDB$UPPER_BOUND); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_filters(void) { /************************************** * * w r i t e _ f i l t e r s * ************************************** * * Functional description * write a record in the burp file for * each filter. * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$FILTERS PUT (rec_filter); l = PUT_TEXT (att_filter_name, X.RDB$FUNCTION_NAME); MISC_terminate ((UCHAR*) X.RDB$FUNCTION_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (145, temp, NULL, NULL, NULL, NULL); /* msg 145 writing filter %s */ put_source_blob (att_filter_description2, att_filter_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT_TEXT (att_filter_module_name, X.RDB$MODULE_NAME); PUT_TEXT (att_filter_entrypoint, X.RDB$ENTRYPOINT); PUT_NUMERIC (att_filter_input_sub_type, X.RDB$INPUT_SUB_TYPE); PUT_NUMERIC (att_filter_output_sub_type, X.RDB$OUTPUT_SUB_TYPE); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_functions(void) { /************************************** * * w r i t e _ f u n c t i o n s * ************************************** * * Functional description * write a record in the burp file for * each function. * **************************************/ SSHORT l; GDS_NAME func; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$FUNCTIONS PUT (rec_function); l = PUT_TEXT (att_function_name, X.RDB$FUNCTION_NAME); MISC_terminate ((UCHAR*) X.RDB$FUNCTION_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (147, temp, NULL, NULL, NULL, NULL); /* msg 147 writing function %.*s */ put_source_blob (att_function_description2, att_function_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT_TEXT (att_function_module_name, X.RDB$MODULE_NAME); PUT_TEXT (att_function_entrypoint, X.RDB$ENTRYPOINT); PUT_NUMERIC (att_function_return_arg, X.RDB$RETURN_ARGUMENT); PUT_NUMERIC (att_function_type, X.RDB$FUNCTION_TYPE); PUT_TEXT (att_function_query_name, X.RDB$QUERY_NAME); PUT (att_end); COPY (X.RDB$FUNCTION_NAME, func); write_function_args (func); PUT (rec_function_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_function_args( GDS_NAME funcptr) { /************************************** * * w r i t e _ f u n c t i o n _ a r g s * ************************************** * * Functional description * write all arguments for a function. * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* if we have all capabilities, use the first request to get the most performance out of the latest engine; if we don't have one of the capabilities we must use the second set of requests--this requires more code but it is well worth it for the performance benefits, especially remotely--deej */ if (tdgbl->BCK_capabilities & BCK_ods10) { FOR (REQUEST_HANDLE tdgbl->handles_write_function_args_req_handle1) X IN RDB$FUNCTION_ARGUMENTS WITH X.RDB$FUNCTION_NAME EQ funcptr PUT (rec_function_arg); l = PUT_TEXT (att_functionarg_name, X.RDB$FUNCTION_NAME); MISC_terminate ((UCHAR*) X.RDB$FUNCTION_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (141, temp, NULL, NULL, NULL, NULL); /* msg 141 writing argument for function %s */ PUT_NUMERIC (att_functionarg_position, X.RDB$ARGUMENT_POSITION); PUT_NUMERIC (att_functionarg_mechanism, X.RDB$MECHANISM); PUT_NUMERIC (att_functionarg_field_type, X.RDB$FIELD_TYPE); PUT_NUMERIC (att_functionarg_field_scale, X.RDB$FIELD_SCALE); PUT_NUMERIC (att_functionarg_field_length, X.RDB$FIELD_LENGTH); PUT_NUMERIC (att_functionarg_field_sub_type, X.RDB$FIELD_SUB_TYPE); if (!(X.RDB$CHARACTER_SET_ID.NULL)) PUT_NUMERIC (att_functionarg_character_set, X.RDB$CHARACTER_SET_ID); if (!(X.RDB$FIELD_PRECISION.NULL)) PUT_NUMERIC (att_functionarg_field_precision, X.RDB$FIELD_PRECISION); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } else { FOR (REQUEST_HANDLE tdgbl->handles_write_function_args_req_handle1) X IN RDB$FUNCTION_ARGUMENTS WITH X.RDB$FUNCTION_NAME EQ funcptr PUT (rec_function_arg); l = PUT_TEXT (att_functionarg_name, X.RDB$FUNCTION_NAME); MISC_terminate ((UCHAR*) X.RDB$FUNCTION_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (141, temp, NULL, NULL, NULL, NULL); /* msg 141 writing argument for function %s */ PUT_NUMERIC (att_functionarg_position, X.RDB$ARGUMENT_POSITION); PUT_NUMERIC (att_functionarg_mechanism, X.RDB$MECHANISM); PUT_NUMERIC (att_functionarg_field_type, X.RDB$FIELD_TYPE); PUT_NUMERIC (att_functionarg_field_scale, X.RDB$FIELD_SCALE); PUT_NUMERIC (att_functionarg_field_length, X.RDB$FIELD_LENGTH); PUT_NUMERIC (att_functionarg_field_sub_type, X.RDB$FIELD_SUB_TYPE); if (tdgbl->BCK_capabilities & BCK_ods8) { FOR (REQUEST_HANDLE tdgbl->handles_write_function_args_req_handle2) X2 IN RDB$FUNCTION_ARGUMENTS WITH X2.RDB$FUNCTION_NAME EQ funcptr AND X2.RDB$ARGUMENT_POSITION = X.RDB$ARGUMENT_POSITION; if (!(X2.RDB$CHARACTER_SET_ID.NULL)) PUT_NUMERIC (att_functionarg_character_set, X2.RDB$CHARACTER_SET_ID); /* Note that BCK_ods10 canNOT be set if we're in this ``else'' branch. Hence there is no need to test that bit and store the RDB$FIELD_PRECISION. */ END_FOR; ON_ERROR general_on_error (); END_ERROR; } PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } } static void write_generators(void) { /************************************** * * w r i t e _ g e n e r a t o r s * ************************************** * * Functional description * Write any defined generators. * **************************************/ SINT64 value; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; SSHORT l; TEXT temp[GDS_NAME_LEN]; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$GENERATORS WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1 PUT (rec_generator); l = PUT_TEXT (att_gen_generator, X.RDB$GENERATOR_NAME); value = get_gen_id (X.RDB$GENERATOR_NAME, l); PUT_INT64 (att_gen_value_int64, value); PUT (att_end); MISC_terminate ( (UCHAR*) X.RDB$GENERATOR_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (165, temp, (void*) value, NULL, NULL, NULL); /* msg 165 writing generator %s value %ld */ END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_global_fields(void) { /************************************** * * w r i t e _ g l o b a l _ f i e l d s * ************************************** * * Functional description * write a record in the burp file for * each global field. * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL, req_handle2 = NULL, req_handle3 = NULL, req_handle4 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* if we have all capabilities, use the first request to get the most performance out of the latest engine; if we don't have one of the capabilities we must use the second set of requests--this requires more code but it is well worth it for the performance benefits, especially remotely--deej */ if ((tdgbl->BCK_capabilities & BCK_attributes_v3) && (tdgbl->BCK_capabilities & BCK_ods8) && (tdgbl->BCK_capabilities & BCK_ods10)) { FOR (REQUEST_HANDLE req_handle1) X IN RDB$FIELDS WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING PUT (rec_global_field); l = PUT_TEXT (att_field_name, X.RDB$FIELD_NAME); MISC_terminate ((UCHAR*) X.RDB$FIELD_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (149, temp, NULL, NULL, NULL, NULL); /* msg 149 writing global field %.*s */ if (X.RDB$QUERY_NAME [0] != ' ') PUT_TEXT (att_field_query_name, X.RDB$QUERY_NAME); if (X.RDB$EDIT_STRING [0] != ' ') PUT_TEXT (att_field_edit_string, X.RDB$EDIT_STRING); put_source_blob (att_field_query_header, att_field_query_header, (ISC_QUAD *)&X.RDB$QUERY_HEADER); PUT_NUMERIC (att_field_type, X.RDB$FIELD_TYPE); PUT_NUMERIC (att_field_length, X.RDB$FIELD_LENGTH); PUT_NUMERIC (att_field_sub_type, X.RDB$FIELD_SUB_TYPE); PUT_NUMERIC (att_field_scale, X.RDB$FIELD_SCALE); put_blr_blob (att_field_missing_value, (ISC_QUAD *)&X.RDB$MISSING_VALUE); put_blr_blob (att_field_default_value, (ISC_QUAD *)&X.RDB$DEFAULT_VALUE); put_blr_blob (att_field_validation_blr, (ISC_QUAD *)&X.RDB$VALIDATION_BLR); put_source_blob (att_field_validation_source2, att_field_validation_source, (ISC_QUAD *)&X.RDB$VALIDATION_SOURCE); put_blr_blob (att_field_computed_blr, &X.RDB$COMPUTED_BLR); put_source_blob (att_field_computed_source2, att_field_computed_source, (ISC_QUAD *)&X.RDB$COMPUTED_SOURCE); if (X.RDB$SEGMENT_LENGTH) PUT_NUMERIC (att_field_segment_length, X.RDB$SEGMENT_LENGTH); if (X.RDB$SYSTEM_FLAG) PUT_NUMERIC (att_field_system_flag, X.RDB$SYSTEM_FLAG); put_source_blob (att_field_description2, att_field_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); if (X.RDB$EXTERNAL_LENGTH) PUT_NUMERIC (att_field_external_length, X.RDB$EXTERNAL_LENGTH); if (X.RDB$EXTERNAL_TYPE) PUT_NUMERIC (att_field_external_type, X.RDB$EXTERNAL_TYPE); if (X.RDB$EXTERNAL_SCALE) PUT_NUMERIC (att_field_external_scale, X.RDB$EXTERNAL_SCALE); if (X.RDB$DIMENSIONS) PUT_NUMERIC (att_field_dimensions, X.RDB$DIMENSIONS); if (!(X.RDB$NULL_FLAG.NULL)) PUT_NUMERIC (att_field_null_flag, X.RDB$NULL_FLAG); if (!(X.RDB$CHARACTER_LENGTH.NULL)) PUT_NUMERIC (att_field_character_length, X.RDB$CHARACTER_LENGTH); if (!(X.RDB$DEFAULT_SOURCE.NULL)) put_source_blob (att_field_default_source, att_field_default_source, (ISC_QUAD *)&X.RDB$DEFAULT_SOURCE); if (!(X.RDB$MISSING_SOURCE.NULL)) put_source_blob (att_field_missing_source, att_field_missing_source, (ISC_QUAD *)&X.RDB$MISSING_SOURCE); if (!(X.RDB$CHARACTER_SET_ID.NULL)) PUT_NUMERIC (att_field_character_set, X.RDB$CHARACTER_SET_ID); if (!(X.RDB$COLLATION_ID.NULL)) PUT_NUMERIC (att_field_collation_id, X.RDB$COLLATION_ID); if (!(X.RDB$FIELD_PRECISION.NULL)) PUT_NUMERIC (att_field_precision, X.RDB$FIELD_PRECISION); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } else { FOR (REQUEST_HANDLE req_handle1) X IN RDB$FIELDS WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING PUT (rec_global_field); l = PUT_TEXT (att_field_name, X.RDB$FIELD_NAME); MISC_terminate ((UCHAR*) X.RDB$FIELD_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (149, temp, NULL, NULL, NULL, NULL); /* msg 149 writing global field %.*s */ if (X.RDB$QUERY_NAME [0] != ' ') PUT_TEXT (att_field_query_name, X.RDB$QUERY_NAME); if (X.RDB$EDIT_STRING [0] != ' ') PUT_TEXT (att_field_edit_string, X.RDB$EDIT_STRING); put_source_blob (att_field_query_header, att_field_query_header, (ISC_QUAD *)&X.RDB$QUERY_HEADER); PUT_NUMERIC (att_field_type, X.RDB$FIELD_TYPE); PUT_NUMERIC (att_field_length, X.RDB$FIELD_LENGTH); PUT_NUMERIC (att_field_sub_type, X.RDB$FIELD_SUB_TYPE); PUT_NUMERIC (att_field_scale, X.RDB$FIELD_SCALE); put_blr_blob (att_field_missing_value, (ISC_QUAD *)&X.RDB$MISSING_VALUE); put_blr_blob (att_field_default_value, (ISC_QUAD *)&X.RDB$DEFAULT_VALUE); put_blr_blob (att_field_validation_blr, (ISC_QUAD *)&X.RDB$VALIDATION_BLR); put_source_blob (att_field_validation_source2, att_field_validation_source, (ISC_QUAD *)&X.RDB$VALIDATION_SOURCE); put_blr_blob (att_field_computed_blr, (ISC_QUAD *)&X.RDB$COMPUTED_BLR); put_source_blob (att_field_computed_source2, att_field_computed_source, (ISC_QUAD *)&X.RDB$COMPUTED_SOURCE); if (X.RDB$SEGMENT_LENGTH) PUT_NUMERIC (att_field_segment_length, X.RDB$SEGMENT_LENGTH); if (X.RDB$SYSTEM_FLAG) PUT_NUMERIC (att_field_system_flag, X.RDB$SYSTEM_FLAG); put_source_blob (att_field_description2, att_field_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); if (tdgbl->BCK_capabilities & BCK_attributes_v3) { FOR (REQUEST_HANDLE req_handle2) F IN RDB$FIELDS WITH F.RDB$FIELD_NAME = X.RDB$FIELD_NAME if (F.RDB$EXTERNAL_LENGTH) PUT_NUMERIC (att_field_external_length, F.RDB$EXTERNAL_LENGTH); if (F.RDB$EXTERNAL_TYPE) PUT_NUMERIC (att_field_external_type, F.RDB$EXTERNAL_TYPE); if (F.RDB$EXTERNAL_SCALE) PUT_NUMERIC (att_field_external_scale, F.RDB$EXTERNAL_SCALE); if (F.RDB$DIMENSIONS) PUT_NUMERIC (att_field_dimensions, F.RDB$DIMENSIONS); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (tdgbl->BCK_capabilities & BCK_ods8) { FOR (REQUEST_HANDLE req_handle3) F IN RDB$FIELDS WITH F.RDB$FIELD_NAME = X.RDB$FIELD_NAME if (!(F.RDB$NULL_FLAG.NULL)) PUT_NUMERIC (att_field_null_flag, F.RDB$NULL_FLAG); if (!(F.RDB$CHARACTER_LENGTH.NULL)) PUT_NUMERIC (att_field_character_length, F.RDB$CHARACTER_LENGTH); if (!(F.RDB$DEFAULT_SOURCE.NULL)) put_source_blob (att_field_default_source, att_field_default_source, (ISC_QUAD *)&F.RDB$DEFAULT_SOURCE); if (!(F.RDB$MISSING_SOURCE.NULL)) put_source_blob (att_field_missing_source, att_field_missing_source, (ISC_QUAD *)&F.RDB$MISSING_SOURCE); if (!(F.RDB$CHARACTER_SET_ID.NULL)) PUT_NUMERIC (att_field_character_set, F.RDB$CHARACTER_SET_ID); if (!(F.RDB$COLLATION_ID.NULL)) PUT_NUMERIC (att_field_collation_id, F.RDB$COLLATION_ID); if (tdgbl->BCK_capabilities & BCK_ods10) { FOR (REQUEST_HANDLE req_handle4) K IN RDB$FIELDS WITH K.RDB$FIELD_NAME = X.RDB$FIELD_NAME if (!(K.RDB$FIELD_PRECISION.NULL)) PUT_NUMERIC (att_field_precision, K.RDB$FIELD_PRECISION); END_FOR; ON_ERROR general_on_error (); END_ERROR; } END_FOR; ON_ERROR general_on_error (); END_ERROR; } PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (req_handle1) isc_release_request(req_status, &req_handle1); if (req_handle2) isc_release_request(req_status, &req_handle2); if (req_handle3) isc_release_request(req_status, &req_handle3); if (req_handle4) isc_release_request(req_status, &req_handle4); } static void write_procedures(void) { /************************************** * * w r i t e _ p r o c e d u r e s * ************************************** * * Functional description * write a record in the burp file for * each stored procedure. * **************************************/ SSHORT l; GDS_NAME proc; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$PROCEDURES PUT (rec_procedure); l = PUT_TEXT (att_procedure_name, X.RDB$PROCEDURE_NAME); MISC_terminate ((UCHAR*) X.RDB$PROCEDURE_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (193, temp, NULL, NULL, NULL, NULL); /* msg 193 writing stored procedure %.*s */ PUT_NUMERIC (att_procedure_inputs, X.RDB$PROCEDURE_INPUTS); PUT_NUMERIC (att_procedure_outputs, X.RDB$PROCEDURE_OUTPUTS); put_source_blob (att_procedure_description2, att_procedure_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); put_source_blob (att_procedure_source2, att_procedure_source, (ISC_QUAD *)&X.RDB$PROCEDURE_SOURCE); put_blr_blob (att_procedure_blr, (ISC_QUAD *)&X.RDB$PROCEDURE_BLR); if (!X.RDB$SECURITY_CLASS.NULL) PUT_TEXT (att_procedure_security_class, X.RDB$SECURITY_CLASS); if (!X.RDB$SECURITY_CLASS.NULL) PUT_TEXT (att_procedure_owner_name, X.RDB$OWNER_NAME); PUT (att_end); COPY(X.RDB$PROCEDURE_NAME, proc); write_procedure_prms (proc); PUT (rec_procedure_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_procedure_prms( GDS_NAME procptr) { /************************************** * * w r i t e _ p r o c e d u r e _ p r m s * ************************************** * * Functional description * write all parameters of a stored procedure. * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE tdgbl->handles_write_procedure_prms_req_handle1) X IN RDB$PROCEDURE_PARAMETERS WITH X.RDB$PROCEDURE_NAME EQ procptr PUT (rec_procedure_prm); l = PUT_TEXT (att_procedureprm_name, X.RDB$PARAMETER_NAME); MISC_terminate ((UCHAR*) X.RDB$PARAMETER_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (194, temp, NULL, NULL, NULL, NULL); /* msg 194 writing parameter %s for stored procedure */ PUT_NUMERIC (att_procedureprm_number, X.RDB$PARAMETER_NUMBER); PUT_NUMERIC (att_procedureprm_type, X.RDB$PARAMETER_type); PUT_TEXT (att_procedureprm_field_source, X.RDB$FIELD_SOURCE); put_source_blob (att_procedureprm_description2, att_procedureprm_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } static void write_ref_constraints(void) { /************************************** * * w r i t e _ r e f _ c o n s t r a i n t s * ************************************** * * Functional description * write a record in the burp file for * each referential constraint. * **************************************/ isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$REF_CONSTRAINTS PUT (rec_ref_constraint); 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 (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_rel_constraints(void) { /************************************** * * w r i t e _ r e l _ c o n s t r a i n t s * ************************************** * * Functional description * write a record in the burp file for * each relation constraint. * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$RELATION_CONSTRAINTS PUT (rec_rel_constraint); l = PUT_TEXT (att_rel_constraint_name, X.RDB$CONSTRAINT_NAME); MISC_terminate ((UCHAR*) X.RDB$CONSTRAINT_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (207, temp, NULL, NULL, NULL, NULL); /* msg 207 writing constraint %s */ PUT_MESSAGE (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); if (!(X.RDB$INDEX_NAME.NULL)) PUT_TEXT (att_rel_constraint_index, X.RDB$INDEX_NAME); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_relations(void) { /************************************** * * w r i t e _ r e l a t i o n s * ************************************** * * Functional description * write a record in the burp file for * each relation. * **************************************/ SSHORT l, flags; REL relation; TEXT temp[32]; isc_req_handle req_handle1 = NULL, req_handle2 = NULL, req_handle3 = NULL, req_handle4 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* if we have all capabilities, use the first request to get the most performance out of the latest engine; if we don't have one of the capabilities we must use the second set of requests--this requires more code but it is well worth it for the performance benefits, especially remotely--deej */ if ((tdgbl->BCK_capabilities & BCK_ods8) && (tdgbl->BCK_capabilities & BCK_security) && (tdgbl->BCK_capabilities & BCK_attributes_v3)) { FOR (REQUEST_HANDLE req_handle1) X IN RDB$RELATIONS WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING flags = 0; PUT (rec_relation); l = PUT_TEXT (att_relation_name, X.RDB$RELATION_NAME); MISC_terminate ((UCHAR*) X.RDB$RELATION_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (153, temp, NULL, NULL, NULL, NULL); /* msg 153 writing relation %.*s */ /* RDB$VIEW_BLR must be the first blob field in the backup file. * RESTORE.E makes this assumption in get_relation(). */ if (put_blr_blob (att_relation_view_blr, (ISC_QUAD *)&X.RDB$VIEW_BLR)) flags |= REL_view; if (X.RDB$SYSTEM_FLAG) PUT_NUMERIC (att_relation_system_flag, X.RDB$SYSTEM_FLAG); if (!(X.RDB$FLAGS.NULL)) PUT_NUMERIC (att_relation_flags, X.RDB$FLAGS); if (!X.RDB$SECURITY_CLASS.NULL) PUT_TEXT (att_relation_security_class, X.RDB$SECURITY_CLASS); put_source_blob (att_relation_description2, att_relation_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); put_source_blob (att_relation_view_source2, att_relation_view_source, (ISC_QUAD *)&X.RDB$VIEW_SOURCE); put_source_blob (att_relation_ext_description2, att_relation_ext_description, (ISC_QUAD *)&X.RDB$EXTERNAL_DESCRIPTION); PUT_TEXT (att_relation_owner_name, X.RDB$OWNER_NAME); if (!X.RDB$EXTERNAL_FILE.NULL) if (!tdgbl->gbl_sw_convert_ext_tables) { PUT_TEXT(att_relation_ext_file_name, X.RDB$EXTERNAL_FILE); flags |= REL_external; } PUT (att_end); relation = (REL) BURP_ALLOC_ZERO (sizeof (struct rel)); relation->rel_next = tdgbl->relations; tdgbl->relations = relation; relation->rel_id = X.RDB$RELATION_ID; relation->rel_name_length = COPY(X.RDB$RELATION_NAME, relation->rel_name); relation->rel_flags |= flags; put_relation (relation); END_FOR; ON_ERROR general_on_error (); END_ERROR; } else { FOR (REQUEST_HANDLE req_handle1) X IN RDB$RELATIONS WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING flags = 0; PUT (rec_relation); l = PUT_TEXT(att_relation_name, X.RDB$RELATION_NAME); MISC_terminate ((UCHAR*) X.RDB$RELATION_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (153, temp, NULL, NULL, NULL, NULL); /* msg 153 writing relation %.*s */ /* RDB$VIEW_BLR must be the first blob field in the backup file. * RESTORE.E makes this assumption in get_relation(). */ if (put_blr_blob (att_relation_view_blr, (ISC_QUAD *)&X.RDB$VIEW_BLR)) flags |= REL_view; if (X.RDB$SYSTEM_FLAG) PUT_NUMERIC (att_relation_system_flag, X.RDB$SYSTEM_FLAG); if (tdgbl->BCK_capabilities & BCK_ods8) { FOR (REQUEST_HANDLE req_handle2) R IN RDB$RELATIONS WITH R.RDB$RELATION_NAME = X.RDB$RELATION_NAME if (!(R.RDB$FLAGS.NULL)) PUT_NUMERIC (att_relation_flags, R.RDB$FLAGS); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (tdgbl->BCK_capabilities & BCK_security) { FOR (REQUEST_HANDLE req_handle3) R IN RDB$RELATIONS WITH R.RDB$RELATION_NAME = X.RDB$RELATION_NAME if (!R.RDB$SECURITY_CLASS.NULL) PUT_TEXT(att_relation_security_class, R.RDB$SECURITY_CLASS); END_FOR; ON_ERROR general_on_error (); END_ERROR; } put_source_blob (att_relation_description2, att_relation_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); put_source_blob (att_relation_view_source2, att_relation_view_source, (ISC_QUAD *)&X.RDB$VIEW_SOURCE); if (tdgbl->BCK_capabilities & BCK_attributes_v3) { FOR (REQUEST_HANDLE req_handle4) R IN RDB$RELATIONS WITH R.RDB$RELATION_NAME = X.RDB$RELATION_NAME put_source_blob (att_relation_ext_description2, att_relation_ext_description, (ISC_QUAD *)&R.RDB$EXTERNAL_DESCRIPTION); PUT_TEXT(att_relation_owner_name, R.RDB$OWNER_NAME); if (!R.RDB$EXTERNAL_FILE.NULL) { if (!tdgbl->gbl_sw_convert_ext_tables) { PUT_TEXT(att_relation_ext_file_name, R.RDB$EXTERNAL_FILE); flags |= REL_external; } } END_FOR; ON_ERROR general_on_error (); END_ERROR; } PUT (att_end); relation = (REL) BURP_ALLOC_ZERO (sizeof (struct rel)); relation->rel_next = tdgbl->relations; tdgbl->relations = relation; relation->rel_id = X.RDB$RELATION_ID; relation->rel_name_length = COPY(X.RDB$RELATION_NAME, relation->rel_name); relation->rel_flags |= flags; put_relation (relation); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (req_handle1) isc_release_request(req_status, &req_handle1); if (req_handle2) isc_release_request(req_status, &req_handle2); if (req_handle3) isc_release_request(req_status, &req_handle3); if (req_handle4) isc_release_request(req_status, &req_handle4); } static void write_shadow_files(void) { /************************************** * * w r i t e _ s h a d o w _ f i l e s * ************************************** * * Functional description * Write out files to use as shadows. * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$FILES WITH X.RDB$SHADOW_NUMBER NOT MISSING AND X.RDB$SHADOW_NUMBER NE 0 PUT (rec_files); l = PUT_TEXT (att_file_filename, X.RDB$FILE_NAME); MISC_terminate ((UCHAR*) X.RDB$FILE_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (163, temp, NULL, NULL, NULL, NULL); /* msg 163 writing shadow file %s */ PUT_NUMERIC (att_file_sequence, X.RDB$FILE_SEQUENCE); PUT_NUMERIC (att_file_start, X.RDB$FILE_START); PUT_NUMERIC (att_file_length, X.RDB$FILE_LENGTH); PUT_NUMERIC (att_file_flags, X.RDB$FILE_FLAGS); PUT_NUMERIC (att_shadow_number, X.RDB$SHADOW_NUMBER); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_sql_roles(void) { /************************************** * * w r i t e _ s q l _ r o l e s * ************************************** * * Functional description * write a record in the burp file for * each SQL roles. * **************************************/ isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; TEXT temp[GDS_NAME_LEN]; SSHORT l; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$ROLES PUT (rec_sql_roles); l = PUT_TEXT(att_role_name, X.RDB$ROLE_NAME); PUT_TEXT (att_role_owner_name, X.RDB$OWNER_NAME); PUT (att_end); MISC_terminate ((UCHAR*) X.RDB$ROLE_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (249, temp, NULL, NULL, NULL, NULL); /* msg 249 writing SQL role: %s */ END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_triggers(void) { /************************************** * * w r i t e _ t r i g g e r s * ************************************** * * Functional description * write the triggers in rdb$triggers * **************************************/ SSHORT l; TEXT temp[GDS_NAME_LEN]; isc_req_handle req_handle1 = NULL, req_handle2 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; /* if we have all capabilities, use the first request to get the most performance out of the latest engine; if we don't have one of the capabilities we must use the second set of requests--this requires more code but it is well worth it for the performance benefits, especially remotely--deej */ if (tdgbl->BCK_capabilities & BCK_ods8) { FOR (REQUEST_HANDLE req_handle1) X IN RDB$TRIGGERS WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING PUT (rec_trigger); l = PUT_TEXT (att_trig_name, X.RDB$TRIGGER_NAME); MISC_terminate ((UCHAR*) X.RDB$TRIGGER_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (156, temp, NULL, NULL, NULL, NULL); /* msg 156 writing trigger %s */ PUT_TEXT (att_trig_relation_name, X.RDB$RELATION_NAME); PUT_NUMERIC (att_trig_sequence, X.RDB$TRIGGER_SEQUENCE); PUT_NUMERIC (att_trig_type, X.RDB$TRIGGER_TYPE); put_blr_blob (att_trig_blr, (ISC_QUAD *)&X.RDB$TRIGGER_BLR); put_source_blob (att_trig_source2, att_trig_source, (ISC_QUAD *)&X.RDB$TRIGGER_SOURCE); put_source_blob (att_trig_description2, att_trig_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT_NUMERIC (att_trig_system_flag, X.RDB$SYSTEM_FLAG); PUT_NUMERIC (att_trig_inactive, X.RDB$TRIGGER_INACTIVE); if (!(X.RDB$FLAGS.NULL)) PUT_NUMERIC (att_trig_flags, X.RDB$FLAGS); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } else { FOR (REQUEST_HANDLE req_handle1) X IN RDB$TRIGGERS WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING PUT (rec_trigger); l = PUT_TEXT (att_trig_name, X.RDB$TRIGGER_NAME); MISC_terminate ((UCHAR*) X.RDB$TRIGGER_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (156, temp, NULL, NULL, NULL, NULL); /* msg 156 writing trigger %s */ PUT_TEXT (att_trig_relation_name, X.RDB$RELATION_NAME); PUT_NUMERIC (att_trig_sequence, X.RDB$TRIGGER_SEQUENCE); PUT_NUMERIC (att_trig_type, X.RDB$TRIGGER_TYPE); put_blr_blob (att_trig_blr, (ISC_QUAD *)&X.RDB$TRIGGER_BLR); put_source_blob (att_trig_source2, att_trig_source, (ISC_QUAD *)&X.RDB$TRIGGER_SOURCE); put_source_blob (att_trig_description2, att_trig_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); PUT_NUMERIC (att_trig_system_flag, X.RDB$SYSTEM_FLAG); PUT_NUMERIC (att_trig_inactive, X.RDB$TRIGGER_INACTIVE); if (tdgbl->BCK_capabilities & BCK_ods8) { FOR (REQUEST_HANDLE req_handle2) Y IN RDB$TRIGGERS WITH X.RDB$TRIGGER_NAME = Y.RDB$TRIGGER_NAME if (!(Y.RDB$FLAGS.NULL)) PUT_NUMERIC (att_trig_flags, Y.RDB$FLAGS); END_FOR; ON_ERROR general_on_error (); END_ERROR; } PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (req_handle1) isc_release_request(req_status, &req_handle1); if (req_handle2) isc_release_request(req_status, &req_handle2); } static void write_trigger_messages(void) { /************************************** * * w r i t e _ t r i g g e r _ m e s s a g e s * ************************************** * * Functional description * write a record in the burp file for * each trigger message. * **************************************/ SSHORT l; TEXT temp[32]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) T IN RDB$TRIGGERS CROSS X IN RDB$TRIGGER_MESSAGES OVER RDB$TRIGGER_NAME WITH T.RDB$SYSTEM_FLAG NE 1 OR T.RDB$SYSTEM_FLAG MISSING; PUT (rec_trigger_message); l = PUT_TEXT (att_trigmsg_name, X.RDB$TRIGGER_NAME); MISC_terminate ((UCHAR*) X.RDB$TRIGGER_NAME, (UCHAR*) temp, l, sizeof (temp)); BURP_verbose (157, temp, NULL, NULL, NULL, NULL); /* 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 (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_types(void) { /************************************** * * w r i t e _ t y p e s * ************************************** * * Functional description * write a record in the burp file for * each type. * **************************************/ isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; FOR (REQUEST_HANDLE req_handle1) X IN RDB$TYPES WITH X.RDB$SYSTEM_FLAG NE 1 OR X.RDB$SYSTEM_FLAG MISSING PUT (rec_type); PUT_TEXT (att_type_name, X.RDB$TYPE_NAME); PUT_TEXT (att_type_field_name, X.RDB$FIELD_NAME); BURP_verbose (160, X.RDB$TYPE_NAME, X.RDB$FIELD_NAME, NULL, NULL, NULL); /* msg 160 writing type %s for field %s */ PUT_NUMERIC (att_type_type, X.RDB$TYPE); put_source_blob (att_type_description2, att_type_description, (ISC_QUAD *)&X.RDB$DESCRIPTION); if (X.RDB$SYSTEM_FLAG) PUT_NUMERIC (att_type_system_flag, X.RDB$SYSTEM_FLAG); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; if (req_handle1) isc_release_request(req_status, &req_handle1); } static void write_user_privileges(void) { /************************************** * * w r i t e _ u s e r _ p r i v i l e g e s * ************************************** * * Functional description * write a record in the burp file for * each user privilege. * **************************************/ SSHORT l; TEXT temp[32]; isc_req_handle req_handle1 = NULL; STATUS req_status[ISC_STATUS_LENGTH]; TGBL tdgbl; tdgbl = GET_THREAD_DATA; if (tdgbl->BCK_capabilities & BCK_ods8) { FOR (REQUEST_HANDLE req_handle1) X IN RDB$USER_PRIVILEGES PUT (rec_user_privilege); l = PUT_TEXT (att_priv_user, X.RDB$USER); MISC_terminate ((UCHAR*) X.RDB$USER, (UCHAR*) temp, l, sizeof(temp)); BURP_verbose (152, temp, NULL, NULL, NULL, NULL); /* msg 152 writing privilege for user %s */ PUT_TEXT (att_priv_grantor, X.RDB$GRANTOR); PUT_TEXT (att_priv_privilege, X.RDB$PRIVILEGE); PUT_NUMERIC (att_priv_grant_option, X.RDB$GRANT_OPTION); PUT_TEXT (att_priv_object_name, X.RDB$RELATION_NAME); if (!X.RDB$FIELD_NAME.NULL) PUT_TEXT (att_priv_field_name, X.RDB$FIELD_NAME); PUT_NUMERIC (att_priv_user_type, X.RDB$USER_TYPE); PUT_NUMERIC (att_priv_obj_type, X.RDB$OBJECT_TYPE); PUT (att_end); END_FOR ON_ERROR general_on_error (); END_ERROR; } else { FOR (REQUEST_HANDLE req_handle1) X IN RDB$USER_PRIVILEGES PUT (rec_user_privilege); l = PUT_TEXT (att_priv_user, X.RDB$USER); MISC_terminate ((UCHAR*) X.RDB$USER, (UCHAR*) temp, l, sizeof(temp)); BURP_verbose (152, temp, NULL, NULL, NULL, NULL); /* msg 152 writing privilege for user %s */ PUT_TEXT (att_priv_grantor, X.RDB$GRANTOR); PUT_TEXT (att_priv_privilege, X.RDB$PRIVILEGE); PUT_NUMERIC (att_priv_grant_option, X.RDB$GRANT_OPTION); PUT_TEXT (att_priv_object_name, X.RDB$RELATION_NAME); if (!X.RDB$FIELD_NAME.NULL) PUT_TEXT (att_priv_field_name, X.RDB$FIELD_NAME); PUT (att_end); END_FOR; ON_ERROR general_on_error (); END_ERROR; } if (req_handle1) isc_release_request(req_status, &req_handle1); }