8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 07:23:04 +01:00
firebird-mirror/src/qli/show.epp
2009-05-05 11:45:58 +00:00

2887 lines
73 KiB
Plaintext

/*
* PROGRAM: JRD Command Oriented Query Language
* MODULE: show.epp
* DESCRIPTION: Show environment commands
*
* 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): ______________________________________.
*/
#include "firebird.h"
#include <stdio.h>
#include <string.h>
#include "../jrd/ibase.h"
#include "../qli/dtr.h"
#include "../qli/parse.h"
#include "../qli/compile.h"
#include "../jrd/license.h"
#include "../qli/reqs.h"
#include "../jrd/flags.h"
#include "../qli/all_proto.h"
#include "../qli/comma_proto.h"
#include "../qli/err_proto.h"
#include "../qli/meta_proto.h"
#include "../qli/proc_proto.h"
#include "../qli/show_proto.h"
#include "../jrd/gds_proto.h"
#include "../common/utils_proto.h"
#include "../common/classes/UserBlob.h"
using MsgFormat::SafeArg;
static void array_dimensions(qli_dbb*, const TEXT*);
static void display_acl(qli_dbb*, ISC_QUAD&);
static void display_blob(qli_dbb*, ISC_QUAD&, const TEXT*, USHORT, const UCHAR*, bool);
static void display_blr(qli_dbb*, ISC_QUAD&);
static void display_text(qli_dbb*, ISC_QUAD&, const TEXT*, bool);
static void display_procedure(qli_dbb*, const UCHAR*, FB_API_HANDLE);
static USHORT get_window_size(int);
static void show_blob_info(ISC_QUAD&, ISC_QUAD&, USHORT, USHORT, qli_dbb*, const TEXT*);
static void show_blr(qli_dbb*, USHORT, ISC_QUAD&, USHORT, ISC_QUAD&);
static void show_datatype(qli_dbb*, USHORT, USHORT, SSHORT, SSHORT, USHORT, USHORT);
static void show_dbb(qli_dbb*);
static void show_dbb_parameters(qli_dbb*);
static int show_field_detail(qli_dbb*, const TEXT*, const TEXT*, qli_syntax*);
static int show_field_instances(qli_dbb*, const TEXT*);
static void show_fields(qli_rel*, qli_fld*);
static void show_filt(qli_filter*);
static int show_filter_detail(qli_dbb*, const TEXT*);
static void show_filts(qli_dbb*);
static int show_filters_detail(qli_dbb*);
static void show_fld(qli_syntax*);
static void show_func(qli_func*);
static int show_func_detail(qli_dbb*, const TEXT*);
static void show_funcs(qli_dbb*);
static int show_funcs_detail(qli_dbb*);
static int show_insecure_fields(qli_dbb*, const TEXT*, const TEXT*);
//static void show_forms_db(qli_dbb*);
static void show_gbl_field(qli_syntax*);
static int show_gbl_field_detail(qli_dbb*, const TEXT*);
static void show_gbl_fields(qli_dbb*);
static int show_gbl_fields_detail(qli_dbb*);
static int show_indices_detail(qli_rel*);
static void show_matching();
static void show_names(const TEXT*, USHORT, TEXT*);
static void show_proc(qli_proc*);
static void show_procs(qli_dbb*);
static void show_rel(qli_rel*);
static void show_rel_detail(qli_rel*);
static void show_rels(qli_dbb*, enum show_t, SSHORT);
static USHORT show_security_class_detail(qli_dbb*, const TEXT*);
static USHORT show_security_classes_detail(qli_dbb*);
static void show_string(USHORT, TEXT*, USHORT, TEXT*);
static void show_sys_trigs(qli_dbb*);
static void show_text_blob(qli_dbb*, const TEXT*, USHORT, ISC_QUAD*, USHORT, ISC_QUAD*, bool);
static void show_trig(qli_rel*);
static int show_trigger_detail(qli_dbb*, const TEXT*);
static void show_trigger_header(TEXT*, USHORT, USHORT, USHORT, ISC_QUAD&, qli_dbb*); // const TEXT*);
static void show_trigger_messages(qli_dbb*, const TEXT*);
static void show_trigger_status(TEXT*, USHORT, USHORT, USHORT);
static void show_trigs(qli_dbb*);
static int show_triggers_detail(qli_dbb*);
static void show_var(const qli_name*);
static void show_vars();
static void show_versions();
static void show_view(qli_rel*);
static int show_views_detail(qli_dbb*);
static void view_info(qli_dbb*, const TEXT*, const TEXT*, SSHORT, SSHORT);
static const SCHAR db_items[] =
{
isc_info_page_size, isc_info_db_size_in_pages, isc_info_end
};
static const UCHAR acl_bpb[] =
{
isc_bpb_version1, isc_bpb_source_type, 1, 3,
isc_bpb_target_type, 1, 1
};
static const UCHAR blr_bpb[] =
{
isc_bpb_version1, isc_bpb_source_type, 1, 2,
isc_bpb_target_type, 1, 1
};
DATABASE DB = EXTERN FILENAME "yachts.lnk";
/*
values for rdb$trigger_type, based from types.h
** Some better way should be found to pick this up dynamically (?) **
until then, this must be kept in sync with jrd/types.h manually.
*/
const USHORT PRE_STORE = 1;
const USHORT POST_STORE = 2;
const USHORT PRE_MODIFY = 3;
const USHORT POST_MODIFY = 4;
const USHORT PRE_ERASE = 5;
const USHORT POST_ERASE = 6;
const int buf_len = 256;
typedef TEXT buf_type[buf_len];
void SHOW_stuff( qli_syntax* node)
{
/**************************************
*
* S H O W _ s t u f f
*
**************************************
*
* Functional description
* Show various stuffs.
*
**************************************/
qli_rel* relation;
qli_dbb* dbb;
USHORT count;
qli_name* name;
SSHORT width;
QLI_skip_line = true;
qli_syntax** ptr = node->syn_arg;
for (USHORT i = 0; i < node->syn_count; i++)
{
const show_t sw = (enum show_t)(IPTR)*ptr++;
qli_syntax* value = *ptr++;
if (sw != show_matching_language && sw != show_version &&
sw != show_variable && sw != show_variables && CMD_check_ready())
{
return;
}
switch (sw)
{
case show_all:
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
{
show_dbb(dbb);
for (relation = dbb->dbb_relations; relation; relation = relation->rel_next)
{
if (!(relation->rel_flags & REL_system)) {
show_rel(relation);
show_fields(relation, NULL);
}
if (QLI_abort)
return;
}
printf("\n");
}
if (QLI_variables)
show_vars();
break;
case show_databases:
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
{
show_dbb(dbb);
show_dbb_parameters(dbb);
}
break;
case show_database:
if (!(dbb = (qli_dbb*) value))
dbb = QLI_databases;
show_dbb(dbb);
show_dbb_parameters(dbb);
for (relation = dbb->dbb_relations; relation; relation = relation->rel_next)
{
if (!(relation->rel_flags & REL_system)) {
show_rel(relation);
show_fields(relation, NULL);
}
}
printf("\n");
break;
case show_relations:
case show_system_relations:
// No need to define a buffer here; we are interested in its length.
width = get_window_size(buf_len - 1);
if (dbb = (qli_dbb*) value)
show_rels(dbb, sw, width);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
show_rels(dbb, sw, width);
}
break;
case show_db_fields:
dbb = (qli_dbb*) value;
for (relation = dbb->dbb_relations; relation; relation = relation->rel_next)
{
if (!(relation->rel_flags & REL_system)) {
show_rel(relation);
show_fields(relation, NULL);
}
if (QLI_abort)
return;
}
break;
case show_security_classes:
count = 0;
if (value)
count += show_security_classes_detail((qli_dbb*) value);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
count += show_security_classes_detail(dbb);
}
if (!count) {
ERRQ_msg_put(90);
// Msg90 No security classes defined
}
break;
case show_security_class:
count = 0;
name = (qli_name*) value;
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
count += show_security_class_detail(dbb, name->nam_string);
if (!count) {
ERRQ_msg_put(91, name->nam_string);
// Msg91 Security class %s is not defined
}
break;
case show_views:
count = 0;
if (value)
count += show_views_detail((qli_dbb*) value);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
count += show_views_detail(dbb);
}
if (!count) {
ERRQ_msg_put(92);
// Msg92 No views defined
}
break;
case show_relation:
show_rel((qli_rel*) value);
show_fields((qli_rel*) value, NULL);
show_view((qli_rel*) value);
show_rel_detail((qli_rel*) value);
break;
case show_indices:
if (value)
{
show_rel((qli_rel*) value);
if (!show_indices_detail((qli_rel*) value)) {
ERRQ_msg_put(93);
// Msg93 No indices defined
}
break;
}
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
{
show_dbb(dbb);
for (relation = dbb->dbb_relations; relation; relation = relation->rel_next)
{
if (!(relation->rel_flags & (REL_system | REL_view)))
{
show_rel(relation);
if (!show_indices_detail(relation)) {
ERRQ_msg_put(94);
// Msg94 No indices defined
}
}
}
}
break;
case show_db_indices:
dbb = (qli_dbb*) value;
show_dbb(dbb);
for (relation = dbb->dbb_relations; relation; relation = relation->rel_next)
{
if (!(relation->rel_flags & (REL_system | REL_view)))
{
show_rel(relation);
if (!show_indices_detail(relation)) {
ERRQ_msg_put(94);
// Msg94 No indices defined
}
}
}
break;
case show_field:
show_fld(value);
break;
case show_filter:
show_filt((qli_filter*) value);
break;
case show_filters:
if (value)
show_filts((qli_dbb*) value);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
show_filts(dbb);
}
break;
/*
case show_forms:
if (value)
show_forms_db((qli_dbb*) value);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
show_forms_db(dbb);
}
break;
*/
case show_function:
show_func((qli_func*) value);
break;
case show_functions:
if (value)
show_funcs((qli_dbb*) value);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
show_funcs(dbb);
}
break;
case show_matching_language:
show_matching();
break;
case show_procedures:
if (value)
show_procs((qli_dbb*) value);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
show_procs(dbb);
}
break;
case show_procedure:
show_proc((qli_proc*) value);
break;
case show_version:
show_versions();
break;
case show_variable:
show_var((qli_name*) value);
break;
case show_variables:
show_vars();
break;
case show_global_field:
show_gbl_field(value);
break;
case show_global_fields:
show_gbl_fields((qli_dbb*) value);
break;
case show_trigger:
show_trig((qli_rel*) value);
break;
case show_triggers:
show_trigs((qli_dbb*) value);
break;
case show_system_triggers:
if (value)
show_sys_trigs((qli_dbb*) value);
else {
for (dbb = QLI_databases; dbb; dbb = dbb->dbb_next)
show_sys_trigs(dbb);
}
break;
default:
ERRQ_bugcheck(7); // Msg7 show option not implemented
}
}
}
static void array_dimensions( qli_dbb* database, const TEXT* field_name)
{
/**************************************
*
* a r r a y _ d i m e n s i o n s
*
**************************************
*
* Functional description
* Display the dimensions of an array
*
**************************************/
MET_meta_transaction(database, false);
TEXT s[128], *p = s;
s[0] = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_dimensions])
D IN RDB$FIELD_DIMENSIONS WITH D.RDB$FIELD_NAME = field_name
SORTED BY D.RDB$DIMENSION
if (D.RDB$LOWER_BOUND != 1) {
sprintf(p, "%"SLONGFORMAT":", D.RDB$LOWER_BOUND);
while (*++p);
}
sprintf(p, "%"SLONGFORMAT", ", D.RDB$UPPER_BOUND);
while (*++p);
END_FOR;
--p;
*--p = 0;
ERRQ_msg_partial(479, SafeArg() << s); // Msg479 (%s)
}
static void display_acl( qli_dbb* dbb, ISC_QUAD& blob_id)
{
/**************************************
*
* d i s p l a y _ a c l
*
**************************************
*
* Functional description
* Display the contents of a security class
*
**************************************/
display_blob(dbb, blob_id, "\t ", sizeof(acl_bpb), acl_bpb, true);
}
static void display_blob(qli_dbb* dbb,
ISC_QUAD& blob_id,
const TEXT* prefix,
USHORT bpb_length,
const UCHAR* bpb,
bool strip_line)
{
/**************************************
*
* d i s p l a y _ b l o b
*
**************************************
*
* Functional description
* Display the contents of a security class
*
**************************************/
ISC_STATUS_ARRAY status_vector;
UserBlob blob(status_vector);
if (!blob.open(dbb->dbb_handle, dbb->dbb_meta_trans, blob_id, bpb_length, bpb))
{
ERRQ_database_error(dbb, status_vector);
}
buf_type buffer;
const USHORT buffer_length = sizeof(buffer) - 1;
for (;;)
{
size_t length;
if (!blob.getSegment(buffer_length, buffer, length))
break;
buffer[length--] = 0;
if (strip_line)
{
for (TEXT* b = buffer + length; b >= buffer;)
{
if (*b == '\n' || *b == '\t' || *b == ' ')
*b-- = 0;
else
break;
}
}
else {
if (buffer[length] == '\n')
buffer[length] = 0;
}
if (buffer[0])
printf("%s%s\n", prefix, buffer);
}
blob.close();
}
static void display_blr( qli_dbb* dbb, ISC_QUAD& blob_id)
{
/**************************************
*
* d i s p l a y _ b l r
*
**************************************
*
* Functional description
* Display the contents of a security class
*
**************************************/
display_blob(dbb, blob_id, "\t ", sizeof(blr_bpb), blr_bpb, true);
}
static void display_text( qli_dbb* dbb, ISC_QUAD& blob_id, const TEXT* prefix, bool strip)
{
/**************************************
*
* d i s p l a y _ t e x t
*
**************************************
*
* Functional description
* Display a text blob.
*
**************************************/
display_blob(dbb, blob_id, prefix, 0, NULL, strip);
}
static void display_procedure( qli_dbb* database, const UCHAR* name, FB_API_HANDLE blob)
{
/**************************************
*
* d i s p l a y _ p r o c e d u r e
*
**************************************
*
* Functional description
* Show definition of procedure. Somebody
* else has already figured out what database
* it's in, and so forth.
*
**************************************/
ERRQ_msg_put(96, SafeArg() << name <<
database->dbb_filename << database->dbb_symbol->sym_string);
// Msg96 Procedure %s in database %s (%s)
TEXT buffer[256];
while (PRO_get_line(blob, buffer, sizeof(buffer))) {
printf(" %s", buffer);
}
PRO_close(database, blob);
printf("\n");
}
static USHORT get_window_size( int max_width)
{
/**************************************
*
* g e t _ w i n d o w _ s i z e
*
**************************************
*
* Functional description
* Get the display window size.
*
**************************************/
SSHORT result = QLI_columns;
if (max_width < result)
result = max_width;
return result;
}
static void show_blob_info(ISC_QUAD& blob_blr,
ISC_QUAD& blob_src,
USHORT msg_blr,
USHORT msg_src, qli_dbb* database,
const TEXT* relation_name)
{
/*****************************************************
*
* s h o w _ b l o b _ i n f o
*
*****************************************************
*
* Functional description
* Display source if possible or blr.
*
*****************************************************/
if (UserBlob::blobIsNull(blob_src)) {
ERRQ_msg_put(msg_blr);
display_blr(database, blob_blr);
}
else {
ERRQ_msg_put(msg_src, relation_name);
show_text_blob(database, "\t", 0, &blob_src, 0, NULL, true);
}
}
static void show_blr(qli_dbb* database,
USHORT source_msg,
ISC_QUAD& source, USHORT blr_msg, ISC_QUAD& blr)
{
/**************************************
*
* s h o w _ b l r
*
**************************************
*
* Functional description
* Show either source or blr for a blr item along with
* appopriate messages.
*
**************************************/
if (!UserBlob::blobIsNull(source))
show_text_blob(database, "\t", source_msg, &source, 0, NULL, false);
else if (!UserBlob::blobIsNull(blr))
{
if (blr_msg)
ERRQ_msg_put(blr_msg);
display_blr(database, blr);
}
}
static void show_datatype(qli_dbb* database,
USHORT dtype,
USHORT length,
SSHORT scale,
SSHORT sub_type,
USHORT segment_length,
USHORT dimensions)
{
/**************************************
*
* s h o w _ d a t a t y p e
*
**************************************
*
* Functional description
* Display datatype information.
*
**************************************/
TEXT subtype[32];
SSHORT msg = 0;
switch (dtype)
{
case dtype_text:
msg = 97;
break;
case dtype_varying:
msg = 98;
break;
case dtype_cstring:
length -= 1;
msg = 99;
break;
case dtype_short:
msg = 100;
break;
case dtype_long:
msg = 101;
break;
case dtype_quad:
msg = 102;
break;
case dtype_real:
msg = 103;
break;
case dtype_double:
msg = 104;
break;
case dtype_int64:
msg = 329;
break;
case dtype_blob:
ERRQ_msg_partial(105); // Msg105 blob
if (segment_length) {
ERRQ_msg_partial(106, SafeArg() << segment_length); // Msg106 , segment length %d
}
if (sub_type)
{
// Only the number in case there's no text name for the type.
sprintf(subtype, "%d", sub_type);
if (database && (database->dbb_capabilities & DBB_cap_types))
{
FOR(REQUEST_HANDLE database->dbb_requests[REQ_fld_subtype])
TYPE IN RDB$TYPES WITH TYPE.RDB$FIELD_NAME EQ "RDB$FIELD_SUB_TYPE"
AND TYPE.RDB$TYPE EQ sub_type
TEXT* p = subtype;
for (const TEXT* q = TYPE.RDB$TYPE_NAME; *q && *q != ' ';) {
*p++ = *q++;
}
*p = 0;
END_FOR;
}
ERRQ_msg_partial(107, SafeArg() << subtype);
}
return;
case dtype_sql_date:
ERRQ_msg_partial(110, SafeArg() << length);
ERRQ_msg_partial(107, SafeArg() << "SQL DATE");
return;
case dtype_sql_time:
ERRQ_msg_partial(110, SafeArg() << length);
ERRQ_msg_partial(107, SafeArg() << "SQL TIME");
return;
case dtype_timestamp:
msg = 110;
break;
default:
ERRQ_bugcheck(8); // Msg8 show_fields: dtype not done
}
ERRQ_msg_partial(msg, SafeArg() << length);
if (dimensions) {
ERRQ_msg_partial(433); // Msg433 array
}
switch (dtype)
{
case dtype_short:
case dtype_long:
case dtype_quad:
case dtype_int64:
if (scale) {
ERRQ_msg_partial(111, SafeArg() << scale);
// Msg111 , scale %d
}
break;
case dtype_text:
case dtype_varying:
case dtype_cstring:
if (sub_type == 1)
ERRQ_msg_partial(112); // Msg112 , subtype fixed
else if (sub_type != 0) {
sprintf(subtype, "%d", sub_type);
ERRQ_msg_partial(107, SafeArg() << subtype);
}
break;
}
}
static void show_dbb( qli_dbb* database)
{
/**************************************
*
* s h o w _ d b b
*
**************************************
*
* Functional description
* Print a database name and some
* functional stuff about it.
*
**************************************/
if (database)
{
const qli_symbol* symbol = database->dbb_symbol;
if (symbol) {
ERRQ_msg_put(113, SafeArg() << database->dbb_filename << symbol->sym_string);
// Msg113 Database %s readied as %s
}
else
ERRQ_msg_put(114, database->dbb_filename); // Msg114 Database %s
}
else
ERRQ_msg_put(115); // Msg115 No databases are currently ready
}
static void show_dbb_parameters( qli_dbb* database)
{
/**************************************
*
* s h o w _ d b b _ p a r a m e t e r s
*
**************************************
*
* Functional description
* Print stuff about a database.
*
**************************************/
UCHAR buffer[127];
ISC_STATUS_ARRAY status_vector;
if (!database)
return;
if (isc_database_info(status_vector, &database->dbb_handle,
sizeof(db_items), db_items, sizeof(buffer), (char*) buffer))
{
ERRQ_database_error(database, status_vector);
}
SLONG page_size = 0, allocation = 0;
for (const UCHAR* d = buffer; *d != isc_info_end;)
{
const UCHAR item = *d++;
const SLONG length = gds__vax_integer(d, 2);
d += 2;
switch (item)
{
case isc_info_db_size_in_pages:
allocation = gds__vax_integer(d, length);
break;
case isc_info_page_size:
page_size = gds__vax_integer(d, length);
break;
case isc_info_error:
break;
}
d += length;
}
ERRQ_msg_put(116, SafeArg() << page_size << allocation);
// Msg116 Page size is %d bytes. Current allocation is %d pages.
MET_meta_transaction(database, false);
if (database->dbb_capabilities & DBB_cap_security) {
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_dbb])
D IN RDB$DATABASE
show_string(260, D.RDB$SECURITY_CLASS, 0, NULL);
show_text_blob(database, "\t", 261, &D.RDB$DESCRIPTION, 0, NULL, false);
END_FOR;
}
else {
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_dbb])
D IN RDB$DATABASE
show_text_blob(database, "\t", 262, &D.RDB$DESCRIPTION, 0, NULL, false);
END_FOR;
}
if (database->dbb_capabilities & DBB_cap_files)
{
if (database->dbb_capabilities & DBB_cap_shadowing)
{
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_files])
F IN DB.RDB$FILES SORTED BY F.RDB$SHADOW_NUMBER, F.RDB$FILE_START
if (F.RDB$SHADOW_NUMBER)
{
if (!(F.RDB$FILE_FLAGS & FILE_conditional)) {
ERRQ_msg_put(385, SafeArg() << F.RDB$SHADOW_NUMBER <<
F.RDB$FILE_NAME << F.RDB$FILE_START);
// Msg385 Shadow %d, File:%s starting at page %d
}
}
else {
ERRQ_msg_put(263, SafeArg() << F.RDB$FILE_NAME << F.RDB$FILE_START);
// Msg263 File:%s starting at page %d
}
END_FOR;
}
else {
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_files])
F IN DB.RDB$FILES SORTED BY F.RDB$FILE_START
ERRQ_msg_put(263, SafeArg() << F.RDB$FILE_NAME << F.RDB$FILE_START);
// Msg263 File:%s starting at page %d
END_FOR;
}
}
}
static int show_field_detail(qli_dbb* database,
const TEXT* relation_name,
const TEXT* field_name,
qli_syntax* idx_node)
{
/**************************************
*
* s h o w _ f i e l d _ d e t a i l
*
**************************************
*
* Functional description
* Show everything we know about local
* fields with the specified name in a particular
* database.
*
**************************************/
MET_meta_transaction(database, false);
USHORT count = 0;
if (!(database->dbb_capabilities & DBB_cap_security))
count += show_insecure_fields(database, relation_name, field_name);
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_field])
RFR IN RDB$RELATION_FIELDS CROSS
F IN RDB$FIELDS CROSS
R IN RDB$RELATIONS WITH
RFR.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME AND
R.RDB$RELATION_NAME = RFR.RDB$RELATION_NAME AND
(RFR.RDB$FIELD_NAME = field_name OR
RFR.RDB$QUERY_NAME = field_name OR
(RFR.RDB$QUERY_NAME MISSING AND F.RDB$QUERY_NAME = field_name))
fb_utils::exact_name(RFR.RDB$RELATION_NAME);
if (relation_name && (strcmp(RFR.RDB$RELATION_NAME, relation_name)))
continue;
const USHORT dimensions = MET_dimensions(database, F.RDB$FIELD_NAME);
if (dimensions && idx_node && dimensions != idx_node->syn_arg[s_idx_count]->syn_count)
{
continue;
}
if (count++)
printf("\n");
fb_utils::exact_name(RFR.RDB$FIELD_NAME);
fb_utils::exact_name(F.RDB$FIELD_NAME);
if (!R.RDB$VIEW_BLR.NULL) {
ERRQ_msg_put(495, SafeArg() << RFR.RDB$FIELD_NAME << RFR.RDB$RELATION_NAME <<
database->dbb_symbol->sym_string);
// Msg495 Field %s in view %s of database %s
}
else {
ERRQ_msg_put(496, SafeArg() << RFR.RDB$FIELD_NAME << RFR.RDB$RELATION_NAME <<
database->dbb_symbol->sym_string);
// Msg495 Field %s in relation %s of database %s
}
ERRQ_msg_put(265, F.RDB$FIELD_NAME);
// Msg265 Global field %s
if (!RFR.RDB$BASE_FIELD.NULL) {
fb_utils::exact_name(RFR.RDB$BASE_FIELD);
view_info(database, RFR.RDB$RELATION_NAME, RFR.RDB$BASE_FIELD, RFR.RDB$VIEW_CONTEXT, 0);
}
show_text_blob(database, "\t", 266, &RFR.RDB$DESCRIPTION, 339, &F.RDB$DESCRIPTION, false);
ERRQ_msg_put(267);
// Msg267 Datatype information:
printf("\t");
show_datatype(database, MET_get_datatype(F.RDB$FIELD_TYPE), F.RDB$FIELD_LENGTH,
F.RDB$FIELD_SCALE, F.RDB$FIELD_SUB_TYPE, F.RDB$SEGMENT_LENGTH, dimensions);
if (dimensions && !idx_node)
array_dimensions(database, F.RDB$FIELD_NAME);
printf("\n");
show_blr(database, 341, F.RDB$COMPUTED_SOURCE, 341, F.RDB$COMPUTED_BLR);
show_blr(database, 342, F.RDB$VALIDATION_SOURCE, 342, F.RDB$VALIDATION_BLR);
show_string(270, RFR.RDB$SECURITY_CLASS, 0, NULL);
show_string(271, RFR.RDB$QUERY_NAME, 271, F.RDB$QUERY_NAME);
show_string(273, RFR.RDB$EDIT_STRING, 273, F.RDB$EDIT_STRING);
show_text_blob(database, "\t", 275, &RFR.RDB$QUERY_HEADER, 275, &F.RDB$QUERY_HEADER, false);
END_FOR;
return count;
}
static int show_field_instances( qli_dbb* database, const TEXT* field_name)
{
/**************************************
*
* s h o w _ f i e l d _ i n s t a n c e s
*
**************************************
*
* Functional description
* Print a list of places where a global field
* is used.
*
**************************************/
int count = 0;
MET_meta_transaction(database, false);
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_field_instance])
RFR IN RDB$RELATION_FIELDS WITH RFR.RDB$FIELD_SOURCE = field_name
SORTED BY RFR.RDB$RELATION_NAME
if (!count++) {
ERRQ_msg_put(335, SafeArg() << field_name << database->dbb_symbol->sym_string);
// Msg335 Global field %s is used database %s as:
}
fb_utils::exact_name(RFR.RDB$FIELD_NAME);
fb_utils::exact_name(RFR.RDB$RELATION_NAME);
ERRQ_msg_put(336, SafeArg() << RFR.RDB$FIELD_NAME << RFR.RDB$RELATION_NAME);
// Msg336 %s in relation %s
END_FOR;
return count;
}
static void show_fields( qli_rel* relation, qli_fld* fields)
{
/**************************************
*
* s h o w _ f i e l d s
*
**************************************
*
* Functional description
* Show the fields for a relation.
*
**************************************/
qli_dbb* database;
// Find the long field name (including query name)
if (relation) {
if (!(relation->rel_flags & REL_fields))
MET_fields(relation);
fields = relation->rel_fields;
database = relation->rel_database;
MET_meta_transaction(database, false);
}
else
database = NULL;
USHORT max_name = 0;
const qli_fld* field;
for (field = fields; field; field = field->fld_next)
{
USHORT l = field->fld_name->sym_length;
const qli_symbol* symbol = field->fld_query_name;
if (symbol)
l += symbol->sym_length + 3;
max_name = MAX(max_name, l);
}
// Now print the fields
for (field = fields; field; field = field->fld_next)
{
if (QLI_abort)
return;
const qli_symbol* symbol = field->fld_name;
USHORT l = symbol->sym_length;
printf(" %s", symbol->sym_string);
if (symbol = field->fld_query_name) {
l += symbol->sym_length + 3;
printf(" (%s)", symbol->sym_string);
}
for (l = max_name + 12 - l; l; --l)
putchar(' ');
show_datatype(database, field->fld_dtype,
(field->fld_dtype == dtype_varying) ? field->fld_length - 2 : field->fld_length,
field->fld_scale, field->fld_sub_type, field->fld_segment_length,
(field->fld_flags & FLD_array) ? 1 : 0);
if (database && field->fld_flags & FLD_array)
array_dimensions(database, field->fld_name->sym_string);
if (field->fld_flags & FLD_computed)
ERRQ_msg_put(119); // Msg119 (computed expression)
else
printf("\n");
}
}
static void show_filt( qli_filter* filter)
{
/**************************************
*
* s h o w _ f i l t
*
**************************************
*
* Functional description
* Show definition of filter. If a particular database
* was specified, look there, otherwise, print all filters
* with that name.
*
**************************************/
int count = 0;
const qli_name* name = filter->qfl_name;
qli_dbb* database = filter->qfl_database;
if (database)
{
if (!(database->dbb_capabilities & DBB_cap_filters)) {
// Msg439 Filters are not supported in database %s.
ERRQ_msg_put(439, database->dbb_symbol->sym_string);
return;
}
count = show_filter_detail(database, name->nam_string);
if (!count) {
// Msg440 Filter %s is not defined in database %s.
ERRQ_msg_put(440, SafeArg() << name->nam_string << database->dbb_symbol->sym_string);
}
}
else
{
bool any_supported = false;
for (database = QLI_databases; database; database = database->dbb_next)
{
if (database->dbb_capabilities & DBB_cap_filters) {
any_supported = true;
count += show_filter_detail(database, name->nam_string);
}
}
if (!count)
{
if (any_supported) {
// Msg441 Filter %s is not defined in any open database
ERRQ_msg_put(441, name->nam_string);
}
else {
// Msg442 Filters are not supported in any open database.
ERRQ_msg_put(442);
}
}
}
}
static int show_filter_detail( qli_dbb* database, const TEXT* filter_name)
{
/**************************************
*
* s h o w _ f i l t e r _ d e t a i l
*
**************************************
*
* Functional description
* Display the following information about a
* filter with the specified name in a particular
* database: Filter name, filter library, input and
* output sub-types, and description.
*
**************************************/
MET_meta_transaction(database, false);
int count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_filter_detail])
F IN RDB$FILTERS WITH F.RDB$FUNCTION_NAME = filter_name
count++;
fb_utils::exact_name(F.RDB$FUNCTION_NAME);
ERRQ_msg_put(444, // Msg444 Filter %s in database \"%s\" (%s):
SafeArg() << F.RDB$FUNCTION_NAME << database->dbb_filename <<
database->dbb_symbol->sym_string);
ERRQ_msg_put(445, F.RDB$MODULE_NAME); // Msg445 Filter library is %s
ERRQ_msg_put(446, SafeArg() << F.RDB$INPUT_SUB_TYPE); // Msg446 Input sub-type is %d
ERRQ_msg_put(447, SafeArg() << F.RDB$OUTPUT_SUB_TYPE); // Msg447 Output sub-type is %d
show_text_blob(database, "\t", 448, &F.RDB$DESCRIPTION, 0, NULL, false);
END_FOR;
return count;
}
static void show_filts( qli_dbb* database)
{
/**************************************
*
* s h o w _ f i l t s
*
* Functional description
* Show filter names in a database.
*
**************************************/
if (!(database->dbb_capabilities & DBB_cap_filters)) {
// Msg463 Filters are not supported for database %s.
ERRQ_msg_put(463, database->dbb_symbol->sym_string);
}
else if (!(show_filters_detail(database))) {
// Msg464 no filters defined for database %s.
ERRQ_msg_put(464, database->dbb_symbol->sym_string);
}
}
static int show_filters_detail( qli_dbb* database)
{
/**************************************
*
* s h o w _ f i l t e r s _ d e t a i l
*
**************************************
*
* Functional description
* Show filter names in a database.
*
**************************************/
buf_type buffer;
SSHORT width = get_window_size(sizeof(buffer) - 1);
buffer[0] = 0;
MET_meta_transaction(database, false);
int count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_filters])
F IN RDB$FILTERS
SORTED BY F.RDB$FUNCTION_NAME
if (!count++) {
ERRQ_msg_put(449, SafeArg() << database->dbb_filename <<
database->dbb_symbol->sym_string);
// Msg449 Filters in database %s (%s):
}
show_names(F.RDB$FUNCTION_NAME, width, buffer);
END_FOR;
if (buffer[0])
printf("%s\n", buffer);
return count;
}
static void show_fld( qli_syntax* field_node)
{
/**************************************
*
* s h o w _ f l d
*
**************************************
*
* Functional description
* Show all details about a particular
* field. What we've got coming in
* is a list of 1, 2, or 3 name blocks,
* contain the [[database.]relation.]field
* specification. Figure out what we've
* got and let somebody else do all the work.
*
**************************************/
qli_syntax* idx_node = NULL;
if (field_node->syn_type == nod_index) {
idx_node = field_node;
field_node = idx_node->syn_arg[s_idx_field];
}
qli_dbb* database = NULL;
qli_name* field_name = NULL;
qli_name* relation_name = NULL;
for (qli_syntax** ptr = field_node->syn_arg + field_node->syn_count;
--ptr >= field_node->syn_arg;)
{
if (!field_name)
field_name = (qli_name*) * ptr;
else if (!relation_name)
relation_name = (qli_name*) * ptr;
else
for (qli_symbol* symbol = ((qli_name*) *ptr)->nam_symbol; symbol; symbol = symbol->sym_homonym)
{
if (symbol->sym_type == SYM_database) {
database = (qli_dbb*) symbol->sym_object;
break;
}
}
}
const TEXT* string = relation_name ? relation_name->nam_string : NULL;
TEXT s[65];
if (string)
sprintf(s, "%s.%s", string, field_name->nam_string);
else
sprintf(s, "%s", field_name->nam_string);
int count = 0;
if (database)
{
count += show_field_detail(database, string, field_name->nam_string, NULL);
if (!count) {
ERRQ_msg_put(117, SafeArg() << s << database->dbb_symbol->sym_string);
// Msg117 Field %s does not exist in database %s
}
}
else
{
for (database = QLI_databases; database; database = database->dbb_next)
{
count += show_field_detail(database, string, field_name->nam_string, idx_node);
}
if (!count) {
ERRQ_msg_put(118, s);
// Msg118 Field %s does not exist in any open database
}
}
}
static void show_func( qli_func* func)
{
/**************************************
*
* s h o w _ f u n c
*
**************************************
*
* Functional description
* Show definition of function. If a particular database
* was specified, look there, otherwise, print all functions
* with that name.
*
**************************************/
int count = 0;
const qli_name* name = func->qfn_name;
qli_dbb* database = func->qfn_database;
if (database)
{
if (!(database->dbb_capabilities & DBB_cap_functions)) {
// Msg417 Functions are not supported in database %s.
ERRQ_msg_put(417, database->dbb_symbol->sym_string);
return;
}
count = show_func_detail(database, name->nam_string);
if (!count) {
// Msg422 Function %s is not defined in database %s.
ERRQ_msg_put(422, SafeArg() << name->nam_string << database->dbb_symbol->sym_string);
}
}
else
{
bool any_supported = false;
for (database = QLI_databases; database; database = database->dbb_next)
{
if (database->dbb_capabilities & DBB_cap_functions) {
any_supported = true;
count += show_func_detail(database, name->nam_string);
}
}
if (!count)
{
if (any_supported) {
// Msg423 Function is %s not defined in any open database
ERRQ_msg_put(423, name->nam_string);
}
else {
// Msg420 Functions are not supported in any open database.
ERRQ_msg_put(420);
}
}
}
}
static int show_func_detail( qli_dbb* database, const TEXT* func_name)
{
/**************************************
*
* s h o w _ f u n c _ d e t a i l
*
**************************************
*
* Functional description
* Display the following information about a
* function with the specified name in a particular
* database: Function name, query name, function
* library, input and output argument datatypes, and
* description.
*
**************************************/
MET_meta_transaction(database, false);
int count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_func_detail])
F IN RDB$FUNCTIONS WITH
(F.RDB$FUNCTION_NAME = func_name OR F.RDB$QUERY_NAME = func_name)
count++;
fb_utils::exact_name(F.RDB$QUERY_NAME);
fb_utils::exact_name(F.RDB$FUNCTION_NAME);
BASED ON RDB$FUNCTIONS.RDB$QUERY_NAME fq_name;
strcpy(fq_name, F.RDB$FUNCTION_NAME);
if (F.RDB$QUERY_NAME[0])
{
ERRQ_msg_put(424, // Msg424 Function %s (%s) in database \"%s\" (%s):
SafeArg() << F.RDB$FUNCTION_NAME << F.RDB$QUERY_NAME <<
database->dbb_filename << database->dbb_symbol->sym_string);
}
else
{
ERRQ_msg_put(425, // Msg425 Function %s in database \"%s\" (%s):
SafeArg() << F.RDB$FUNCTION_NAME << database->dbb_filename <<
database->dbb_symbol->sym_string);
}
ERRQ_msg_put(426, F.RDB$MODULE_NAME);
// Msg426 Function library is %s
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_func_args])
FA IN RDB$FUNCTION_ARGUMENTS WITH
FA.RDB$FUNCTION_NAME = fq_name SORTED BY FA.RDB$ARGUMENT_POSITION
if (FA.RDB$ARGUMENT_POSITION == 0) {
ERRQ_msg_partial(427);
// Msg427 Return argument is
}
else {
ERRQ_msg_partial(428, SafeArg() << FA.RDB$ARGUMENT_POSITION);
// Msg428 Argument %d is
}
const USHORT array = (FA.RDB$MECHANISM == 2); // funct below wants USHORT
show_datatype(database, MET_get_datatype(FA.RDB$FIELD_TYPE),
FA.RDB$FIELD_LENGTH, FA.RDB$FIELD_SCALE,
FA.RDB$FIELD_SUB_TYPE, 0, array);
printf("\n");
END_FOR;
show_text_blob(database, "\t", 421, &F.RDB$DESCRIPTION, 0, NULL, false);
END_FOR;
return count;
}
static void show_funcs( qli_dbb* database)
{
/**************************************
*
* s h o w _ f u n c s
*
**************************************
*
* Functional description
* Show function names in all ready databases,
* or a specific database.
*
**************************************/
if (!(database->dbb_capabilities & DBB_cap_functions)) {
ERRQ_msg_put(461, database->dbb_symbol->sym_string);
// 461 - functions aren't supported in this database
}
if (!(show_funcs_detail(database))) {
ERRQ_msg_put(462, database->dbb_symbol->sym_string);
// 462 - no functions are defined in this database
}
}
static int show_funcs_detail( qli_dbb* database)
{
/**************************************
*
* s h o w _ f u n c s _ d e t a i l
*
**************************************
*
* Functional description
* Show function names in a database.
*
**************************************/
buf_type buffer;
SSHORT width = get_window_size(sizeof(buffer) - 1);
buffer[0] = 0;
MET_meta_transaction(database, false);
int count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_functions])
F IN RDB$FUNCTIONS
SORTED BY F.RDB$FUNCTION_NAME
if (!count++) {
// Msg416 Functions in database %s (%s):
ERRQ_msg_put(416, SafeArg() << database->dbb_filename <<
database->dbb_symbol->sym_string);
}
show_names(F.RDB$FUNCTION_NAME, width, buffer);
END_FOR;
if (buffer[0])
printf("%s\n", buffer);
return count;
}
static int show_insecure_fields(qli_dbb* database,
const TEXT* relation_name,
const TEXT* field_name)
{
/**************************************
*
* s h o w _ i n s e c u r e _ f i e l d s
*
**************************************
*
* Functional description
* Show everything we know about local
* fields with the specified name in a particular
* database, that doesn't have security classes
* defined.
*
**************************************/
int count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_field])
RFR IN RDB$RELATION_FIELDS CROSS
F IN RDB$FIELDS CROSS
R IN RDB$RELATIONS WITH
RFR.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME AND
R.RDB$RELATION_NAME = RFR.RDB$RELATION_NAME AND
(RFR.RDB$FIELD_NAME = field_name OR
RFR.RDB$QUERY_NAME = field_name OR
(RFR.RDB$QUERY_NAME MISSING AND F.RDB$QUERY_NAME = field_name))
fb_utils::exact_name(RFR.RDB$RELATION_NAME);
if (relation_name && (strcmp(RFR.RDB$RELATION_NAME, relation_name)))
continue;
if (count++)
printf("\n");
fb_utils::exact_name(RFR.RDB$FIELD_NAME);
fb_utils::exact_name(F.RDB$FIELD_NAME);
if (R.RDB$VIEW_BLR.NULL) {
ERRQ_msg_put(496, SafeArg() << RFR.RDB$FIELD_NAME << RFR.RDB$RELATION_NAME <<
database->dbb_symbol->sym_string);
// Msg495 Field %s in relation %s of database %s
}
else {
ERRQ_msg_put(495, SafeArg() << RFR.RDB$FIELD_NAME << RFR.RDB$RELATION_NAME <<
database->dbb_symbol->sym_string);
// Msg495 Field %s in view %s of database %s
}
ERRQ_msg_put(338, F.RDB$FIELD_NAME);
// Msg338 Global field %s
if (!RFR.RDB$BASE_FIELD.NULL) {
fb_utils::exact_name(RFR.RDB$BASE_FIELD);
view_info(database, RFR.RDB$RELATION_NAME, RFR.RDB$BASE_FIELD, RFR.RDB$VIEW_CONTEXT, 0);
}
show_text_blob(database, "\t", 339, &RFR.RDB$DESCRIPTION, 339, &F.RDB$DESCRIPTION, false);
ERRQ_msg_partial(340); // Msg340 Datatype information:
printf("\t");
show_datatype(database, MET_get_datatype(F.RDB$FIELD_TYPE),
F.RDB$FIELD_LENGTH, F.RDB$FIELD_SCALE,
F.RDB$FIELD_SUB_TYPE, F.RDB$SEGMENT_LENGTH,
MET_dimensions(database, F.RDB$FIELD_NAME));
printf("\n");
show_blr(database, 341, F.RDB$COMPUTED_SOURCE, 341, F.RDB$COMPUTED_BLR);
show_blr(database, 342, F.RDB$VALIDATION_SOURCE, 342, F.RDB$VALIDATION_BLR);
show_string(343, RFR.RDB$QUERY_NAME, 343, F.RDB$QUERY_NAME);
show_string(346, RFR.RDB$EDIT_STRING, 346, F.RDB$EDIT_STRING);
show_text_blob(database, "\t", 345, &RFR.RDB$QUERY_HEADER, 345, &F.RDB$QUERY_HEADER, false);
END_FOR;
return count;
}
#ifdef NOT_USED_OR_REPLACED
static void show_forms_db( qli_dbb* database)
{
/**************************************
*
* s h o w _ f o r m s _ d b
*
**************************************
*
* Functional description
* Show what we know about forms
* for one database.
*
**************************************/
ERRQ_msg_put(120, database->dbb_symbol->sym_string);
// Msg120 There are no forms defined for database %s
}
#endif // NOT_USED_OR_REPLACED
static void show_gbl_field( qli_syntax* field_node)
{
/**************************************
*
* s h o w _ g b l _ f i e l d
*
**************************************
*
* Functional description
* Show what we know about a global
* field. It may be qualified with a
* database handle, in which case, show only
* the one global field in that database,
* otherwise show them all.
*
**************************************/
qli_name* field_name = NULL;
qli_dbb* database = NULL;
for (qli_syntax** ptr = field_node->syn_arg + field_node->syn_count - 1;
ptr >= field_node->syn_arg; ptr--)
{
if (!field_name) {
field_name = (qli_name*) * ptr;
}
else
{
qli_name* name = (qli_name*) *ptr;
for (qli_symbol* symbol = name->nam_symbol; symbol; symbol = symbol->sym_homonym)
{
if (symbol->sym_type == SYM_database) {
database = (qli_dbb*) symbol->sym_object;
break;
}
}
}
}
int count = 0;
if (database)
{
count += show_gbl_field_detail(database, field_name->nam_string);
if (!count) {
ERRQ_msg_put(122, // Msg122 Global field %s does not exist in database %s
SafeArg() << field_name->nam_string <<
database->dbb_symbol->sym_string);
}
}
else
{
for (database = QLI_databases; database; database = database->dbb_next)
count += show_gbl_field_detail(database, field_name->nam_string);
if (!count) {
ERRQ_msg_put(123, field_name->nam_string);
// Msg123 Global field %s does not exist in any open database
}
}
}
static int show_gbl_field_detail( qli_dbb* database, const TEXT* field_name)
{
/**************************************
*
* s h o w _ g b l _ f i e l d _ d e t a i l
*
**************************************
*
* Functional description
* Show everything we know about a global
* field with the specified name in a particular
* database.
*
**************************************/
int count = 0;
MET_meta_transaction(database, false);
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_global_field])
F IN RDB$FIELDS WITH F.RDB$FIELD_NAME = field_name
if (count++)
printf("\n");
fb_utils::exact_name(F.RDB$FIELD_NAME);
ERRQ_msg_put(276, SafeArg() << F.RDB$FIELD_NAME << database->dbb_symbol->sym_string);
// Msg276 Global field %s in database %s
show_text_blob(database, "\t", 277, &F.RDB$DESCRIPTION, 0, NULL, false);
ERRQ_msg_put(278); // Msg278 Datatype information:
printf("\t");
show_datatype(database, MET_get_datatype(F.RDB$FIELD_TYPE),
F.RDB$FIELD_LENGTH, F.RDB$FIELD_SCALE,
F.RDB$FIELD_SUB_TYPE, F.RDB$SEGMENT_LENGTH,
MET_dimensions(database, F.RDB$FIELD_NAME));
printf("\n");
show_blr(database, 279, F.RDB$COMPUTED_SOURCE, 341, F.RDB$COMPUTED_BLR);
show_blr(database, 280, F.RDB$VALIDATION_SOURCE, 342, F.RDB$VALIDATION_BLR);
show_string(281, F.RDB$QUERY_NAME, 0, NULL);
show_string(282, F.RDB$EDIT_STRING, 0, NULL);
show_text_blob(database, "\t", 283, &F.RDB$QUERY_HEADER, 0, NULL, false);
END_FOR;
if (count && !(show_field_instances(database, field_name))) {
ERRQ_msg_put(284, SafeArg() << field_name << database->dbb_symbol->sym_string);
// Msg284 %s is not used in any relations in database %s
}
return count;
}
static void show_gbl_fields( qli_dbb* database)
{
/**************************************
*
* s h o w _ g b l _ f i e l d s
*
**************************************
*
* Functional description
* Show what we know about a global
* field. It may be qualified with a
* database handle, in which case, show only
* the global fields in that database,
* otherwise show them all.
*
**************************************/
int count = 0;
if (database)
{
count += show_gbl_fields_detail(database);
if (!count) {
ERRQ_msg_put(124, database->dbb_symbol->sym_string);
// Msg124 There are no fields defined for database %s
}
}
else
{
for (database = QLI_databases; database; database = database->dbb_next)
{
count += show_gbl_fields_detail(database);
}
if (!count) {
ERRQ_msg_put(125);
// Msg125 There are no fields defined in any open database
}
}
}
static int show_gbl_fields_detail( qli_dbb* database)
{
/**************************************
*
* s h o w _ g b l _ f i e l d s _ d e t a i l
*
**************************************
*
* Functional description
* Show everything we know about
* global fields in a particular
* database.
*
**************************************/
int count = 0;
MET_meta_transaction(database, false);
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_global_fields])
F IN RDB$FIELDS WITH F.RDB$SYSTEM_FLAG MISSING OR
F.RDB$SYSTEM_FLAG = 0 SORTED BY F.RDB$FIELD_NAME
if (!count++) {
ERRQ_msg_put(286, SafeArg() << database->dbb_symbol->sym_string);
// Msg286 Global fields for database %s:
}
if (!F.RDB$COMPUTED_BLR.NULL)
continue;
printf(" %s", F.RDB$FIELD_NAME);
show_datatype(database, MET_get_datatype(F.RDB$FIELD_TYPE),
F.RDB$FIELD_LENGTH, F.RDB$FIELD_SCALE,
F.RDB$FIELD_SUB_TYPE, F.RDB$SEGMENT_LENGTH,
MET_dimensions(database, F.RDB$FIELD_NAME));
show_text_blob(database, "\t", 262, &F.RDB$DESCRIPTION, 0, NULL, false);
printf("\n");
END_FOR;
return count;
}
static int show_indices_detail( qli_rel* relation)
{
/**************************************
*
* s h o w _ i n d i c e s _ d e t a i l
*
**************************************
*
* Functional description
* Show indices for a relation. If none, return 0.
*
**************************************/
USHORT count = 0;
qli_dbb* database = relation->rel_database;
MET_meta_transaction(database, false);
if (database->dbb_capabilities & DBB_cap_idx_inactive)
{
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_indices])
X IN RDB$INDICES CROSS Z IN RDB$RELATIONS
WITH X.RDB$RELATION_NAME EQ relation->rel_symbol->sym_string
AND Z.RDB$RELATION_NAME EQ X.RDB$RELATION_NAME
AND Z.RDB$VIEW_BLR MISSING SORTED BY X.RDB$INDEX_NAME
++count;
USHORT type = 0; // this wasn't reset for each index!
if (database->dbb_capabilities & DBB_cap_index_type)
{
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_index_type])
Y IN RDB$INDICES WITH Y.RDB$INDEX_NAME = X.RDB$INDEX_NAME
type = Y.RDB$INDEX_TYPE;
END_FOR;
}
// Index name can have spaces, we need something like MET_exact_name()
// to replace the custom loops that get rid of trailing spaces.
// I found truncate_string(). But later replaced it by fb_utils::exact_name().
fb_utils::exact_name(X.RDB$INDEX_NAME);
ERRQ_msg_put(450, SafeArg() << X.RDB$INDEX_NAME <<
((X.RDB$UNIQUE_FLAG) ? " (unique)" : "") <<
((type == 1) ? " (descending)" : "") <<
((X.RDB$INDEX_INACTIVE) ? " (inactive)" : ""));
// Msg450 Index %s%s%s%s
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_index])
Y IN RDB$INDEX_SEGMENTS WITH
Y.RDB$INDEX_NAME EQ X.RDB$INDEX_NAME
SORTED BY Y.RDB$FIELD_POSITION
fb_utils::exact_name(Y.RDB$FIELD_NAME);
printf(" %s\n", Y.RDB$FIELD_NAME);
END_FOR;
if (!X.RDB$EXPRESSION_SOURCE.NULL)
show_text_blob(database, "\t ", 0, &X.RDB$EXPRESSION_SOURCE, 0, NULL, true);
else if (!X.RDB$EXPRESSION_BLR.NULL)
{
ERRQ_msg_put (485);
display_blr(database, X.RDB$EXPRESSION_BLR);
}
END_FOR;
}
else
{
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_indices])
X IN RDB$INDICES CROSS Z IN RDB$RELATIONS
WITH X.RDB$RELATION_NAME EQ relation->rel_symbol->sym_string
AND Z.RDB$RELATION_NAME EQ X.RDB$RELATION_NAME
AND Z.RDB$VIEW_BLR MISSING SORTED BY X.RDB$INDEX_NAME
++count;
fb_utils::exact_name(X.RDB$INDEX_NAME);
ERRQ_msg_put(290, SafeArg() << X.RDB$INDEX_NAME <<
((X.RDB$UNIQUE_FLAG) ? " (unique)" : "")); // Msg290 Index %s%s
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_index])
Y IN RDB$INDEX_SEGMENTS WITH
Y.RDB$INDEX_NAME EQ X.RDB$INDEX_NAME
SORTED BY Y.RDB$FIELD_POSITION
fb_utils::exact_name(Y.RDB$FIELD_NAME);
printf(" %s\n", Y.RDB$FIELD_NAME);
END_FOR;
END_FOR;
}
return count;
}
static void show_matching()
{
/**************************************
*
* s h o w _ m a t c h i n g
*
**************************************
*
* Functional description
* Just print the QLI matching language string.
*
**************************************/
if (QLI_abort)
return;
if (QLI_matching_language)
{
buf_type buffer;
strncpy(buffer, (char*) QLI_matching_language->con_data,
QLI_matching_language->con_desc.dsc_length);
buffer[QLI_matching_language->con_desc.dsc_length] = 0;
printf("\n\t%s\n", buffer);
}
}
static void show_names( const TEXT* name, USHORT width, TEXT* buffer)
{
/**************************************
*
* s h o w _ n a m e s
*
**************************************
*
* Functional description
*
**************************************/
BASED ON QLI$PROCEDURES.QLI$PROCEDURE_NAME padded_name;
TEXT* s = buffer + strlen(buffer);
SSHORT len = sizeof(padded_name) - 1;
const SSHORT l1 = s - buffer;
if ((s != buffer) && ((l1 + len + 4) > width))
{
printf("%s\n", buffer);
buffer[0] = 0;
s = buffer;
}
*s++ = ' ';
*s++ = ' ';
*s++ = ' ';
*s++ = ' ';
strcpy(s, name);
while (*s) {
s++;
len--;
}
while (len--) {
*s++ = ' ';
}
*s = 0;
}
static void show_proc( qli_proc* proc)
{
/**************************************
*
* s h o w _ p r o c
*
**************************************
*
* Functional description
* Show definition of procedure. If a particular database
* was specified, look there, otherwise, print all procedures
* with that name.
*
**************************************/
const qli_name* name = proc->qpr_name;
qli_dbb* database = proc->qpr_database;
if (database)
{
FB_API_HANDLE blob = PRO_fetch_procedure(database, (TEXT*) name->nam_string);
if (blob)
display_procedure(database, (const UCHAR*) name->nam_string, blob);
else {
ERRQ_msg_put(126, // Msg126 Procedure %s not found in database %s
SafeArg() << name->nam_string << database->dbb_symbol->sym_string);
}
return;
}
int count = 0;
for (database = QLI_databases; database; database = database->dbb_next)
{
FB_API_HANDLE blob = PRO_fetch_procedure(database, (TEXT*) name->nam_string);
if (blob) {
display_procedure(database, (const UCHAR*) name->nam_string, blob);
count++;
}
}
if (!count) {
ERRQ_msg_put(127, name->nam_string);
// Msg127 Procedure %s not found
return;
}
}
static void show_procs( qli_dbb* database)
{
/**************************************
*
* s h o w _ p r o c s
*
**************************************
*
* Functional description
* Show procedures in a database
*
**************************************/
buf_type buffer;
const SSHORT width = get_window_size(sizeof(buffer) - 1);
PRO_setup(database);
ERRQ_msg_put(128, SafeArg() << database->dbb_filename << // Msg128 Procedures in database %s (%s):
database->dbb_symbol->sym_string);
buffer[0] = 0;
FOR(REQUEST_HANDLE database->dbb_scan_blobs) X IN DB.QLI$PROCEDURES
SORTED BY X.QLI$PROCEDURE_NAME
show_names(X.QLI$PROCEDURE_NAME, width, buffer);
END_FOR;
if (buffer[0])
printf("%s\n", buffer);
}
static void show_rel( qli_rel* relation)
{
/**************************************
*
* s h o w _ r e l
*
**************************************
*
* Functional description
* Just print a relation name. Almost mindless.
*
**************************************/
if (QLI_abort)
return;
printf(" %s\n", relation->rel_symbol->sym_string);
}
static void show_rel_detail( qli_rel* relation)
{
/**************************************
*
* s h o w _ r e l _ d e t a i l
*
**************************************
*
* Functional description
* Ask META to print description,
* security class, etc.
*
**************************************/
const TEXT* relation_name = relation->rel_symbol->sym_string;
qli_dbb* database = relation->rel_database;
MET_meta_transaction(database, false);
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_rel_detail])
R IN RDB$RELATIONS WITH R.RDB$RELATION_NAME = relation_name
show_text_blob(database, "\t", 291, &R.RDB$DESCRIPTION, 0, NULL, false);
if (database->dbb_capabilities & DBB_cap_security)
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_rel_secur])
S IN RDB$RELATIONS WITH S.RDB$RELATION_NAME = R.RDB$RELATION_NAME
AND S.RDB$SECURITY_CLASS NOT MISSING
show_string(292, S.RDB$SECURITY_CLASS, 0, NULL);
END_FOR;
if (database->dbb_capabilities & DBB_cap_extern_file)
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_rel_extern])
E IN RDB$RELATIONS WITH E.RDB$RELATION_NAME = R.RDB$RELATION_NAME
AND E.RDB$EXTERNAL_FILE NOT MISSING
ERRQ_msg_put(293, E.RDB$EXTERNAL_FILE); // Msg293 Stored in external file %s
END_FOR;
// OBSOLETE - Handling of DBB_cap_triggers (old V2 style triggers)
// OBSOLETE - Msg294 An erase trigger is defined for %s
// OBSOLETE - Msg295 A modify trigger is defined for %s
// OBSOLETE - Msg296 A store trigger is defined for %s
if (database->dbb_capabilities & DBB_cap_new_triggers)
{
USHORT msg = 380;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_new_trig_exists])
X IN RDB$TRIGGERS
WITH X.RDB$RELATION_NAME EQ relation->rel_symbol->sym_string
if (!X.RDB$TRIGGER_BLR.NULL)
{
if (msg) {
ERRQ_msg_put(msg);
// Msg380 Trigger defined for this relation
msg = 0;
}
printf("\t");
show_trigger_status(X.RDB$TRIGGER_NAME, X.RDB$TRIGGER_TYPE,
X.RDB$TRIGGER_INACTIVE, X.RDB$TRIGGER_SEQUENCE);
}
END_FOR;
}
END_FOR;
}
static void show_rels( qli_dbb* dbb, enum show_t sw, SSHORT width)
{
/**************************************
*
* s h o w _ r e l s
*
**************************************
*
* Functional description
* Display information about a relations
* or system_relations for a specific database.
*
**************************************/
buf_type buffer;
switch (sw)
{
case show_relations:
{
show_dbb(dbb);
buffer[0] = 0;
for (const qli_rel* relation = dbb->dbb_relations; relation;
relation = relation->rel_next)
{
if (!(relation->rel_flags & REL_system))
show_names(relation->rel_symbol->sym_string, width, buffer);
}
if (buffer[0])
printf("%s\n", buffer);
printf("\n");
break;
}
case show_system_relations:
{
show_dbb(dbb);
buffer[0] = 0;
for (const qli_rel* relation = dbb->dbb_relations; relation;
relation = relation->rel_next)
{
if (relation->rel_flags & REL_system)
show_names(relation->rel_symbol->sym_string, width, buffer);
}
if (buffer[0])
printf("%s\n", buffer);
printf("\n");
}
}
}
static USHORT show_security_class_detail( qli_dbb* database, const TEXT* name)
{
/**************************************
*
* s h o w _ s e c u r i t y _ c l a s s _ d e t a i l
*
**************************************
*
* Functional description
* Show security classes for a databases.
*
**************************************/
MET_meta_transaction(database, false);
if (!(database->dbb_capabilities & DBB_cap_security))
return 0;
USHORT count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_secur_class])
S IN RDB$SECURITY_CLASSES WITH S.RDB$SECURITY_CLASS = name
if (fb_utils::exact_name(S.RDB$SECURITY_CLASS)[0]) {
printf("\t%s:\n", S.RDB$SECURITY_CLASS);
display_acl(database, S.RDB$ACL);
}
count++;
END_FOR;
return count;
}
static USHORT show_security_classes_detail( qli_dbb* database)
{
/**************************************
*
* s h o w _ s e c u r i t y _ c l a s s e s _ d e t a i l
*
**************************************
*
* Functional description
* Show security classes for a databases.
*
**************************************/
MET_meta_transaction(database, false);
if (!(database->dbb_capabilities & DBB_cap_security))
return 0;
USHORT count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_secur])
S IN RDB$SECURITY_CLASSES
if (!count) {
ERRQ_msg_put(297, database->dbb_symbol->sym_string);
// Msg297 Security classes for database %s
}
if (fb_utils::exact_name(S.RDB$SECURITY_CLASS)[0]) {
printf("\t%s:\n", S.RDB$SECURITY_CLASS);
display_acl(database, S.RDB$ACL);
}
count++;
END_FOR;
return count;
}
static void show_string(USHORT msg1, TEXT* string1, USHORT msg2, TEXT* string2)
{
/**************************************
*
* s h o w _ s t r i n g
*
**************************************
*
* Functional description
* Show one of two strings and maybe a message, too.
*
**************************************/
if (string2 && (!*string1 || *string1 == ' ')) {
msg1 = msg2;
string1 = string2;
}
if (!*string1 || *string1 == ' ')
return;
fb_utils::exact_name(string1);
ERRQ_msg_put(msg1, string1);
}
static void show_sys_trigs( qli_dbb* database)
{
/**************************************
*
* s h o w _ s y s _ t r i g s
*
**************************************
*
* Functional description
* Ask META to print trigger information
* for the system. Since parse
* has already swallowed a possible database
* qualifier, just assume that the database
* is the right one.
*
**************************************/
MET_meta_transaction(database, false);
USHORT count = 0;
if (database->dbb_capabilities & DBB_cap_new_triggers)
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_sys_triggers])
X IN RDB$TRIGGERS WITH X.RDB$SYSTEM_FLAG EQ 1
SORTED BY X.RDB$RELATION_NAME, X.RDB$TRIGGER_TYPE,
X.RDB$TRIGGER_SEQUENCE,
X.RDB$TRIGGER_NAME
if (!X.RDB$TRIGGER_BLR.NULL)
{
ERRQ_msg_put(379, X.RDB$RELATION_NAME);
// Msg379 System Triggers
show_trigger_header(X.RDB$TRIGGER_NAME, X.RDB$TRIGGER_TYPE,
X.RDB$TRIGGER_SEQUENCE,
X.RDB$TRIGGER_INACTIVE, X.RDB$DESCRIPTION,
database); //, X.RDB$RELATION_NAME);
show_blob_info(X.RDB$TRIGGER_BLR, X.RDB$TRIGGER_SOURCE,
377, // Msg377 Source for the trigger is not available. Trigger BLR:
376, // Msg376 Source for the trigger
database, X.RDB$RELATION_NAME);
show_trigger_messages(database, X.RDB$TRIGGER_NAME);
count++;
}
END_FOR;
if (!count)
ERRQ_msg_put(378); // Msg378 No system triggers
}
static void show_text_blob(qli_dbb* database,
const TEXT* column,
USHORT msg1,
ISC_QUAD* blob1,
USHORT msg2,
ISC_QUAD* blob2,
bool strip)
{
/**************************************
*
* s h o w _ t e x t _ b l o b
*
**************************************
*
* Functional description
* Display a text blob.
*
**************************************/
if (blob2 && UserBlob::blobIsNull(*blob1)) {
blob1 = blob2;
msg1 = msg2;
}
if (UserBlob::blobIsNull(*blob1))
return;
if (msg1)
ERRQ_msg_put(msg1);
display_text(database, *blob1, column, strip);
}
static void show_trig( qli_rel* relation)
{
/**************************************
*
* s h o w _ t r i g
*
**************************************
*
* Functional description
* Ask META to print trigger information
* for a particular relation. Since parse
* has already swallowed a possible database
* qualifier, just assume that the database
* is the right one.
*
**************************************/
if (!(show_trigger_detail(relation->rel_database, relation->rel_symbol->sym_string)))
{
ERRQ_msg_put(129, relation->rel_symbol->sym_string);
// Msg129 No triggers are defined for relation %s
}
}
static int show_trigger_detail( qli_dbb* database, const TEXT* relation_name)
{
/**************************************
*
* s h o w _ t r i g g e r _ d e t a i l
*
**************************************
*
* Functional description
* Show trigger definitions for a particular
* relation.
*
**************************************/
if (!(database->dbb_capabilities & DBB_cap_new_triggers))
return 0;
MET_meta_transaction(database, false);
int count = 0;
// New style triggers
if (database->dbb_capabilities & DBB_cap_new_triggers)
{
ERRQ_msg_put(365, relation_name); // Msg365 Triggers for relation %s
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_new_trigger])
X IN RDB$TRIGGERS WITH X.RDB$RELATION_NAME EQ relation_name
AND(X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG EQ 0)
SORTED BY X.RDB$TRIGGER_TYPE, X.RDB$TRIGGER_SEQUENCE,
X.RDB$TRIGGER_NAME
if (!X.RDB$TRIGGER_BLR.NULL)
{
show_trigger_header(X.RDB$TRIGGER_NAME, X.RDB$TRIGGER_TYPE,
X.RDB$TRIGGER_SEQUENCE,
X.RDB$TRIGGER_INACTIVE,
X.RDB$DESCRIPTION, database);
//relation_name);
show_blob_info(X.RDB$TRIGGER_BLR, X.RDB$TRIGGER_SOURCE,
377, // Msg377 Source for the trigger is not available. Trigger BLR:
376, // Msg376 Source for the trigger
database, relation_name);
show_trigger_messages(database, X.RDB$TRIGGER_NAME);
count++;
}
END_FOR;
return count;
}
// Old style triggers
// OBSOLETE - 1996-Aug-06 David Schnepper
// OBSOLETE - Msg298 Triggers for relation %s:
// OBSOLETE - Msg299 Source for the erase trigger is not available. Trigger BLR:
// OBSOLETE - Msg300 Erase trigger for relation %s:
// OBSOLETE - Msg301 Source for the modify trigger is not available. Trigger BLR:
// OBSOLETE - Msg302 Modify trigger for relation %s:
// OBSOLETE - Msg303 Source for the store trigger is not available. Trigger BLR:
// OBSOLETE - Msg304 Store trigger for relation %s:
return count;
}
static void show_trigger_header(TEXT* name,
USHORT type,
USHORT sequence,
USHORT inactive,
ISC_QUAD& description,
qli_dbb* database)
//const TEXT* relation_name) // unused param
{
/*****************************************************
*
* s h o w _ t r i g g e r _ h e a d e r
*
*****************************************************
*
* Functional description
* Display header information for a new style
* trigger only.
*
*****************************************************/
show_trigger_status(name, type, inactive, sequence);
show_text_blob(database, "\t ", 375, &description, 0, NULL, true);
}
static void show_trigger_messages( qli_dbb* database, const TEXT* name)
{
/*****************************************************
*
* s h o w _ t r i g g e r _ m e s s a g e s
*
*****************************************************
*
* Display error messages associated with
* a new style (V3) trigger
*
*****************************************************/
bool first = true;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_trig_message])
M IN RDB$TRIGGER_MESSAGES WITH M.RDB$TRIGGER_NAME = name
SORTED BY M.RDB$MESSAGE_NUMBER
if (first) {
ERRQ_msg_put(456, name);
// msg 456: Messages associated with %s:\n
first = false;
}
ERRQ_msg_put(457, SafeArg() << M.RDB$MESSAGE_NUMBER << M.RDB$MESSAGE);
// msg 457: message %ld: %s\n
END_FOR;
if (!first)
printf("\n");
}
static void show_trigger_status(TEXT* name, USHORT type, USHORT status, USHORT sequence)
{
/*****************************************************
*
* s h o w _ t r i g g e r _ s t a t u s
*
*****************************************************
*
* Display type and active status of a new style (V3) trigger
*
*****************************************************/
SCHAR trigger_type[16], trigger_active[9];
int msg_num;
switch (type)
{
case PRE_STORE:
msg_num = 367;
break; // Msg367 pre-store
case POST_STORE:
msg_num = 368;
break; // Msg368 post-store
case PRE_MODIFY:
msg_num = 369;
break; // Msg369 pre-modify
case POST_MODIFY:
msg_num = 370;
break; // Msg370 post-modify
case PRE_ERASE:
msg_num = 371;
break; // Msg371 pre-erase
case POST_ERASE:
msg_num = 372;
break; // Msg372 post-erase
default:
msg_num = 372;
break; // Should never happen, not worth an error
}
ERRQ_msg_format(msg_num, sizeof(trigger_type), trigger_type);
msg_num = status ? 374 : 373;
ERRQ_msg_format(msg_num, sizeof(trigger_active), trigger_active);
fb_utils::exact_name(name);
ERRQ_msg_put(366, SafeArg() << name << trigger_type << sequence << trigger_active);
// Msg366 Name: %s, Type: %s, Sequence: %d, Active: %s
}
static void show_trigs( qli_dbb* database)
{
/**************************************
*
* s h o w _ t r i g s
*
**************************************
*
* Functional description
* Ask META to print all trigger information
* for a particular database or all databases.
*
**************************************/
if (database)
{
if (!show_triggers_detail(database)) {
ERRQ_msg_put(130, database->dbb_symbol->sym_string);
// Msg130 No triggers are defined in database %s
}
}
else
{
for (database = QLI_databases; database; database = database->dbb_next)
if (!show_triggers_detail(database))
{
ERRQ_msg_put(131, database->dbb_symbol->sym_string);
// Msg131 No triggers are defined in database %s
}
}
}
static int show_triggers_detail( qli_dbb* database)
{
/**************************************
*
* s h o w _ t r i g g e r s _ d e t a i l
*
**************************************
*
* Functional description
* Show trigger definitions for a particular
* database
*
**************************************/
MET_meta_transaction(database, false);
int count = 0;
if (!(database->dbb_capabilities & DBB_cap_new_triggers))
return count;
if (database->dbb_capabilities & DBB_cap_new_triggers)
{
// New style triggers
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_new_triggers])
X IN RDB$TRIGGERS WITH X.RDB$SYSTEM_FLAG MISSING
OR X.RDB$SYSTEM_FLAG EQ 0 SORTED BY X.RDB$RELATION_NAME,
X.RDB$TRIGGER_TYPE, X.RDB$TRIGGER_SEQUENCE, X.RDB$TRIGGER_NAME
if (!X.RDB$TRIGGER_BLR.NULL)
{
fb_utils::exact_name(X.RDB$RELATION_NAME);
ERRQ_msg_put(381, X.RDB$RELATION_NAME);
// Msg365 Triggers for relation %s
show_trigger_header(X.RDB$TRIGGER_NAME, X.RDB$TRIGGER_TYPE,
X.RDB$TRIGGER_SEQUENCE,
X.RDB$TRIGGER_INACTIVE,
X.RDB$DESCRIPTION, database);
//X.RDB$RELATION_NAME);
show_blob_info(X.RDB$TRIGGER_BLR, X.RDB$TRIGGER_SOURCE,
377, // Msg377 Source for the trigger is not available. Trigger BLR:
376, // Msg376 Source for the trigger
database, X.RDB$RELATION_NAME);
show_trigger_messages(database, X.RDB$TRIGGER_NAME);
count++;
}
END_FOR;
}
else
{
// Old style triggers
// OBSOLETE - 1996-Aug-06 David Schnepper
// OBSOLETE - Msg305 Triggers for relation %s:
// OBSOLETE - Msg306 Source for the erase trigger is not available. Trigger BLR:
// OBSOLETE - Msg307 Erase trigger for relation %s:
// OBSOLETE - Msg308 Source for the modify trigger is not available. Trigger BLR:
// OBSOLETE - Msg309 Modify trigger for relation %s:
// OBSOLETE - Msg310 Source for the store trigger is not available. Trigger BLR:
// OBSOLETE - Msg311 Store trigger for relation %s:
}
return count;
}
static void show_var( const qli_name* var_name)
{
/**************************************
*
* s h o w _ v a r
*
**************************************
*
* Functional description
* Display a global variables.
*
**************************************/
const qli_fld* variable;
for (variable = QLI_variables; variable; variable = variable->fld_next) {
if (!strcmp(var_name->nam_string, variable->fld_name->sym_string))
break;
}
if (!variable) {
ERRQ_msg_put(474, var_name->nam_string); // Msg474 Variable %s has not been declared
return;
}
ERRQ_msg_put(471, variable->fld_name->sym_string); // Msg471 Variable %s
ERRQ_msg_put(475);
printf("\t");
show_datatype(NULL, variable->fld_dtype,
(variable->fld_dtype == dtype_varying) ?
variable->fld_length - 2 : variable->fld_length,
variable->fld_scale,
variable->fld_sub_type, variable->fld_segment_length,
(variable->fld_flags & FLD_array) ? 1 : 0);
printf("\n");
if (variable->fld_query_name) {
ERRQ_msg_put(472, variable->fld_query_name->sym_string);
}
if (variable->fld_edit_string)
ERRQ_msg_put(473, variable->fld_edit_string);
}
static void show_vars()
{
/**************************************
*
* s h o w _ v a r s
*
**************************************
*
* Functional description
* Display global variables. If there aren't any, don't
* display any.
*
**************************************/
ERRQ_msg_put(132); // Msg132 Variables:
show_fields(NULL, QLI_variables);
}
static void show_versions()
{
/**************************************
*
* s h o w _ v e r s i o n s
*
**************************************
*
* Functional description
* Show the version for QLI and all databases.
*
**************************************/
ERRQ_msg_put(133, GDS_VERSION); // Msg133 QLI, version %s
for (qli_dbb* dbb = QLI_databases; dbb; dbb = dbb->dbb_next) {
ERRQ_msg_put(134, dbb->dbb_filename);
// Msg134 Version(s) for database %s
isc_version(&dbb->dbb_handle, NULL, NULL);
}
}
static void show_view( qli_rel* relation)
{
/**************************************
*
* s h o w _ v i e w
*
**************************************
*
* Functional description
* Call MET to show the view definition
* if there is one.
*
**************************************/
qli_dbb* database = relation->rel_database;
MET_meta_transaction(database, false);
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_view])
X IN RDB$RELATIONS
WITH X.RDB$RELATION_NAME EQ relation->rel_symbol->sym_string
AND X.RDB$VIEW_BLR NOT MISSING
if (X.RDB$VIEW_SOURCE.NULL) {
ERRQ_msg_put(312, relation->rel_symbol->sym_string);
// Msg312 View source for relation %s is not available. View BLR:
display_blr(database, X.RDB$VIEW_BLR);
}
else {
ERRQ_msg_put(313, relation->rel_symbol->sym_string);
// Msg313 Relation %s is a view defined as:
show_text_blob(database, "\t", 0, &X.RDB$VIEW_SOURCE, 0, NULL, false);
}
END_FOR;
}
static int show_views_detail( qli_dbb* database)
{
/**************************************
*
* s h o w _ v i e w s _ d e t a i l
*
**************************************
*
* Functional description
* Show the view definitions. If none, return 0.
*
**************************************/
MET_meta_transaction(database, false);
int count = 0;
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_views])
X IN RDB$RELATIONS WITH X.RDB$VIEW_BLR NOT MISSING
SORTED BY X.RDB$RELATION_NAME
if (!count++) {
ERRQ_msg_put(316, database->dbb_symbol->sym_string);
// Msg316 Views in database %s:
}
fb_utils::exact_name(X.RDB$RELATION_NAME);
ERRQ_msg_put(317, X.RDB$RELATION_NAME); // Msg317 %s comprised of:
FOR(REQUEST_HANDLE database->dbb_requests[REQ_show_view_rel])
V IN RDB$VIEW_RELATIONS
WITH V.RDB$VIEW_NAME = X.RDB$RELATION_NAME
SORTED BY V.RDB$RELATION_NAME
printf(" %s\n", V.RDB$RELATION_NAME);
END_FOR;
END_FOR;
return count;
}
static void view_info(qli_dbb* dbb,
const TEXT* view,
const TEXT* base_field,
SSHORT context,
SSHORT level)
{
/**************************************
*
* v i e w _ i n f o
*
**************************************
*
* Functional description
*
* field came from another relation.
* expand on this phenomenon.
*
**************************************/
TEXT spaces[64];
FOR(REQUEST_HANDLE dbb->dbb_requests[REQ_show_view_field] LEVEL level)
RFR IN RDB$RELATION_FIELDS CROSS VR IN RDB$VIEW_RELATIONS
WITH RFR.RDB$FIELD_NAME = base_field AND
RFR.RDB$RELATION_NAME = VR.RDB$RELATION_NAME AND
VR.RDB$VIEW_NAME = view AND
VR.RDB$VIEW_CONTEXT = context
fb_utils::exact_name(RFR.RDB$RELATION_NAME);
// create some space according to how many levels deep we are;
// this is to avoid using %*s in the printf, which doesn't work for OS/2
TEXT* p = spaces;
for (const TEXT* const end = spaces + MIN((level + 2) * 4, static_cast<int>(sizeof(spaces) - 1));
p < end;)
{
*p++ = ' ';
}
*p = '\0';
if (RFR.RDB$BASE_FIELD.NULL) {
ERRQ_msg_put(507, SafeArg() << spaces << base_field << RFR.RDB$RELATION_NAME);
// Msg507 %s Based on field %s of relation %s
}
else {
ERRQ_msg_put(508, SafeArg() << spaces << base_field << RFR.RDB$RELATION_NAME);
// Msg508 %s Based on field %s of view %s
}
show_text_blob(dbb, "\t", 349, &RFR.RDB$DESCRIPTION, 0, NULL, false);
if (!RFR.RDB$DESCRIPTION.NULL) {
ERRQ_msg_put(349, SafeArg() << spaces << base_field);
// Msg349 %sBase field description for %s:
show_text_blob(dbb, "\t\t", 0, &RFR.RDB$DESCRIPTION, 0, NULL, false);
}
if (!RFR.RDB$BASE_FIELD.NULL && (dbb->dbb_capabilities & DBB_cap_multi_trans))
{
fb_utils::exact_name(RFR.RDB$BASE_FIELD);
view_info(dbb, RFR.RDB$RELATION_NAME, RFR.RDB$BASE_FIELD,
RFR.RDB$VIEW_CONTEXT, level + 1);
}
END_FOR;
}