8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 06:43:02 +01:00
firebird-mirror/src/dudley/generate.cpp

642 lines
13 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Data Definition Utility
* MODULE: generate.cpp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Blr generator
*
* 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"
2001-05-23 15:26:42 +02:00
#include <string.h>
2003-11-08 00:27:24 +01:00
#include "../jrd/ibase.h"
2001-05-23 15:26:42 +02:00
#include "../dudley/ddl.h"
#include "../jrd/acl.h"
#include "../dudley/gener_proto.h"
#include "../jrd/gds_proto.h"
#include "../dudley/trn_proto.h"
static void generate(STR, DUDLEY_NOD);
static void get_set_generator(STR, DUDLEY_NOD);
2001-05-23 15:26:42 +02:00
static inline void check_blr(str* blr, const int l)
{
if (!(blr->str_current - blr->str_start + l <= blr->str_length)
&& !TRN_get_buffer(blr, l) )
{
DDL_err (289, NULL, NULL, NULL, NULL, NULL);
}
}
2001-05-23 15:26:42 +02:00
int GENERATE_acl( SCL sec_class, UCHAR * buffer)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* G E N E R A T E _ a c l
*
**************************************
*
* Functional description
* Generate an access control list.
*
**************************************/
UCHAR** id;
2001-05-23 15:26:42 +02:00
USHORT i;
UCHAR* p = buffer;
2001-05-23 15:26:42 +02:00
*p++ = ACL_version;
for (SCE item = sec_class->scl_entries; item; item = item->sce_next) {
2001-05-23 15:26:42 +02:00
*p++ = ACL_id_list;
for (i = 0, id = item->sce_idents; i < id_max; id++, i++)
{
const UCHAR* q = *id;
if (q) {
2001-05-23 15:26:42 +02:00
*p++ = i;
*p++ = strlen((const char*) q);
UCHAR c;
2001-05-23 15:26:42 +02:00
while (c = *q++)
*p++ = UPPER(c);
}
}
2001-05-23 15:26:42 +02:00
*p++ = priv_end;
*p++ = ACL_priv_list;
for (i = 0; i < priv_max; i++)
if (item->sce_privileges & (1 << i))
*p++ = i;
*p++ = id_end;
}
*p++ = ACL_end;
return p - buffer;
}
void GENERATE_blr( STR blr, DUDLEY_NOD node)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* G E N E R A T E _ b l r
*
**************************************
*
* Functional description
* Compile a node tree into a blr string.
*
**************************************/
check_blr(blr, 1);
blr->add_byte(blr_version4);
2001-05-23 15:26:42 +02:00
generate(blr, node);
check_blr(blr, 1);
blr->add_byte(blr_eoc);
2001-05-23 15:26:42 +02:00
}
static void generate( STR blr, DUDLEY_NOD node)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e n e r a t e
*
**************************************
*
* Functional description
* Generate blr.
*
**************************************/
DUDLEY_FLD field;
DUDLEY_REL relation;
2001-05-23 15:26:42 +02:00
SYM symbol;
CON constant;
DUDLEY_NOD sub;
DUDLEY_CTX context;
2001-07-12 07:46:06 +02:00
SCHAR operatr, *p;
2001-05-23 15:26:42 +02:00
SLONG value;
USHORT l, pos;
2001-05-23 15:26:42 +02:00
USHORT posi = 0;
USHORT endi = node->nod_count;
2001-05-23 15:26:42 +02:00
switch (node->nod_type) {
case nod_fid:
check_blr(blr, 4);
blr->add_byte(blr_fid);
blr->add_byte(0);
blr->add_word(0);
2001-05-23 15:26:42 +02:00
return;
case nod_field:
check_blr(blr, 4);
2001-05-23 15:26:42 +02:00
if (sub = node->nod_arg[s_fld_subs])
blr->add_byte(blr_index);
blr->add_byte(blr_field);
field = (DUDLEY_FLD) node->nod_arg[s_fld_field];
context = (DUDLEY_CTX) node->nod_arg[s_fld_context];
blr->add_byte(context->ctx_context_id);
2001-05-23 15:26:42 +02:00
symbol = field->fld_name;
blr->add_byte(l = symbol->sym_length);
2001-05-23 15:26:42 +02:00
p = (SCHAR *) symbol->sym_string;
if (l) {
check_blr(blr, l);
2001-05-23 15:26:42 +02:00
do
blr->add_byte(*p++);
2001-05-23 15:26:42 +02:00
while (--l);
}
if (sub) {
check_blr(blr, 1);
blr->add_byte(sub->nod_count);
for (pos = 0; pos < sub->nod_count; pos++)
generate(blr, sub->nod_arg[pos]);
2001-05-23 15:26:42 +02:00
}
return;
case nod_function:
check_blr(blr, 2);
blr->add_byte(blr_function);
2001-05-23 15:26:42 +02:00
symbol = (SYM) node->nod_arg[1];
blr->add_byte(l = symbol->sym_length);
2001-05-23 15:26:42 +02:00
p = (SCHAR *) symbol->sym_string;
if (l) {
check_blr(blr, l);
2001-05-23 15:26:42 +02:00
do
blr->add_byte(*p++);
2001-05-23 15:26:42 +02:00
while (--l);
}
sub = node->nod_arg[0];
check_blr(blr, 1);
blr->add_byte(sub->nod_count);
for (pos = 0; pos < sub->nod_count ; pos++)
generate(blr, sub->nod_arg[pos]);
2001-05-23 15:26:42 +02:00
return;
case nod_context:
context = (DUDLEY_CTX) node->nod_arg[0];
2001-05-23 15:26:42 +02:00
relation = context->ctx_relation;
check_blr(blr, 2);
blr->add_byte(blr_relation);
2001-05-23 15:26:42 +02:00
symbol = relation->rel_name;
blr->add_byte(l = symbol->sym_length);
2001-05-23 15:26:42 +02:00
p = (SCHAR *) symbol->sym_string;
if (l) {
check_blr(blr, l);
2001-05-23 15:26:42 +02:00
do
blr->add_byte(*p++);
2001-05-23 15:26:42 +02:00
while (--l);
}
check_blr(blr, 1);
blr->add_byte(context->ctx_context_id);
2001-05-23 15:26:42 +02:00
return;
case nod_gen_id:
check_blr(blr, 2);
blr->add_byte(blr_gen_id);
2001-05-23 15:26:42 +02:00
symbol = (SYM) node->nod_arg[1];
blr->add_byte(l = symbol->sym_length);
2001-05-23 15:26:42 +02:00
p = (SCHAR *) symbol->sym_string;
if (l) {
check_blr(blr, l);
2004-05-29 06:55:23 +02:00
do {
blr->add_byte(*p++);
2004-05-29 06:55:23 +02:00
} while (--l);
2001-05-23 15:26:42 +02:00
}
generate(blr, node->nod_arg[0]);
return;
case nod_set_generator:
get_set_generator(blr, node);
return;
case nod_user_name:
check_blr(blr, 1);
blr->add_byte(blr_user_name);
2001-05-23 15:26:42 +02:00
return;
case nod_null:
check_blr(blr, 1);
blr->add_byte(blr_null);
2001-05-23 15:26:42 +02:00
return;
case nod_literal:
check_blr(blr, 6);
blr->add_byte(blr_literal);
2001-05-23 15:26:42 +02:00
constant = (CON) node->nod_arg[0];
l = constant->con_desc.dsc_length;
switch (constant->con_desc.dsc_dtype) {
case dtype_text:
blr->add_byte(blr_text);
blr->add_word(l);
2001-05-23 15:26:42 +02:00
break;
case dtype_short:
check_blr(blr, 2);
blr->add_byte(blr_short);
blr->add_byte(constant->con_desc.dsc_scale);
2001-05-23 15:26:42 +02:00
break;
case dtype_long:
check_blr(blr, 2);
blr->add_byte(blr_long);
blr->add_byte(constant->con_desc.dsc_scale);
2001-05-23 15:26:42 +02:00
break;
case dtype_quad:
check_blr(blr, 2);
blr->add_byte(blr_quad);
blr->add_byte(constant->con_desc.dsc_scale);
2001-05-23 15:26:42 +02:00
break;
case dtype_real:
check_blr(blr, 1);
blr->add_byte(blr_float);
2001-05-23 15:26:42 +02:00
break;
case dtype_double:
check_blr(blr, 1);
blr->add_byte(blr_double);
2001-05-23 15:26:42 +02:00
break;
case dtype_timestamp:
check_blr(blr, 1);
blr->add_byte(blr_timestamp);
2001-05-23 15:26:42 +02:00
break;
case dtype_int64:
case dtype_sql_time:
case dtype_sql_date:
default:
DDL_err(95, NULL, NULL, NULL, NULL, NULL);
// msg 95: GENERATE_blr: dtype not supported
2001-05-23 15:26:42 +02:00
}
p = (SCHAR *) constant->con_data;
switch (constant->con_desc.dsc_dtype) {
case dtype_short:
value = *(SSHORT *) p;
check_blr(blr, 2);
blr->add_word(value);
2001-05-23 15:26:42 +02:00
break;
case dtype_long:
value = *(SLONG *) p;
check_blr(blr, 4);
blr->add_word(value);
blr->add_word(value >> 16);
2001-05-23 15:26:42 +02:00
break;
case dtype_quad:
case dtype_timestamp:
value = *(SLONG *) p;
check_blr(blr, 8);
blr->add_word(value);
blr->add_word(value >> 16);
2001-05-23 15:26:42 +02:00
value = *(SLONG *) (p + 4);
blr->add_word(value);
blr->add_word(value >> 16);
2001-05-23 15:26:42 +02:00
break;
default:
if (l) {
check_blr(blr, l);
2004-05-29 06:55:23 +02:00
do {
blr->add_byte(*p++);
2004-05-29 06:55:23 +02:00
} while (--l);
2001-05-23 15:26:42 +02:00
}
}
return;
case nod_rse:
check_blr(blr, 2);
blr->add_byte(blr_rse);
2001-05-23 15:26:42 +02:00
sub = node->nod_arg[s_rse_contexts];
blr->add_byte(sub->nod_count);
for (pos = 0; pos < sub->nod_count ; pos++)
generate(blr, sub->nod_arg[pos]);
2001-05-23 15:26:42 +02:00
if (sub = node->nod_arg[s_rse_first]) {
check_blr(blr, 1);
blr->add_byte(blr_first);
2001-05-23 15:26:42 +02:00
generate(blr, sub);
}
if (sub = node->nod_arg[s_rse_boolean]) {
check_blr(blr, 1);
blr->add_byte(blr_boolean);
2001-05-23 15:26:42 +02:00
generate(blr, sub);
}
if (sub = node->nod_arg[s_rse_sort]) {
check_blr(blr, 2);
blr->add_byte(blr_sort);
blr->add_byte(sub->nod_count / 2);
for (pos = 0; pos < sub->nod_count ; pos+=2) {
check_blr(blr, 1);
blr->add_byte((sub->nod_arg[pos + 1]) ? blr_descending : blr_ascending);
generate(blr, sub->nod_arg[pos]);
2001-05-23 15:26:42 +02:00
}
}
if (sub = node->nod_arg[s_rse_reduced]) {
check_blr(blr, 2);
blr->add_byte(blr_project);
blr->add_byte(sub->nod_count / 2);
for (pos = 0; pos < sub->nod_count ; pos+=2)
generate(blr, sub->nod_arg[pos]);
2001-05-23 15:26:42 +02:00
}
check_blr(blr, 1);
blr->add_byte(blr_end);
2001-05-23 15:26:42 +02:00
return;
case nod_count:
case nod_max:
case nod_min:
case nod_total:
case nod_average:
case nod_from:
switch (node->nod_type) {
case nod_count:
2001-07-12 07:46:06 +02:00
operatr = blr_count;
2001-05-23 15:26:42 +02:00
break;
case nod_max:
2001-07-12 07:46:06 +02:00
operatr = blr_maximum;
2001-05-23 15:26:42 +02:00
break;
case nod_min:
2001-07-12 07:46:06 +02:00
operatr = blr_minimum;
2001-05-23 15:26:42 +02:00
break;
case nod_total:
2001-07-12 07:46:06 +02:00
operatr = blr_total;
2001-05-23 15:26:42 +02:00
break;
case nod_average:
2001-07-12 07:46:06 +02:00
operatr = blr_average;
2001-05-23 15:26:42 +02:00
break;
case nod_from:
2001-07-12 07:46:06 +02:00
operatr = (node->nod_arg[s_stt_default]) ? blr_via : blr_from;
2001-05-23 15:26:42 +02:00
break;
}
check_blr(blr, 1);
blr->add_byte(operatr);
2001-05-23 15:26:42 +02:00
generate(blr, node->nod_arg[s_stt_rse]);
if (sub = node->nod_arg[s_stt_value])
generate(blr, sub);
if (sub = node->nod_arg[s_stt_default])
generate(blr, sub);
return;
case nod_any:
check_blr(blr, 1);
blr->add_byte(blr_any);
2001-05-23 15:26:42 +02:00
generate(blr, node->nod_arg[0]);
return;
case nod_unique:
check_blr(blr, 1);
blr->add_byte(blr_unique);
2001-05-23 15:26:42 +02:00
generate(blr, node->nod_arg[0]);
return;
case nod_if:
check_blr(blr, 1);
blr->add_byte(blr_if);
generate(blr, node->nod_arg[posi++]);
generate(blr, node->nod_arg[posi++]);
if (node->nod_arg[posi])
generate(blr, node->nod_arg[posi]);
2001-05-23 15:26:42 +02:00
else {
check_blr(blr, 1);
blr->add_byte(blr_end);
2001-05-23 15:26:42 +02:00
}
return;
case nod_list:
check_blr(blr, 1);
blr->add_byte(blr_begin);
for (; posi < endi; posi++)
generate(blr, node->nod_arg[posi]);
check_blr(blr, 1);
blr->add_byte(blr_end);
2001-05-23 15:26:42 +02:00
return;
case nod_abort:
check_blr(blr, 2);
blr->add_byte(blr_leave);
blr->add_byte((IPTR) node->nod_arg[0]);
2001-05-23 15:26:42 +02:00
return;
case nod_erase:
check_blr(blr, 2);
blr->add_byte(blr_erase);
context = (DUDLEY_CTX) node->nod_arg[0];
blr->add_byte(context->ctx_context_id);
2001-05-23 15:26:42 +02:00
return;
case nod_modify:
check_blr(blr, 3);
blr->add_byte(blr_modify);
context = (DUDLEY_CTX) node->nod_arg[s_mod_old_ctx];
blr->add_byte(context->ctx_context_id);
context = (DUDLEY_CTX) node->nod_arg[s_mod_new_ctx];
blr->add_byte(context->ctx_context_id);
2001-05-23 15:26:42 +02:00
generate(blr, node->nod_arg[s_mod_action]);
return;
case nod_eql:
2001-07-12 07:46:06 +02:00
operatr = blr_eql;
2001-05-23 15:26:42 +02:00
break;
case nod_neq:
2001-07-12 07:46:06 +02:00
operatr = blr_neq;
2001-05-23 15:26:42 +02:00
break;
case nod_gtr:
2001-07-12 07:46:06 +02:00
operatr = blr_gtr;
2001-05-23 15:26:42 +02:00
break;
case nod_geq:
2001-07-12 07:46:06 +02:00
operatr = blr_geq;
2001-05-23 15:26:42 +02:00
break;
case nod_leq:
2001-07-12 07:46:06 +02:00
operatr = blr_leq;
2001-05-23 15:26:42 +02:00
break;
case nod_lss:
2001-07-12 07:46:06 +02:00
operatr = blr_lss;
2001-05-23 15:26:42 +02:00
break;
case nod_between:
2001-07-12 07:46:06 +02:00
operatr = blr_between;
2001-05-23 15:26:42 +02:00
break;
case nod_matches:
2001-07-12 07:46:06 +02:00
operatr = blr_matching;
2001-05-23 15:26:42 +02:00
break;
case nod_containing:
2001-07-12 07:46:06 +02:00
operatr = blr_containing;
2001-05-23 15:26:42 +02:00
break;
case nod_starts:
2001-07-12 07:46:06 +02:00
operatr = blr_starting;
2001-05-23 15:26:42 +02:00
break;
case nod_missing:
2001-07-12 07:46:06 +02:00
operatr = blr_missing;
2001-05-23 15:26:42 +02:00
break;
case nod_and:
2001-07-12 07:46:06 +02:00
operatr = blr_and;
2001-05-23 15:26:42 +02:00
break;
case nod_or:
2001-07-12 07:46:06 +02:00
operatr = blr_or;
2001-05-23 15:26:42 +02:00
break;
case nod_not:
2001-07-12 07:46:06 +02:00
operatr = blr_not;
2001-05-23 15:26:42 +02:00
break;
case nod_add:
2001-07-12 07:46:06 +02:00
operatr = blr_add;
2001-05-23 15:26:42 +02:00
break;
case nod_subtract:
2001-07-12 07:46:06 +02:00
operatr = blr_subtract;
2001-05-23 15:26:42 +02:00
break;
case nod_multiply:
2001-07-12 07:46:06 +02:00
operatr = blr_multiply;
2001-05-23 15:26:42 +02:00
break;
case nod_divide:
2001-07-12 07:46:06 +02:00
operatr = blr_divide;
2001-05-23 15:26:42 +02:00
break;
case nod_negate:
2001-07-12 07:46:06 +02:00
operatr = blr_negate;
2001-05-23 15:26:42 +02:00
break;
case nod_concatenate:
2001-07-12 07:46:06 +02:00
operatr = blr_concatenate;
2001-05-23 15:26:42 +02:00
break;
case nod_for:
2001-07-12 07:46:06 +02:00
operatr = blr_for;
2001-05-23 15:26:42 +02:00
break;
case nod_assignment:
2001-07-12 07:46:06 +02:00
operatr = blr_assignment;
2001-05-23 15:26:42 +02:00
break;
case nod_store:
2001-07-12 07:46:06 +02:00
operatr = blr_store;
2001-05-23 15:26:42 +02:00
break;
case nod_post:
2001-07-12 07:46:06 +02:00
operatr = blr_post;
2001-05-23 15:26:42 +02:00
break;
case nod_uppercase:
2001-07-12 07:46:06 +02:00
operatr = blr_upcase;
2001-05-23 15:26:42 +02:00
break;
case nod_sleuth:
2001-07-12 07:46:06 +02:00
operatr = blr_matching2;
2001-05-23 15:26:42 +02:00
break;
// case nod_substr:
// operatr = blr_substring;
// break;
2001-05-23 15:26:42 +02:00
default:
DDL_err(96, NULL, NULL, NULL, NULL, NULL);
// msg 96: GENERATE_blr: node not supported
2001-05-23 15:26:42 +02:00
return;
}
// If the user has given us something that has the form
//
// field {EQ} NULL
// {NE}
//
// transform it into
//
// field [NOT] MISSING
2001-05-23 15:26:42 +02:00
if ((operatr == blr_eql || operatr == blr_neq)
&& (node->nod_arg[posi]->nod_type == nod_null ||
node->nod_arg[posi + 1]->nod_type == nod_null))
{
2001-07-12 07:46:06 +02:00
if (operatr == blr_neq) {
check_blr(blr, 1);
blr->add_byte(blr_not);
2001-05-23 15:26:42 +02:00
}
2001-07-12 07:46:06 +02:00
operatr = blr_missing;
if (node->nod_arg[posi]->nod_type == nod_null)
posi++;
endi = posi + 1;
2001-05-23 15:26:42 +02:00
}
// Fall thru on reasonable stuff
2001-05-23 15:26:42 +02:00
check_blr(blr, 1);
blr->add_byte(operatr);
for (; posi < endi; posi++)
generate(blr, node->nod_arg[posi]);
2001-05-23 15:26:42 +02:00
}
static void get_set_generator( STR blr, DUDLEY_NOD node)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ s e t _ g e n e r a t o r
*
**************************************
*
* Functional description
* produce blr for set_generator. The
* mutable characteristics are the
* generator name and the increment.
* The rest is canned.
**************************************/
SCHAR *p;
SYM symbol;
static SCHAR gen_prologue[] = {
blr_begin, blr_message, 0, 1, 0, blr_long, 0,
blr_send, 0, blr_begin, blr_assignment, blr_gen_id,
};
static SCHAR gen_epilogue[] = {
blr_parameter, 0, 0, 0, blr_end, blr_end
};
int l;
CON constant;
SLONG value;
/* copy the beginning of the blr into the buffer */
l = sizeof(gen_prologue);
p = gen_prologue;
check_blr(blr, l);
2004-05-29 06:55:23 +02:00
do {
blr->add_byte(*p++);
2004-05-29 06:55:23 +02:00
} while (--l);
2001-05-23 15:26:42 +02:00
/* stuff in the name length and the name */
symbol = (SYM) node->nod_arg[1];
check_blr(blr, 1);
blr->add_byte(l = symbol->sym_length);
2001-05-23 15:26:42 +02:00
p = (SCHAR *) symbol->sym_string;
if (l) {
check_blr(blr, l);
2004-05-29 06:55:23 +02:00
do {
blr->add_byte(*p++);
2004-05-29 06:55:23 +02:00
} while (--l);
2001-05-23 15:26:42 +02:00
}
/* now for the increvent value */
check_blr(blr, 7);
blr->add_byte(blr_literal);
2001-05-23 15:26:42 +02:00
constant = (CON) node->nod_arg[0]->nod_arg[0];
blr->add_byte(blr_long);
blr->add_byte(constant->con_desc.dsc_scale);
2001-05-23 15:26:42 +02:00
p = (SCHAR *) constant->con_data;
value = *(SLONG *) p;
blr->add_word(value);
blr->add_word(value >> 16);
2001-05-23 15:26:42 +02:00
/* complete the string */
l = sizeof(gen_epilogue);
p = (SCHAR *) gen_epilogue;
check_blr(blr, l);
2004-05-29 06:55:23 +02:00
do {
blr->add_byte(*p++);
2004-05-29 06:55:23 +02:00
} while (--l);
2001-05-23 15:26:42 +02:00
}