mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-27 18:03:04 +01:00
709 lines
13 KiB
C++
709 lines
13 KiB
C++
/*
|
|
* PROGRAM: JRD Access Method
|
|
* MODULE: MBLR.C
|
|
* DESCRIPTION: RDB DDL Call translator
|
|
* Translate MBLR byte strings to DYN byte strings.
|
|
*
|
|
* 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 "../jrd/common.h"
|
|
#include "../jrd/gds.h"
|
|
#include "../jrd/mblr.h"
|
|
#include "../jrd/mblr_proto.h"
|
|
|
|
#define GET_BYTE(op) op = (*mblr->met_mblr++); mblr->met_mblr_length--
|
|
#define GET_WORD(op) op = get_word (mblr)
|
|
#define PEEK_BYTE (*mblr->met_mblr)
|
|
#define STUFF(dyn) (*mblr->met_dyn++) = (dyn)
|
|
#define STUFF_END STUFF (gds_dyn_end)
|
|
#define STUFF_LITERAL get_literal (mblr)
|
|
#define STUFF_LITERAL_W get_literal_w (mblr)
|
|
#define STUFF_WORD(dyn) STUFF (dyn); STUFF (dyn >> 8)
|
|
#define STUFF_INT(dyn) STUFF (dyn); STUFF (dyn >> 8); STUFF (dyn >> 16); STUFF (dyn >> 24)
|
|
|
|
#define IN_FIELD 1
|
|
#define IN_INDEX 2
|
|
#define IN_RELATION 3
|
|
#define IN_VIEW 4
|
|
|
|
typedef struct met {
|
|
UCHAR met_op;
|
|
UCHAR *met_mblr;
|
|
UCHAR *met_dyn;
|
|
USHORT met_mblr_length;
|
|
USHORT met_dyn_length;
|
|
} *MET;
|
|
|
|
static int area, level, duplicates;
|
|
|
|
static int field_def(MET);
|
|
static int field_descriptor(MET);
|
|
static void get_literal(MET);
|
|
static void get_literal_w(MET);
|
|
static int get_word(MET);
|
|
static int index_def(MET);
|
|
static int parse_mblr(MET);
|
|
static int relation_def(MET);
|
|
static int view_def(MET);
|
|
|
|
|
|
int MBLR_translate_to_dyn(
|
|
USHORT ddl_operation,
|
|
USHORT mblr_buffer_length,
|
|
UCHAR * mblr_buffer,
|
|
USHORT * dyn_length, UCHAR * dyn_buffer)
|
|
{
|
|
/************************************************
|
|
*
|
|
* M B L R _ t r a n s l a t e _ t o _ d y n
|
|
*
|
|
************************************************
|
|
*
|
|
* Functional description
|
|
* Translate Rdb/VMS RDB$DDL call MBLR byte-string
|
|
* to a DYN byte-string. DYN string is created in
|
|
* a buffer passed by the caller. This routine
|
|
* returns the length of the DYN string, or zero
|
|
* for any failure.
|
|
*
|
|
************************************************/
|
|
struct met mblr;
|
|
UCHAR op;
|
|
int result;
|
|
UCHAR *dyn_start;
|
|
|
|
level = FALSE;
|
|
|
|
if ((ddl_operation != mblr$k_define) &&
|
|
(ddl_operation != mblr$k_modify) && (ddl_operation != mblr$k_delete))
|
|
return FALSE;
|
|
|
|
mblr.met_op = ddl_operation;
|
|
|
|
mblr.met_mblr = mblr_buffer;
|
|
mblr.met_mblr_length = mblr_buffer_length;
|
|
|
|
mblr.met_dyn = dyn_start = dyn_buffer;
|
|
mblr.met_dyn_length = 0;
|
|
|
|
op = *mblr.met_mblr++;
|
|
mblr.met_mblr_length--;
|
|
|
|
if (op != mblr$k_version_1)
|
|
return NULL;
|
|
|
|
*mblr.met_dyn++ = (gds_dyn_version_1);
|
|
*mblr.met_dyn++ = (gds_dyn_begin);
|
|
|
|
op = *mblr.met_mblr++;
|
|
mblr.met_mblr_length--;
|
|
|
|
switch (op) {
|
|
case mblr$k_relation_def:
|
|
area = IN_RELATION;
|
|
result = relation_def(&mblr);
|
|
break;
|
|
case mblr$k_field_def:
|
|
area = IN_FIELD;
|
|
result = field_def(&mblr);
|
|
break;
|
|
case mblr$k_view_def:
|
|
area = IN_VIEW;
|
|
result = view_def(&mblr);
|
|
break;
|
|
case mblr$k_index_def:
|
|
area = IN_INDEX;
|
|
result = index_def(&mblr);
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
*mblr.met_dyn++ = (gds_dyn_end);
|
|
*mblr.met_dyn++ = (gds_dyn_eoc);
|
|
|
|
*dyn_length = mblr.met_dyn - dyn_start;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int field_def(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* f i e l d _ d e f
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Translate a field modify / update / delete.
|
|
*
|
|
**************************************/
|
|
int op, result;
|
|
|
|
result = TRUE;
|
|
|
|
switch (mblr->met_op) {
|
|
case mblr$k_modify:
|
|
STUFF(gds_dyn_mod_global_fld);
|
|
STUFF_LITERAL;
|
|
while ((PEEK_BYTE != mblr$k_field_end) && result)
|
|
result = parse_mblr(mblr);
|
|
break;
|
|
|
|
case mblr$k_define:
|
|
if (level)
|
|
STUFF(gds_dyn_def_local_fld);
|
|
else
|
|
STUFF(gds_dyn_def_global_fld);
|
|
STUFF_LITERAL;
|
|
while ((PEEK_BYTE != mblr$k_field_end) && result)
|
|
result = parse_mblr(mblr);
|
|
break;
|
|
|
|
case mblr$k_delete:
|
|
if (area == IN_FIELD)
|
|
STUFF(gds_dyn_delete_global_fld);
|
|
else
|
|
STUFF(gds_dyn_delete_local_fld);
|
|
STUFF_LITERAL;
|
|
break;
|
|
}
|
|
|
|
if (level)
|
|
GET_BYTE(op);
|
|
|
|
STUFF_END;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int index_def(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* i n d e x _ d e f
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Translate a index modify / update / delete.
|
|
*
|
|
**************************************/
|
|
int result;
|
|
|
|
result = TRUE;
|
|
|
|
switch (mblr->met_op) {
|
|
case mblr$k_modify:
|
|
result = FALSE;
|
|
break;
|
|
|
|
case mblr$k_define:
|
|
duplicates = FALSE;
|
|
STUFF(gds_dyn_def_idx);
|
|
STUFF_LITERAL;
|
|
while ((PEEK_BYTE != mblr$k_index_end) && result)
|
|
result = parse_mblr(mblr);
|
|
STUFF(gds_dyn_idx_inactive);
|
|
STUFF(FALSE);
|
|
if (duplicates == FALSE) {
|
|
STUFF(gds_dyn_idx_unique);
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(TRUE);
|
|
}
|
|
break;
|
|
|
|
case mblr$k_delete:
|
|
STUFF(gds_dyn_delete_idx);
|
|
STUFF_LITERAL;
|
|
break;
|
|
}
|
|
|
|
STUFF_END;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int relation_def(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* r e l a t i o n _ d e f
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Translate a relation modify / update / delete.
|
|
*
|
|
**************************************/
|
|
int result;
|
|
|
|
level = result = TRUE;
|
|
|
|
switch (mblr->met_op) {
|
|
case mblr$k_modify:
|
|
STUFF(gds_dyn_mod_rel);
|
|
break;
|
|
|
|
case mblr$k_define:
|
|
STUFF(gds_dyn_def_rel);
|
|
break;
|
|
|
|
case mblr$k_delete:
|
|
STUFF(gds_dyn_delete_rel);
|
|
break;
|
|
}
|
|
|
|
STUFF_LITERAL;
|
|
|
|
while ((PEEK_BYTE != mblr$k_relation_end) && result)
|
|
result = parse_mblr(mblr);
|
|
|
|
STUFF_END;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int view_def(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* v i e w _ d e f
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Translate a view modify / update / delete.
|
|
*
|
|
**************************************/
|
|
int result;
|
|
|
|
result = TRUE;
|
|
|
|
switch (mblr->met_op) {
|
|
case mblr$k_modify:
|
|
result = FALSE;
|
|
break;
|
|
|
|
case mblr$k_define:
|
|
STUFF(gds_dyn_def_view);
|
|
STUFF_LITERAL;
|
|
while ((PEEK_BYTE != mblr$k_view_end) && result)
|
|
result = parse_mblr(mblr);
|
|
break;
|
|
|
|
case mblr$k_delete:
|
|
STUFF(gds_dyn_delete_rel);
|
|
STUFF_LITERAL;
|
|
break;
|
|
}
|
|
|
|
STUFF_END;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
static int field_descriptor(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* f i e l d _ d e s c r i p t o r
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Translate an mblr field description string
|
|
* from within a define relation statement.
|
|
*
|
|
**************************************/
|
|
int op, type, result;
|
|
|
|
result = TRUE;
|
|
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_type);
|
|
GET_BYTE(type);
|
|
|
|
switch (type) {
|
|
case dsc$k_dtype_adt:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(blr_timestamp);
|
|
break;
|
|
case dsc$k_dtype_b:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(blr_text);
|
|
STUFF(gds_dyn_fld_length);
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(1);
|
|
break;
|
|
case dsc$k_dtype_f:
|
|
case dsc$k_dtype_g:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(type);
|
|
break;
|
|
case dsc$k_dtype_l:
|
|
case dsc$k_dtype_q:
|
|
case dsc$k_dtype_w:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(type);
|
|
STUFF(gds_dyn_fld_scale);
|
|
STUFF_WORD(2);
|
|
GET_BYTE(type);
|
|
STUFF_WORD(type);
|
|
break;
|
|
case dsc$k_dtype_qu:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(blr_blob);
|
|
break;
|
|
case dsc$k_dtype_t:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(blr_text);
|
|
STUFF(gds_dyn_fld_length);
|
|
STUFF_WORD(2);
|
|
GET_WORD(type);
|
|
STUFF_WORD(type);
|
|
break;
|
|
case dsc$k_dtype_vt:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(blr_varying);
|
|
STUFF(gds_dyn_fld_length);
|
|
STUFF_WORD(2);
|
|
GET_WORD(type);
|
|
STUFF_WORD(type);
|
|
break;
|
|
default:
|
|
STUFF_WORD(2);
|
|
STUFF_WORD(blr_short);
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
static void get_literal(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* g e t _ l i t e r a l
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Get a length prefixed literal (byte)
|
|
* Note: most MBLR literals use a byte as a length prefix,
|
|
* DYN literals use a word.
|
|
*
|
|
**************************************/
|
|
|
|
int length, op, n;
|
|
|
|
GET_BYTE(length);
|
|
n = length;
|
|
STUFF_WORD(length);
|
|
|
|
while (--n >= 0) {
|
|
GET_BYTE(op);
|
|
STUFF(op);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
static void get_literal_w(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* g e t _ l i t e r a l_w
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Get a length prefixed literal (word)
|
|
*
|
|
**************************************/
|
|
int length, op, n;
|
|
|
|
GET_WORD(length);
|
|
n = length;
|
|
STUFF_WORD(length);
|
|
|
|
while (--n >= 0) {
|
|
GET_BYTE(op);
|
|
STUFF(op);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int get_word(MET mblr)
|
|
{
|
|
/**************************************
|
|
*
|
|
* g e t _ w o r d
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Pick up a VAX style word.
|
|
*
|
|
**************************************/
|
|
int op, i;
|
|
|
|
GET_BYTE(op);
|
|
GET_BYTE(i);
|
|
op |= i << 8;
|
|
|
|
return op;
|
|
}
|
|
|
|
|
|
|
|
static int parse_mblr(MET mblr)
|
|
{
|
|
/***************************************************
|
|
*
|
|
* p a r s e _ m b l r
|
|
*
|
|
***************************************************
|
|
*
|
|
* Functional description
|
|
* Primary recursive routine to translate mblr.
|
|
*
|
|
***************************************************/
|
|
int op, result, save_area;
|
|
UCHAR *save_dyn;
|
|
|
|
if (!mblr->met_mblr_length)
|
|
return FALSE;
|
|
|
|
op = PEEK_BYTE;
|
|
|
|
result = TRUE;
|
|
|
|
switch (op) {
|
|
case mblr$k_change_attributes:
|
|
case mblr$k_descriptor:
|
|
result = field_descriptor(mblr);
|
|
break;
|
|
|
|
case mblr$k_change_field:
|
|
case mblr$k_delete_field:
|
|
case mblr$k_define_field:
|
|
save_area = area;
|
|
area = IN_FIELD;
|
|
GET_BYTE(op);
|
|
result = field_def(mblr);
|
|
area = save_area;
|
|
break;
|
|
|
|
case mblr$k_dtr_def_val:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_default_value);
|
|
STUFF_LITERAL;
|
|
break;
|
|
|
|
case mblr$k_dtr_edit_str:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_edit_string);
|
|
STUFF_LITERAL;
|
|
break;
|
|
|
|
case mblr$k_dtr_qry_hdr:
|
|
GET_BYTE(op);
|
|
if (PEEK_BYTE == mblr$k_dtr_qry_hdr_line) {
|
|
GET_BYTE(op);
|
|
GET_BYTE(op);
|
|
mblr->met_mblr += op;
|
|
if (PEEK_BYTE != mblr$k_dtr_qry_hdr_end)
|
|
result = FALSE;
|
|
}
|
|
else
|
|
result = FALSE;
|
|
break;
|
|
|
|
case mblr$k_duplicates:
|
|
GET_BYTE(op);
|
|
duplicates = TRUE;
|
|
break;
|
|
|
|
case mblr$k_field_def:
|
|
GET_BYTE(op);
|
|
result = field_def(mblr);
|
|
break;
|
|
|
|
case mblr$k_field_expression:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_computed_blr);
|
|
save_dyn = mblr->met_dyn;
|
|
STUFF_LITERAL_W;
|
|
STUFF(blr_eoc);
|
|
(*save_dyn)++;
|
|
break;
|
|
|
|
case mblr$k_field_name:
|
|
GET_BYTE(op);
|
|
if (area == IN_INDEX)
|
|
STUFF(gds_dyn_fld_name);
|
|
else
|
|
STUFF(gds_dyn_fld_source);
|
|
STUFF_LITERAL;
|
|
break;
|
|
|
|
case mblr$k_missing_value:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_missing_value);
|
|
save_dyn = mblr->met_dyn;
|
|
STUFF_LITERAL_W;
|
|
STUFF(blr_eoc);
|
|
(*save_dyn)++;
|
|
break;
|
|
|
|
case mblr$k_relation_name:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_rel_name);
|
|
STUFF_LITERAL;
|
|
break;
|
|
|
|
case mblr$k_rse:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_view_blr);
|
|
save_dyn = mblr->met_dyn;
|
|
STUFF_LITERAL_W;
|
|
STUFF(blr_eoc);
|
|
(*save_dyn)++;
|
|
break;
|
|
|
|
case mblr$k_valid_if:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_validation_blr);
|
|
save_dyn = mblr->met_dyn;
|
|
STUFF_LITERAL_W;
|
|
STUFF(blr_eoc);
|
|
(*save_dyn)++;
|
|
break;
|
|
|
|
case mblr$k_dtr_qry_nam:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_query_name);
|
|
STUFF_LITERAL;
|
|
break;
|
|
|
|
case mblr$k_valid_if_source:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_validation_source);
|
|
STUFF_LITERAL_W;
|
|
break;
|
|
|
|
case mblr$k_computed_by_source:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_computed_source);
|
|
STUFF_LITERAL_W;
|
|
break;
|
|
|
|
case mblr$k_rse_source:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_view_source);
|
|
STUFF_LITERAL_W;
|
|
break;
|
|
|
|
case mblr$k_description_source:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_description);
|
|
STUFF_LITERAL_W;
|
|
break;
|
|
|
|
case mblr$k_sub_type:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_sub_type);
|
|
STUFF_WORD(2);
|
|
GET_WORD(op);
|
|
STUFF_WORD(op);
|
|
break;
|
|
|
|
case mblr$k_segment_length:
|
|
GET_BYTE(op);
|
|
STUFF(gds_dyn_fld_segment_length);
|
|
STUFF_WORD(2);
|
|
GET_WORD(op);
|
|
STUFF_WORD(op);
|
|
break;
|
|
|
|
case mblr$k_field_noupdate:
|
|
case mblr$k_field_update:
|
|
GET_BYTE(op);
|
|
break;
|
|
|
|
case mblr$k_index_unknown1:
|
|
GET_BYTE(op);
|
|
break;
|
|
|
|
case mblr$k_index_unknown2:
|
|
GET_BYTE(op);
|
|
GET_BYTE(op);
|
|
GET_BYTE(op);
|
|
break;
|
|
|
|
case mblr$k_field_end:
|
|
case mblr$k_index_end:
|
|
case mblr$k_relation_end:
|
|
case mblr$k_view_end:
|
|
break;
|
|
|
|
case mblr_null:
|
|
case mblr$k_cdd_path:
|
|
case mblr$k_commit:
|
|
case mblr$k_constraint:
|
|
case mblr$k_constraint_count:
|
|
case mblr$k_constraint_def:
|
|
case mblr$k_constraint_end:
|
|
case mblr$k_delete_attributes:
|
|
case mblr$k_dtr_qry_hdr_line:
|
|
case mblr$k_dtr_qry_hdr_end:
|
|
case mblr$k_update:
|
|
default:
|
|
result = FALSE;
|
|
break;
|
|
|
|
}
|
|
|
|
return result;
|
|
}
|