mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-27 07:23:04 +01:00
2887 lines
73 KiB
Plaintext
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;
|
|
}
|