8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 01:23:03 +01:00
firebird-mirror/src/burp/backup.epp

4141 lines
120 KiB
Plaintext
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* 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): ______________________________________.
2002-06-29 07:39:38 +02:00
*
2001-05-23 15:26:42 +02:00
* Toni Martir: Added verbose backup records as BACKUP_VERBOSE_INTERVAL
2002-06-29 07:39:38 +02:00
* 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.
* 2002.10.29 Mike Nordell: UINT64 backup message.
2003-08-21 13:02:33 +02:00
* 2003.08.17 Claudio Valderrama: Fix SF Bug #750659.
2001-05-23 15:26:42 +02:00
*/
2002-06-29 07:39:38 +02:00
2001-05-23 15:26:42 +02:00
/*
$Id: backup.epp,v 1.33 2003-08-27 10:20:07 aafemt Exp $
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/ib_stdio.h"
#include <memory.h>
#include <string.h>
#include "../burp/burp.h"
#include "../jrd/ods.h"
#include "../jrd/align.h"
#include "../jrd/gdsassert.h"
2001-12-24 03:51:06 +01:00
#include "../jrd/thd_proto.h"
2001-05-23 15:26:42 +02:00
#include "../burp/backu_proto.h"
#include "../burp/burp_proto.h"
#include "../burp/canon_proto.h"
#include "../burp/mvol_proto.h"
#include "../remote/protocol.h"
#ifdef DEBUG
#include "../gpre/prett_proto.h"
#endif
2001-05-23 15:26:42 +02:00
/* 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. */
2002-12-16 17:25:09 +01:00
DATABASE DB = STATIC FILENAME "yachts.lnk" RUNTIME * dbb_file;
#define DB tdgbl->db_handle
#define gds_trans tdgbl->tr_handle
2001-05-23 15:26:42 +02:00
#define isc_trans tdgbl->tr_handle
#define isc_status tdgbl->status
2001-05-23 15:26:42 +02:00
/*
#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))
2002-06-29 07:39:38 +02:00
#define COPY(source, target) copy ((source), (target), sizeof (target))
2001-05-23 15:26:42 +02:00
static void compress(UCHAR *, ULONG);
static int copy(TEXT *, TEXT *, ULONG);
static BURP_FLD get_fields(BURP_REL);
2002-06-29 07:39:38 +02:00
static SINT64 get_gen_id(TEXT *, SSHORT);
static void get_ranges(BURP_FLD);
static void put_array(BURP_FLD, BURP_REL, ISC_QUAD *);
2001-05-23 15:26:42 +02:00
static void put_asciz(SCHAR, TEXT *);
static void put_blob(BURP_FLD, ISC_QUAD *, ULONG);
2001-05-23 15:26:42 +02:00
static int put_blr_blob(SCHAR, ISC_QUAD *);
static void put_data(BURP_REL);
static void put_index(BURP_REL);
2001-05-23 15:26:42 +02:00
static int put_message(SCHAR, TEXT *, ULONG);
static void put_numeric(SCHAR, SLONG);
static void put_relation(BURP_REL);
2001-05-23 15:26:42 +02:00
static int put_source_blob(SCHAR, SCHAR, ISC_QUAD *);
static int put_text(SCHAR, TEXT *, SSHORT);
#ifdef NOT_USED_OR_REPLACED
2001-05-23 15:26:42 +02:00
static void put_trigger(enum trig_t, GDS__QUAD *, GDS__QUAD *, GDS_NAME);
#endif
2001-05-23 15:26:42 +02:00
static void set_capabilities(void);
2002-06-29 07:39:38 +02:00
static int symbol_length(TEXT *, ULONG);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
*/
typedef struct rfr_tab_t {
2003-02-13 10:19:08 +01:00
const TEXT *relation;
const TEXT *field;
2001-05-23 15:26:42 +02:00
int bit_mask;
} *RFR_TAB;
static const 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},
2001-05-23 15:26:42 +02:00
*/
{"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}
2001-05-23 15:26:42 +02:00
};
2003-02-13 10:19:08 +01:00
static const SCHAR blob_items[] =
2001-05-23 15:26:42 +02:00
{
isc_info_blob_max_segment,
isc_info_blob_num_segments
};
2003-02-13 10:19:08 +01:00
static const SCHAR blr_items[] =
2001-05-23 15:26:42 +02:00
{
isc_info_blob_max_segment,
isc_info_blob_total_length
};
2003-02-13 10:19:08 +01:00
static const SCHAR source_items[] =
2001-05-23 15:26:42 +02:00
{
isc_info_blob_max_segment,
isc_info_blob_total_length,
isc_info_blob_num_segments
};
2003-02-13 10:19:08 +01:00
static const SCHAR db_info_items[] =
2001-05-23 15:26:42 +02:00
{
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
};
2003-02-13 10:19:08 +01:00
static const SCHAR limbo_tpb[] =
2001-05-23 15:26:42 +02:00
{
isc_tpb_version1,
isc_tpb_ignore_limbo
};
2003-02-13 10:19:08 +01:00
static const SCHAR limbo_nau_tpb[] =
2001-05-23 15:26:42 +02:00
{
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.
*
**************************************/
BURP_REL relation;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
ULONG l;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
UINT64 cumul_count = 0;
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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 = (BURP_REL) NULL;
tdgbl->BCK_capabilities = 0;
2001-05-23 15:26:42 +02:00
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])
2001-05-23 15:26:42 +02:00
EXEC SQL SET TRANSACTION;
}
if (!isc_trans)
{
EXEC SQL SET TRANSACTION NAME isc_trans NO_AUTO_UNDO;
if (isc_status[1])
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
/* 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 */
2002-06-29 07:39:38 +02:00
for (relation = tdgbl->relations; relation; relation = relation->rel_next) {
2001-05-23 15:26:42 +02:00
PUT(rec_relation_data);
2002-06-29 07:39:38 +02:00
PUT_TEXT(att_relation_name, relation->rel_name);
2001-05-23 15:26:42 +02:00
PUT(att_end);
2002-06-29 07:39:38 +02:00
if (!(relation->rel_flags & REL_view) &&
!(relation->rel_flags & REL_external)) {
put_index(relation);
if (!tdgbl->gbl_sw_meta) {
2001-05-23 15:26:42 +02:00
put_data(relation);
2002-06-29 07:39:38 +02:00
}
2001-05-23 15:26:42 +02:00
}
2002-06-29 07:39:38 +02:00
2001-05-23 15:26:42 +02:00
PUT(rec_relation_end);
}
/* now for the new triggers in rdb$triggers */
2002-06-29 07:39:38 +02:00
if (tdgbl->BCK_capabilities & BCK_ffmptt) {
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
cumul_count = MVOL_fini_write(&tdgbl->io_cnt, &tdgbl->io_ptr);
if (cumul_count <= MAX_SLONG) {
SLONG tempcount = cumul_count;
BURP_verbose(176, (TEXT *) tempcount, NULL, NULL, NULL, NULL);
/* msg 176 closing file, committing, and finishing. %ld bytes written */
} else {
char psz[64];
ib_sprintf(psz, "%" QUADFORMAT "d", cumul_count);
BURP_verbose(283, psz, NULL, NULL, NULL, NULL);
/* msg 283 closing file, committing, and finishing. %s bytes written */
}
2001-05-23 15:26:42 +02:00
COMMIT;
ON_ERROR
general_on_error ();
END_ERROR;
if (isc_trans)
COMMIT isc_trans;
ON_ERROR
general_on_error ();
END_ERROR;
FINISH
2001-05-23 15:26:42 +02:00
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;
}
}
}
2002-06-29 07:39:38 +02:00
static int copy( TEXT * from, TEXT * to, ULONG size_len)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c o p y
*
**************************************
*
* Functional description
* Copy a blank or null terminated string into a null terminated
* string.
*
**************************************/
ULONG l = (ULONG) symbol_length (from, size_len);
2001-05-23 15:26:42 +02:00
MOVE_FAST(from, to, l);
*(to + l) = '\0';
2002-06-29 07:39:38 +02:00
return (int) l;
2001-05-23 15:26:42 +02:00
}
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 BURP_FLD get_fields( BURP_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ f i e l d s
*
**************************************
*
* Functional description
* Get fields for a relation. Test
* capabilities and get system specific
*
**************************************/
BURP_FLD field, fields;
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$RELATION_NAME EQ relation->rel_name
field = (BURP_FLD) BURP_ALLOC_ZERO(sizeof(burp_fld));
2001-05-23 15:26:42 +02:00
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;
2001-05-23 15:26:42 +02:00
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;
}
2001-05-23 15:26:42 +02:00
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;
}
2001-05-23 15:26:42 +02:00
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)
2002-06-29 07:39:38 +02:00
field->fld_flags |= FLD_update_missing;
2001-05-23 15:26:42 +02:00
else
2002-06-29 07:39:38 +02:00
field->fld_update_flag = X.RDB$UPDATE_FLAG;
2002-06-29 07:39:38 +02:00
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);
2001-05-23 15:26:42 +02:00
blob_id = &Y.RDB$COMPUTED_BLR;
2002-06-29 07:39:38 +02:00
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
field->fld_flags |= FLD_computed;
}
2001-05-23 15:26:42 +02:00
field->fld_system_flag = X.RDB$SYSTEM_FLAG;
2002-06-29 07:39:38 +02:00
COPY (X.RDB$SECURITY_CLASS, field->fld_security_class);
/* use the fld_flags to mark the field as an array and
2001-05-23 15:26:42 +02:00
to differentiate it from other blobs */
2002-06-29 07:39:38 +02:00
if (Y.RDB$DIMENSIONS) {
2001-05-23 15:26:42 +02:00
field->fld_flags |= FLD_array;
field->fld_dimensions = Y.RDB$DIMENSIONS;
2002-06-29 07:39:38 +02:00
if (field->fld_dimensions < 0) {
2003-04-10 08:32:58 +02:00
BURP_error_redirect ((ISC_STATUS*) NULL_PTR, 52, field->fld_name, NULL);
2002-06-29 07:39:38 +02:00
}
2001-05-23 15:26:42 +02:00
/* msg 52 array dimension for field %s is invalid */
2002-06-29 07:39:38 +02:00
get_ranges (field);
}
2002-06-29 07:39:38 +02:00
if (!X.RDB$NULL_FLAG.NULL) {
field->fld_null_flag = X.RDB$NULL_FLAG;
2001-05-23 15:26:42 +02:00
field->fld_flags |= FLD_null_flag;
2002-06-29 07:39:38 +02:00
}
2002-06-29 07:39:38 +02:00
if (!X.RDB$DEFAULT_VALUE.NULL) {
2001-05-23 15:26:42 +02:00
blob_id = &X.RDB$DEFAULT_VALUE;
2002-06-29 07:39:38 +02:00
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
2001-05-23 15:26:42 +02:00
field->fld_default_value = X.RDB$DEFAULT_VALUE;
2002-06-29 07:39:38 +02:00
}
}
2002-06-29 07:39:38 +02:00
if (!X.RDB$DEFAULT_SOURCE.NULL) {
2001-05-23 15:26:42 +02:00
blob_id = &X.RDB$DEFAULT_SOURCE;
2002-06-29 07:39:38 +02:00
if (blob_id->gds_quad_low || blob_id->gds_quad_high) {
2001-05-23 15:26:42 +02:00
field->fld_default_source = X.RDB$DEFAULT_SOURCE;
2002-06-29 07:39:38 +02:00
}
}
2002-06-29 07:39:38 +02:00
if (!(Y.RDB$CHARACTER_SET_ID.NULL)) {
2001-05-23 15:26:42 +02:00
field->fld_character_set_id = Y.RDB$CHARACTER_SET_ID;
2002-06-29 07:39:38 +02:00
field->fld_flags |= FLD_charset_flag;
}
2002-06-29 07:39:38 +02:00
if (!X.RDB$COLLATION_ID.NULL) {
2001-05-23 15:26:42 +02:00
field->fld_collation_id = X.RDB$COLLATION_ID;
2002-06-29 07:39:38 +02:00
field->fld_flags |= FLD_collate_flag;
}
2002-06-29 07:39:38 +02:00
field->fld_next = fields;
fields = field;
2002-06-29 07:39:38 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
2001-05-23 15:26:42 +02:00
}
2002-06-29 07:39:38 +02:00
else {
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$RELATION_NAME EQ relation->rel_name
2002-06-29 07:39:38 +02:00
field = (BURP_FLD) BURP_ALLOC_ZERO(sizeof(burp_fld));
2002-06-29 07:39:38 +02:00
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);
2001-05-23 15:26:42 +02:00
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
2002-06-29 07:39:38 +02:00
COPY (RFR.RDB$COMPLEX_NAME, field->fld_complex_name);
2001-05-23 15:26:42 +02:00
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
2002-06-29 07:39:38 +02:00
COPY (RFR.RDB$SECURITY_CLASS, field->fld_security_class);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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)
2003-04-10 08:32:58 +02:00
BURP_error_redirect ((ISC_STATUS*) NULL_PTR, 52, field->fld_name, NULL);
2001-05-23 15:26:42 +02:00
/* 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
2001-05-23 15:26:42 +02:00
AND X2.RDB$RELATION_NAME EQ relation->rel_name
AND X2.RDB$FIELD_SOURCE EQ F2.RDB$FIELD_NAME
2001-05-23 15:26:42 +02:00
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;
2001-05-23 15:26:42 +02:00
field->fld_next = fields;
fields = field;
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
}
return fields;
}
2002-06-29 07:39:38 +02:00
static SINT64 get_gen_id( TEXT * name, SSHORT name_len)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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 read_msg0;
FRBRD *gen_id_reqh;
2001-05-23 15:26:42 +02:00
SINT64 read_msg1;
2002-06-29 07:39:38 +02:00
SSHORT blr_length;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
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((char*)blr_buffer, NULL, NULL, 0);
2001-05-23 15:26:42 +02:00
#endif
blr_length = blr - blr_buffer;
if (isc_compile_request(status_vector,
GDS_REF(tdgbl->db_handle),
GDS_REF(gen_id_reqh),
blr_length, (char*) GDS_VAL(blr_buffer)))
2001-05-23 15:26:42 +02:00
/* if there's no gen_id, never mind ... */
return 0;
if (isc_start_request(status_vector, GDS_REF(gen_id_reqh), GDS_REF(isc_trans), /* use the same one generated by gpre */
2001-05-23 15:26:42 +02:00
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,
GDS_REF(gen_id_reqh),
2001-05-23 15:26:42 +02:00
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,
GDS_REF(gen_id_reqh),
2001-05-23 15:26:42 +02:00
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, GDS_REF(gen_id_reqh));
2001-05-23 15:26:42 +02:00
return read_msg1;
}
static void get_ranges( BURP_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ r a n g e s
*
**************************************
*
* Functional description
* Fill in the range low and high bounds by reading
2001-05-23 15:26:42 +02:00
* 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
2001-05-23 15:26:42 +02:00
if (count != X.RDB$DIMENSION)
2003-04-10 08:32:58 +02:00
BURP_error_redirect ((ISC_STATUS*) NULL_PTR, 52, field->fld_name, NULL);
2001-05-23 15:26:42 +02:00
/* msg 52 array dimension for field %s is invalid */
*rp++ = X.RDB$LOWER_BOUND;
*rp++ = X.RDB$UPPER_BOUND;
count++;
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
if (count != field->fld_dimensions)
2003-04-10 08:32:58 +02:00
BURP_error_redirect((ISC_STATUS*) NULL_PTR, 52, field->fld_name, NULL);
2001-05-23 15:26:42 +02:00
/* msg 52 array dimension for field %s is invalid */
}
static void put_array( BURP_FLD field, BURP_REL relation, ISC_QUAD * blob_id)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p u t _ a r r a y
2001-05-23 15:26:42 +02:00
*
**************************************
*
* Functional description
* Write out an array. If, however, it's null, don't even bother.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
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;
2003-08-15 12:23:46 +02:00
UCHAR blr_buffer[200]; /* enough for a sdl with 16 dimensions */
UCHAR *blr, *slice, *p;
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
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, NULL, 0);
2001-05-23 15:26:42 +02:00
#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)))
2001-05-23 15:26:42 +02:00
{
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, NULL, 0);
2001-05-23 15:26:42 +02:00
#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);
2001-05-23 15:26:42 +02:00
}
static void put_blob( BURP_FLD field, ISC_QUAD * blob_id, ULONG count)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p u t _ b l o b
*
**************************************
*
* Functional description
* Write out a blob. If, however, it's null, don't even bother.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
FRBRD *blob;
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
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))
2001-05-23 15:26:42 +02:00
{
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);
2001-05-23 15:26:42 +02:00
p += 2;
n = (USHORT) isc_vax_integer((char*) p, l);
2001-05-23 15:26:42 +02:00
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:
2003-04-10 08:32:58 +02:00
BURP_error_redirect((ISC_STATUS*) NULL_PTR, 21, (void*) (ULONG) item, NULL);
2001-05-23 15:26:42 +02:00
/* 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)))
2001-05-23 15:26:42 +02:00
{
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.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
ULONG length, n;
FRBRD *blob;
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
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))
2001-05-23 15:26:42 +02:00
{
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);
2001-05-23 15:26:42 +02:00
p += 2;
n = (USHORT) isc_vax_integer((char*) p, l);
2001-05-23 15:26:42 +02:00
p += l;
switch (item)
{
case isc_info_blob_max_segment:
max_segment = n;
break;
case isc_info_blob_total_length:
length = n;
break;
default:
2003-04-07 23:51:21 +02:00
BURP_print(79, (void *) (ULONG) item, NULL, NULL, NULL, NULL);
2001-05-23 15:26:42 +02:00
/* 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)))
2001-05-23 15:26:42 +02:00
{
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(BURP_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p u t _ d a t a
*
**************************************
*
* Functional description
* Write relation meta-data and data.
*
**************************************/
BURP_FLD field;
FRBRD *request;
int records;
2001-05-23 15:26:42 +02:00
UCHAR *p, *blr, *blr_buffer, *buffer;
LSTRING xdr_buffer;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
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:
2003-04-10 08:32:58 +02:00
BURP_error_redirect((ISC_STATUS*) NULL_PTR, 26, (void *) (SLONG) field->fld_type, NULL);
2001-05-23 15:26:42 +02:00
/* 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((char*)blr_buffer, NULL, NULL, 0);
2001-05-23 15:26:42 +02:00
#endif
/* Compile request */
request = NULL;
blr_length = blr - blr_buffer;
if (isc_compile_request(status_vector,
GDS_REF(tdgbl->db_handle),
GDS_REF(request),
blr_length, (SCHAR*) GDS_VAL(blr_buffer)))
2001-05-23 15:26:42 +02:00
{
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);
2001-05-23 15:26:42 +02:00
}
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,
GDS_REF(request),
2001-05-23 15:26:42 +02:00
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,
GDS_REF(request),
2001-05-23 15:26:42 +02:00
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)
2003-04-07 23:51:21 +02:00
BURP_verbose(108, (void *) (SLONG) records, NULL, NULL, NULL, NULL);
2001-05-23 15:26:42 +02:00
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);
2003-04-07 23:51:21 +02:00
BURP_verbose(108, (void *) (SLONG) records, NULL, NULL, NULL, NULL);
2001-05-23 15:26:42 +02:00
/* msg 108 %ld records written */
if (isc_release_request(status_vector, GDS_REF(request)))
2001-05-23 15:26:42 +02:00
BURP_error_redirect(status_vector, 30, NULL, NULL);
/* msg 30 isc_release_request failed */
}
static void put_index( BURP_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$RELATION_NAME EQ relation->rel_name
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
count++;
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
if (count != (ULONG) X.RDB$SEGMENT_COUNT)
2001-05-23 15:26:42 +02:00
{
2003-04-07 23:51:21 +02:00
BURP_print (180, X.RDB$INDEX_NAME, (void*) count, (void*)(ULONG) X.RDB$SEGMENT_COUNT, NULL, NULL);
continue;
2001-05-23 15:26:42 +02:00
}
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
PUT_NUMERIC (att_index_unique_flag, X.RDB$UNIQUE_FLAG);
2001-05-23 15:26:42 +02:00
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle5)
Y IN RDB$INDEX_SEGMENTS WITH
2001-05-23 15:26:42 +02:00
Y.RDB$INDEX_NAME EQ X.RDB$INDEX_NAME
SORTED BY Y.RDB$FIELD_POSITION
2001-05-23 15:26:42 +02:00
PUT_TEXT (att_index_field_name, Y.RDB$FIELD_NAME);
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
2001-05-23 15:26:42 +02:00
put_source_blob (att_index_description2, att_index_description, (ISC_QUAD *)&X.RDB$DESCRIPTION);
PUT_NUMERIC (att_index_type, X.RDB$INDEX_TYPE);
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
}
else
{
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle1)
X IN RDB$INDICES WITH
2001-05-23 15:26:42 +02:00
X.RDB$RELATION_NAME EQ relation->rel_name
2001-05-23 15:26:42 +02:00
count = 0;
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle2)
I_S IN RDB$INDEX_SEGMENTS WITH
2001-05-23 15:26:42 +02:00
I_S.RDB$INDEX_NAME = X.RDB$INDEX_NAME
match = FALSE;
2001-05-23 15:26:42 +02:00
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle3)
RFR IN RDB$RELATION_FIELDS WITH
2001-05-23 15:26:42 +02:00
I_S.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME AND
RFR.RDB$RELATION_NAME = relation->rel_name
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
else
count++;
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
if (count != (ULONG) X.RDB$SEGMENT_COUNT)
2001-05-23 15:26:42 +02:00
{
2003-04-07 23:51:21 +02:00
BURP_print (180, X.RDB$INDEX_NAME, (void*) count, (void*)(ULONG) X.RDB$SEGMENT_COUNT, NULL, NULL);
continue;
2001-05-23 15:26:42 +02:00
}
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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.
2002-06-29 07:39:38 +02:00
* 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).
2001-05-23 15:26:42 +02:00
*
**************************************/
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);
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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( BURP_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p u t _ r e l a t i o n
*
**************************************
*
* Functional description
* Write relation meta-data and data.
*
**************************************/
BURP_FLD fields, field, aligned, unaligned, aligned4, aligned8;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
SLONG length, n;
FRBRD *blob;
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
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))
2001-05-23 15:26:42 +02:00
{
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);
2001-05-23 15:26:42 +02:00
p += 2;
n = (USHORT) isc_vax_integer((SCHAR*) p, l);
2001-05-23 15:26:42 +02:00
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:
2003-04-07 23:51:21 +02:00
BURP_print(79, (void *) (ULONG) item, NULL, NULL, NULL, NULL);
2001-05-23 15:26:42 +02:00
/* 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)))
2001-05-23 15:26:42 +02:00
{
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;
}
2002-06-29 07:39:38 +02:00
static int put_text( SCHAR attribute, TEXT * text, SSHORT size_len)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p u t _ t e x t
*
**************************************
*
* Functional description
2002-06-29 07:39:38 +02:00
* 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.
2001-05-23 15:26:42 +02:00
*
**************************************/
2002-06-29 07:39:38 +02:00
SSHORT l;
2001-05-23 15:26:42 +02:00
TGBL tdgbl;
tdgbl = GET_THREAD_DATA;
2002-06-29 07:39:38 +02:00
l = (SSHORT) symbol_length (text, (ULONG) size_len);
2001-05-23 15:26:42 +02:00
PUT(attribute);
PUT(l);
if (l)
(void) PUT_BLOCK((UCHAR*) text, l);
2001-05-23 15:26:42 +02:00
2002-06-29 07:39:38 +02:00
return l;
2001-05-23 15:26:42 +02:00
}
#ifdef NOT_USED_OR_REPLACED
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
*
**************************************/
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);
}
#endif
2001-05-23 15:26:42 +02:00
static void set_capabilities(void)
{
/**************************************
*
* s e t _ c a p a b i l i t i e s
*
**************************************
*
* Functional description
*
2001-05-23 15:26:42 +02:00
* set the capabilities bits for the
* database being extracted to avoid
* unpleasantness later.
*
**************************************/
FRBRD *req;
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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, GDS_REF(req));
2001-05-23 15:26:42 +02:00
}
2002-06-29 07:39:38 +02:00
static int symbol_length( TEXT * symbol, ULONG size_len)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s y m b o l _ l e n g t h
*
**************************************
*
* Functional description
2002-06-29 07:39:38 +02:00
* Compute length of null terminated symbol.
* CVC: This function should acknowledge embedded blanks.
2001-05-23 15:26:42 +02:00
*
**************************************/
2002-06-29 07:39:38 +02:00
TEXT *p, *q;
if (size_len < 2) {
return 0;
}
--size_len;
p = symbol;
q = p + size_len;
2001-05-23 15:26:42 +02:00
2002-06-29 07:39:38 +02:00
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;
2001-05-23 15:26:42 +02:00
}
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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
*
**************************************
*
* Functional description
* write a record in the burp file for
* each check constraint.
2001-05-23 15:26:42 +02:00
*
**************************************/
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
TGBL tdgbl;
tdgbl = GET_THREAD_DATA;
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$CHECK_CONSTRAINTS
PUT (rec_chk_constraint);
2001-05-23 15:26:42 +02:00
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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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.
2001-05-23 15:26:42 +02:00
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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))
2001-05-23 15:26:42 +02:00
{
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);
2003-04-07 23:51:21 +02:00
BURP_verbose(77, dbb_file, (void *) (ULONG) page_size, NULL, NULL, NULL);
2001-05-23 15:26:42 +02:00
/* 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
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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;
}
2001-05-23 15:26:42 +02:00
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;
2001-05-23 15:26:42 +02:00
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;
}
}
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
PUT(att_end);
}
static void write_exceptions(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
2001-05-23 15:26:42 +02:00
* 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;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
2001-05-23 15:26:42 +02:00
* 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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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);
}
2001-05-23 15:26:42 +02:00
static void write_filters(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
2001-05-23 15:26:42 +02:00
* 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;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
2001-05-23 15:26:42 +02:00
* 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;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
2002-06-29 07:39:38 +02:00
COPY (X.RDB$FUNCTION_NAME, func);
2001-05-23 15:26:42 +02:00
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);
}
2001-05-23 15:26:42 +02:00
static void write_function_args( GDS_NAME funcptr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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.
*
**************************************/
2001-05-23 15:26:42 +02:00
SSHORT l;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$FUNCTION_NAME EQ funcptr
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$FUNCTION_NAME EQ funcptr
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X2.RDB$ARGUMENT_POSITION = X.RDB$ARGUMENT_POSITION;
2001-05-23 15:26:42 +02:00
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. */
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
}
PUT (att_end);
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
}
}
static void write_generators(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
TGBL tdgbl;
2002-06-29 07:39:38 +02:00
SSHORT l;
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
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);
2002-06-29 07:39:38 +02:00
l = PUT_TEXT (att_gen_generator, X.RDB$GENERATOR_NAME);
2003-08-21 13:02:33 +02:00
if (!tdgbl->gbl_sw_meta) {
value = get_gen_id (X.RDB$GENERATOR_NAME, l);
PUT_INT64 (att_gen_value_int64, value);
}
2001-05-23 15:26:42 +02:00
PUT (att_end);
2002-06-29 07:39:38 +02:00
MISC_terminate ( (UCHAR*) X.RDB$GENERATOR_NAME, (UCHAR*) temp, l, sizeof (temp));
#pragma FB_COMPILER_MESSAGE("BRS: casting SINT64 to SLONG")
BURP_verbose (165, temp, (void*) (SLONG) value, NULL, NULL, NULL);
2002-06-29 07:39:38 +02:00
2001-05-23 15:26:42 +02:00
/* 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);
}
2001-05-23 15:26:42 +02:00
static void write_global_fields(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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.
2001-05-23 15:26:42 +02:00
*
**************************************/
SSHORT l;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL, req_handle2 = NULL,
req_handle3 = NULL, req_handle4 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$SYSTEM_FLAG MISSING
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
if (X.RDB$EXTERNAL_LENGTH)
PUT_NUMERIC (att_field_external_length, X.RDB$EXTERNAL_LENGTH);
if (X.RDB$EXTERNAL_TYPE)
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
if (!(X.RDB$FIELD_PRECISION.NULL))
PUT_NUMERIC (att_field_precision, X.RDB$FIELD_PRECISION);
2001-05-23 15:26:42 +02:00
PUT (att_end);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$SYSTEM_FLAG MISSING
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
if (F.RDB$EXTERNAL_LENGTH)
PUT_NUMERIC (att_field_external_length, F.RDB$EXTERNAL_LENGTH);
if (F.RDB$EXTERNAL_TYPE)
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
2001-05-23 15:26:42 +02:00
* 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;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
2002-06-29 07:39:38 +02:00
COPY(X.RDB$PROCEDURE_NAME, proc);
2001-05-23 15:26:42 +02:00
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);
}
2001-05-23 15:26:42 +02:00
static void write_procedure_prms( GDS_NAME procptr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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.
*
**************************************/
2001-05-23 15:26:42 +02:00
SSHORT l;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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;
}
2001-05-23 15:26:42 +02:00
static void write_ref_constraints(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* w r i t e _ r e f _ c o n s t r a i n t s
2001-05-23 15:26:42 +02:00
*
**************************************
*
* Functional description
* write a record in the burp file for
* each referential constraint.
2001-05-23 15:26:42 +02:00
*
**************************************/
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* w r i t e _ r e l _ c o n s t r a i n t s
2001-05-23 15:26:42 +02:00
*
**************************************
*
* Functional description
* write a record in the burp file for
* each relation constraint.
2001-05-23 15:26:42 +02:00
*
**************************************/
SSHORT l;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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.
2001-05-23 15:26:42 +02:00
*
**************************************/
SSHORT l, flags;
BURP_REL relation;
2001-05-23 15:26:42 +02:00
TEXT temp[32];
isc_req_handle req_handle1 = NULL, req_handle2 = NULL, req_handle3 =
NULL, req_handle4 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$SYSTEM_FLAG MISSING
2001-05-23 15:26:42 +02:00
flags = 0;
PUT (rec_relation);
2002-06-29 07:39:38 +02:00
l = PUT_TEXT (att_relation_name, X.RDB$RELATION_NAME);
MISC_terminate ((UCHAR*) X.RDB$RELATION_NAME, (UCHAR*) temp, l, sizeof (temp));
2001-05-23 15:26:42 +02:00
BURP_verbose (153, temp, NULL, NULL, NULL, NULL);
/* msg 153 writing relation %.*s */
2002-06-29 07:39:38 +02:00
/* RDB$VIEW_BLR must be the first blob field in the backup file.
2001-05-23 15:26:42 +02:00
* RESTORE.E makes this assumption in get_relation().
*/
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
put_source_blob (att_relation_ext_description2, att_relation_ext_description, (ISC_QUAD *)&X.RDB$EXTERNAL_DESCRIPTION);
2002-06-29 07:39:38 +02:00
PUT_TEXT (att_relation_owner_name, X.RDB$OWNER_NAME);
2001-05-23 15:26:42 +02:00
if (!X.RDB$EXTERNAL_FILE.NULL)
if (!tdgbl->gbl_sw_convert_ext_tables)
{
2002-06-29 07:39:38 +02:00
PUT_TEXT(att_relation_ext_file_name, X.RDB$EXTERNAL_FILE);
2001-05-23 15:26:42 +02:00
flags |= REL_external;
}
PUT (att_end);
relation = (BURP_REL) BURP_ALLOC_ZERO(sizeof(burp_rel));
2001-05-23 15:26:42 +02:00
relation->rel_next = tdgbl->relations;
tdgbl->relations = relation;
relation->rel_id = X.RDB$RELATION_ID;
2002-06-29 07:39:38 +02:00
relation->rel_name_length = COPY(X.RDB$RELATION_NAME, relation->rel_name);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$SYSTEM_FLAG MISSING
2001-05-23 15:26:42 +02:00
flags = 0;
PUT (rec_relation);
2002-06-29 07:39:38 +02:00
l = PUT_TEXT(att_relation_name, X.RDB$RELATION_NAME);
MISC_terminate ((UCHAR*) X.RDB$RELATION_NAME, (UCHAR*) temp, l, sizeof (temp));
2001-05-23 15:26:42 +02:00
BURP_verbose (153, temp, NULL, NULL, NULL, NULL);
/* msg 153 writing relation %.*s */
2001-05-23 15:26:42 +02:00
/* RDB$VIEW_BLR must be the first blob field in the backup file.
* RESTORE.E makes this assumption in get_relation().
*/
2001-05-23 15:26:42 +02:00
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)
2002-06-29 07:39:38 +02:00
PUT_TEXT(att_relation_security_class, R.RDB$SECURITY_CLASS);
2001-05-23 15:26:42 +02:00
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);
2002-06-29 07:39:38 +02:00
PUT_TEXT(att_relation_owner_name, R.RDB$OWNER_NAME);
2001-05-23 15:26:42 +02:00
if (!R.RDB$EXTERNAL_FILE.NULL)
{
if (!tdgbl->gbl_sw_convert_ext_tables)
{
2002-06-29 07:39:38 +02:00
PUT_TEXT(att_relation_ext_file_name, R.RDB$EXTERNAL_FILE);
2001-05-23 15:26:42 +02:00
flags |= REL_external;
}
}
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
}
PUT (att_end);
relation = (BURP_REL) BURP_ALLOC_ZERO (sizeof(burp_rel));
2001-05-23 15:26:42 +02:00
relation->rel_next = tdgbl->relations;
tdgbl->relations = relation;
relation->rel_id = X.RDB$RELATION_ID;
2002-06-29 07:39:38 +02:00
relation->rel_name_length = COPY(X.RDB$RELATION_NAME, relation->rel_name);
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
TGBL tdgbl;
tdgbl = GET_THREAD_DATA;
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$FILES
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
}
2001-05-23 15:26:42 +02:00
static void write_sql_roles(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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.
2001-05-23 15:26:42 +02:00
*
**************************************/
isc_req_handle req_handle1 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
TGBL tdgbl;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
SSHORT l;
tdgbl = GET_THREAD_DATA;
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$ROLES
2001-05-23 15:26:42 +02:00
PUT (rec_sql_roles);
2002-06-29 07:39:38 +02:00
l = PUT_TEXT(att_role_name, X.RDB$ROLE_NAME);
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
BURP_verbose (249, temp, NULL, NULL, NULL, NULL);
/* msg 249 writing SQL role: %s */
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
if (req_handle1)
isc_release_request(req_status, &req_handle1);
}
2001-05-23 15:26:42 +02:00
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;
2002-06-29 07:39:38 +02:00
TEXT temp[GDS_NAME_LEN];
2001-05-23 15:26:42 +02:00
isc_req_handle req_handle1 = NULL, req_handle2 = NULL;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$SYSTEM_FLAG MISSING
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
BURP_verbose (156, temp, NULL, NULL, NULL, NULL);
/* msg 156 writing trigger %s */
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
if (!(X.RDB$FLAGS.NULL))
PUT_NUMERIC (att_trig_flags, X.RDB$FLAGS);
2001-05-23 15:26:42 +02:00
PUT (att_end);
2001-05-23 15:26:42 +02:00
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
2001-05-23 15:26:42 +02:00
X.RDB$SYSTEM_FLAG MISSING
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
BURP_verbose (156, temp, NULL, NULL, NULL, NULL);
/* msg 156 writing trigger %s */
2001-05-23 15:26:42 +02:00
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);
2001-05-23 15:26:42 +02:00
if (tdgbl->BCK_capabilities & BCK_ods8)
{
FOR (REQUEST_HANDLE req_handle2)
Y IN RDB$TRIGGERS WITH
2001-05-23 15:26:42 +02:00
X.RDB$TRIGGER_NAME = Y.RDB$TRIGGER_NAME
2001-05-23 15:26:42 +02:00
if (!(Y.RDB$FLAGS.NULL))
PUT_NUMERIC (att_trig_flags, Y.RDB$FLAGS);
2001-05-23 15:26:42 +02:00
END_FOR;
ON_ERROR
general_on_error ();
END_ERROR;
}
2001-05-23 15:26:42 +02:00
PUT (att_end);
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
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;
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
2001-05-23 15:26:42 +02:00
* 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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
TGBL tdgbl;
2001-05-23 15:26:42 +02:00
tdgbl = GET_THREAD_DATA;
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$TYPES WITH X.RDB$SYSTEM_FLAG NE 1 OR
2001-05-23 15:26:42 +02:00
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);
}
2001-05-23 15:26:42 +02:00
static void write_user_privileges(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY req_status;
2001-05-23 15:26:42 +02:00
TGBL tdgbl;
2001-05-23 15:26:42 +02:00
tdgbl = GET_THREAD_DATA;
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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));
2001-05-23 15:26:42 +02:00
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);
}