8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 00:03:03 +01:00
firebird-mirror/src/dudley/parse.cpp

4144 lines
107 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD data definition language parser
2003-10-05 08:42:28 +02:00
* MODULE: parse.cpp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Statement parser
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
*
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include <stdlib.h>
#include <stdio.h> // a single call to sprintf()
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 "../jrd/flags.h"
#include "../dudley/ddl.h"
#include "../jrd/acl.h"
#include "../dudley/ddl_proto.h"
#include "../dudley/exe_proto.h"
#include "../dudley/expr_proto.h"
#include "../dudley/hsh_proto.h"
#include "../dudley/lex_proto.h"
#include "../dudley/parse_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/isc_f_proto.h"
2003-10-05 08:42:28 +02:00
const char* const PROMPT = "GDEF> ";
const char* const CONTINUATION = "CON> ";
const int GDS_NAME_LEN = 31;
2001-05-23 15:26:42 +02:00
const int MAX_DIMENSION = 16;
2003-03-09 03:25:58 +01:00
#ifdef FLINT_CACHE
const int MIN_CACHE_BUFFERS = 250;
const int DEF_CACHE_BUFFERS = 1000;
2003-03-09 03:25:58 +01:00
#endif
2001-05-23 15:26:42 +02:00
typedef enum {
obj_database,
obj_relation,
obj_view,
obj_field,
obj_index,
obj_security_class,
obj_trigger,
obj_file,
obj_none,
obj_function,
obj_type,
obj_filter,
obj_shadow,
obj_generator
2001-05-23 15:26:42 +02:00
} OBJ_T;
/* this table translates between the two types of types */
static TRG_T trig_table[] = {
trg_type_none,
trg_type_none,
trg_store,
trg_post_store,
trg_modify,
trg_post_modify,
trg_type_none,
trg_type_none,
trg_pre_erase,
trg_erase
};
2003-09-10 19:52:12 +02:00
static bool check_filename(SYM, bool);
2001-05-23 15:26:42 +02:00
static SYM copy_symbol(SYM);
static DUDLEY_FLD create_global_field(DUDLEY_FLD);
2003-03-09 03:25:58 +01:00
#ifdef FLINT_CACHE
2001-05-23 15:26:42 +02:00
static FIL define_cache(void);
2003-03-09 03:25:58 +01:00
#endif
2001-05-23 15:26:42 +02:00
static void define_database(enum act_t);
static void define_field(void);
static FIL define_file(void);
static void define_filter(void);
static void define_function(void);
static void define_generator(void);
static void define_index(void);
//static FIL define_log_file(USHORT);
2001-05-23 15:26:42 +02:00
static void define_old_trigger(void);
static void define_relation(void);
static void define_security_class(void);
static void define_shadow(void);
static void define_trigger(void);
2002-07-06 07:32:02 +02:00
static void define_type(void);
static void define_view(void);
2001-05-23 15:26:42 +02:00
static void drop_filter(void);
static void drop_function(void);
static void drop_gfield(void);
static void drop_index(void);
static void drop_relation(void);
static void drop_security_class(void);
static void drop_shadow(void);
static void drop_trigger(void);
static void drop_type(void);
static void end_text(TXT);
static SYM gen_trigger_name(TRG_T, DUDLEY_REL);
2001-05-23 15:26:42 +02:00
static int get_system_flag(void);
static void get_trigger_attributes(int *, int *, int *);
static void grant_user_privilege(void);
2004-02-02 12:02:12 +01:00
static DUDLEY_CTX lookup_context(SYM, dudley_lls*);
static DUDLEY_FLD lookup_global_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static ACT make_action(enum act_t, DBB);
static ACT make_computed_field(DUDLEY_FLD);
static DUDLEY_CTX make_context(TEXT *, DUDLEY_REL);
static ACT make_global_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static void mod_old_trigger(void);
static void modify_field(void);
static void modify_index(void);
static void modify_relation(void);
static void modify_security_class(void);
static void modify_trigger(void);
static void modify_trigger_action(DUDLEY_TRG, DUDLEY_REL);
2001-05-23 15:26:42 +02:00
static void modify_type(void);
static void modify_view(void);
2003-09-04 15:45:44 +02:00
static bool parse_action(void);
static void parse_array(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static TXT parse_description(void);
static void parse_end(void);
static DUDLEY_FLD parse_field(DUDLEY_FLD);
static void parse_field_clauses(DUDLEY_FLD);
static void parse_field_dtype(DUDLEY_FLD);
static void parse_field_subtype(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static FUNCARG parse_function_arg(FUNC, USHORT *);
static SCE parse_identifier(void);
static OBJ_T parse_object(void);
static int parse_page_size(void);
static SLONG parse_privileges(void);
static void revoke_user_privilege(void);
static SLONG score_entry(SCE);
static DUDLEY_NOD set_generator(void);
static void sort_out_attributes(DUDLEY_TRG, SLONG, SLONG, SLONG);
2001-05-23 15:26:42 +02:00
static TXT start_text(void);
static void validate_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
2004-02-02 12:02:12 +01:00
static dudley_lls* local_context;
2001-05-23 15:26:42 +02:00
void PARSE_actions(void)
{
/**************************************
*
* P A R S E_ a c t i o n s
*
**************************************
*
* Functional description
* Parse actions in a loop until end of file.
*
**************************************/
parse_action();
while (!dudleyGlob.DDL_eof && dudleyGlob.DDL_errors < 20) {
if ((!dudleyGlob.database || !dudleyGlob.database->dbb_handle) && (!dudleyGlob.DDL_drop_database)) {
2001-05-23 15:26:42 +02:00
DDL_err(111, NULL, NULL, NULL, NULL, NULL); /* msg 111: no database declared */
if (dudleyGlob.database) {
gds__free(dudleyGlob.database);
dudleyGlob.database = NULL;
2001-05-23 15:26:42 +02:00
}
if (dudleyGlob.DDL_interactive)
2001-05-23 15:26:42 +02:00
parse_action();
else {
DDL_err(112, NULL, NULL, NULL, NULL, NULL); /* msg 112: ceasing processing */
break;
}
}
else {
dudleyGlob.DDL_drop_database = false;
2001-05-23 15:26:42 +02:00
parse_action();
}
}
}
void PARSE_error( USHORT number, const TEXT* arg1, const TEXT* arg2)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P A R S E _ e r r o r
*
**************************************
*
* Functional description
* Generate a syntax error.
*
**************************************/
DDL_err(number, arg1, arg2, NULL, NULL, NULL);
Firebird::status_exception::raise();
2001-05-23 15:26:42 +02:00
}
FUNC PARSE_function(int existingFunction)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P A R S E _ f u n c t i o n
*
**************************************
*
* Functional description
* Get the function block associated with the current token. Also
* advance the token. Create a new function requested.
*
**************************************/
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(113, dudleyGlob.DDL_token.tok_string, 0); /* msg 113: expected function, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
SYM symbol = HSH_typed_lookup(dudleyGlob.DDL_token.tok_string, dudleyGlob.DDL_token.tok_length,
2001-05-23 15:26:42 +02:00
SYM_function);
FUNC function;
2001-05-23 15:26:42 +02:00
if (symbol && (function = (FUNC) symbol->sym_object) &&
function->func_database == dudleyGlob.database)
{
2001-05-23 15:26:42 +02:00
LEX_token();
return function;
}
if (existingFunction) {
PARSE_error(114, dudleyGlob.DDL_token.tok_string, 0); /* msg 114: expected function, encountered \"%s\" */
return NULL; // silence uninitialized warning
2001-05-23 15:26:42 +02:00
}
function = (FUNC) DDL_alloc(sizeof(func));
function->func_name = symbol = PARSE_symbol(tok_ident);
symbol->sym_type = SYM_function;
symbol->sym_object = (DUDLEY_CTX) function;
HSH_insert(symbol);
if (!(function->func_database = dudleyGlob.database))
PARSE_error(111, 0, 0); /* msg 111: no database declared */
2001-05-23 15:26:42 +02:00
return function;
}
enum kwwords PARSE_keyword(void)
{
/**************************************
*
* P A R S E _ k e y w o r d
*
**************************************
*
* Functional description
* Get a real token and return the keyword number.
*
**************************************/
LEX_real();
for (SYM symbol = dudleyGlob.DDL_token.tok_symbol; symbol; symbol = symbol->sym_homonym)
2001-05-23 15:26:42 +02:00
if (symbol->sym_type == SYM_keyword)
return (enum kwwords) symbol->sym_keyword;
return KW_none;
}
2004-02-02 12:02:12 +01:00
DUDLEY_NOD PARSE_make_list(dudley_lls* stack)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P A R S E _ m a k e _ l i s t
*
**************************************
*
* Functional description
* Dump a stack of junk into a list node. Best count
* them first.
*
**************************************/
dudley_lls* temp = stack;
USHORT count = 0;
2001-05-23 15:26:42 +02:00
while (temp) {
count++;
temp = temp->lls_next;
}
DUDLEY_NOD node = PARSE_make_node(nod_list, count);
2001-05-23 15:26:42 +02:00
while (stack)
node->nod_arg[--count] = LLS_POP(&stack);
2001-05-23 15:26:42 +02:00
return node;
}
DUDLEY_NOD PARSE_make_node(enum nod_t type, USHORT count)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P A R S E _ m a k e _ n o d e
*
**************************************
*
* Functional description
* Allocate and initialize a syntax node of given type.
*
**************************************/
DUDLEY_NOD node = (DUDLEY_NOD) DDL_alloc(NOD_LEN(count));
2001-05-23 15:26:42 +02:00
node->nod_type = type;
node->nod_count = count;
return node;
}
2003-09-10 19:52:12 +02:00
bool PARSE_match( enum kwwords keyword)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P A R S E _ m a t c h
*
**************************************
*
* Functional description
* Test the current token for a particular keyword. If so, advanced
* the token stream.
*
**************************************/
if (dudleyGlob.DDL_token.tok_keyword == keyword) {
2001-05-23 15:26:42 +02:00
LEX_token();
2003-09-10 19:52:12 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
for (SYM symbol = dudleyGlob.DDL_token.tok_symbol; symbol; symbol = symbol->sym_homonym)
2001-05-23 15:26:42 +02:00
if (symbol->sym_type == SYM_keyword &&
symbol->sym_keyword == (int) keyword)
{
2001-05-23 15:26:42 +02:00
LEX_token();
2003-09-10 19:52:12 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
2003-09-10 19:52:12 +02:00
return false;
2001-05-23 15:26:42 +02:00
}
int PARSE_number(void)
{
/**************************************
*
* P A R S E _ n u m b e r
*
**************************************
*
* Functional description
* Parse the next token as a number and return its value.
*
**************************************/
const bool negate = PARSE_match(KW_MINUS);
2001-05-23 15:26:42 +02:00
if (dudleyGlob.DDL_token.tok_type != tok_number)
PARSE_error(115, dudleyGlob.DDL_token.tok_string, 0); /* msg 115: expected number, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
const int number = atoi(dudleyGlob.DDL_token.tok_string);
2001-05-23 15:26:42 +02:00
LEX_token();
if (negate)
return -number;
return number;
}
DUDLEY_REL PARSE_relation(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* P A R S E _ r e l a t i o n
*
**************************************
*
* Functional description
* Get the relation block associated with the current token.
* If the relatio was defined before, use the old definition.
* If not, create a new one. Somebody else will decide whether
* this one is worth keeping.
*
**************************************/
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(116, dudleyGlob.DDL_token.tok_string, 0); /* msg 116: expected relation name, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
SYM symbol = HSH_typed_lookup(dudleyGlob.DDL_token.tok_string, dudleyGlob.DDL_token.tok_length,
2001-05-23 15:26:42 +02:00
SYM_relation);
DUDLEY_REL relation;
if (symbol && (relation = (DUDLEY_REL) symbol->sym_object) &&
relation->rel_database == dudleyGlob.database)
{
2001-05-23 15:26:42 +02:00
LEX_token();
return relation;
}
2003-09-30 12:39:11 +02:00
relation = (DUDLEY_REL) DDL_alloc(sizeof(dudley_rel));
2001-05-23 15:26:42 +02:00
relation->rel_name = symbol = PARSE_symbol(tok_ident);
symbol->sym_type = SYM_relation;
symbol->sym_object = (DUDLEY_CTX) relation;
2001-05-23 15:26:42 +02:00
if (!(relation->rel_database = dudleyGlob.database))
2001-05-23 15:26:42 +02:00
PARSE_error(111, 0, 0); /* msg 111: no database declared */
relation->rel_next = dudleyGlob.database->dbb_relations;
dudleyGlob.database->dbb_relations = relation;
2001-05-23 15:26:42 +02:00
return relation;
}
SYM PARSE_symbol(enum tok_t type)
{
/**************************************
*
* P A R S E _ s y m b o l
*
**************************************
*
* Functional description
* Swallow the current token as a symbol.
*
**************************************/
if (dudleyGlob.DDL_token.tok_type != type)
2001-05-23 15:26:42 +02:00
switch (type) {
case tok_ident:
PARSE_error(117, dudleyGlob.DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
case tok_quoted:
PARSE_error(118, dudleyGlob.DDL_token.tok_string, 0); /* msg 118: expected quoted string, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
default:
PARSE_error(119, dudleyGlob.DDL_token.tok_string, 0); /* msg 119: expected symbol, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
}
USHORT l = dudleyGlob.DDL_token.tok_length;
const TEXT* q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
if (type == tok_quoted) {
if (l < 2)
PARSE_error(118, dudleyGlob.DDL_token.tok_string, 0); /* msg 118: expected quoted string, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
q++;
l -= 2;
}
SYM symbol = (SYM) DDL_alloc(SYM_LEN + l);
2001-05-23 15:26:42 +02:00
symbol->sym_length = l;
symbol->sym_string = symbol->sym_name;
TEXT* p = symbol->sym_name;
2001-05-23 15:26:42 +02:00
if (l)
if (type == tok_ident)
do {
const TEXT c = *q++;
2001-05-23 15:26:42 +02:00
*p++ = UPPER(c);
} while (--l);
2001-05-23 15:26:42 +02:00
else
do {
2001-05-23 15:26:42 +02:00
*p++ = *q++;
} while (--l);
2001-05-23 15:26:42 +02:00
LEX_token();
return symbol;
}
2003-09-10 19:52:12 +02:00
static bool check_filename(SYM name,
bool decnet_flag)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c h e c k _ f i l e n a m e
*
**************************************
*
* Functional description
* Make sure that a file path doesn't contain an
* inet node name.
*
**************************************/
TEXT file_name[256];
2001-05-23 15:26:42 +02:00
USHORT l = name->sym_length;
if (!l)
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
l = MIN(l, sizeof(file_name) - 1);
TEXT* pp = file_name;
for (const TEXT* q = name->sym_string; l--; *pp++ = *q++);
*pp = 0;
2001-05-23 15:26:42 +02:00
for (const TEXT* p = file_name; *p; p++)
2001-05-23 15:26:42 +02:00
if (p[0] == ':' && p[1] == ':')
if (!decnet_flag)
2003-09-04 15:45:44 +02:00
return false;
2001-05-23 15:26:42 +02:00
else {
for (p = file_name; *p;)
if (*p++ == '^')
2003-09-04 15:45:44 +02:00
return false;
return true;
2001-05-23 15:26:42 +02:00
}
return (!ISC_check_if_remote(file_name, false));
2001-05-23 15:26:42 +02:00
}
static SYM copy_symbol( SYM old_name)
{
/**************************************
*
* c o p y _ s y m b o l
*
**************************************
*
* Functional description
* Create a new symbol block for
* the same symbol as an existing block.
* This seems dumber than it is, because
* the implicit creation of global fields
* from local definitions depends on it as
* does the implicit invocation of same-named
* global fields.
*
* We'll just leave the type blank for now.
*
**************************************/
SYM new_name = (SYM) DDL_alloc(SYM_LEN + old_name->sym_length);
2001-05-23 15:26:42 +02:00
new_name->sym_length = old_name->sym_length;
new_name->sym_string = new_name->sym_name;
strcpy(new_name->sym_name, old_name->sym_name);
return new_name;
}
static DUDLEY_FLD create_global_field( DUDLEY_FLD local_field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c r e a t e _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
* Copy a field block so we can
* have separate blocks for global
* and local fields, even when the
* global field is defined implicitly.
*
* This creates a new field and symbol
* block.
*
**************************************/
DUDLEY_FLD global_field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
global_field->fld_dtype = local_field->fld_dtype;
global_field->fld_length = local_field->fld_length;
global_field->fld_scale = local_field->fld_scale;
global_field->fld_segment_length = local_field->fld_segment_length;
global_field->fld_sub_type = local_field->fld_sub_type;
global_field->fld_has_sub_type = local_field->fld_has_sub_type;
global_field->fld_dimension = local_field->fld_dimension;
global_field->fld_system = local_field->fld_system;
global_field->fld_database = local_field->fld_database;
global_field->fld_query_name = local_field->fld_query_name;
global_field->fld_query_header = local_field->fld_query_header;
global_field->fld_edit_string = local_field->fld_edit_string;
global_field->fld_computed = local_field->fld_computed;
global_field->fld_missing = local_field->fld_missing;
global_field->fld_default = local_field->fld_default;
global_field->fld_validation = local_field->fld_validation;
global_field->fld_description = local_field->fld_description;
global_field->fld_compute_src = local_field->fld_compute_src;
global_field->fld_valid_src = local_field->fld_valid_src;
global_field->fld_ranges = local_field->fld_ranges;
if (local_field->fld_source)
global_field->fld_name = local_field->fld_source;
else {
SYM old_name = local_field->fld_name;
SYM new_name = copy_symbol(old_name);
global_field->fld_name = new_name;
2001-05-23 15:26:42 +02:00
new_name->sym_type = SYM_global;
new_name->sym_object = (DUDLEY_CTX) global_field;
2001-05-23 15:26:42 +02:00
local_field->fld_source = new_name;
}
global_field->fld_flags = local_field->fld_flags & ~fld_local;
local_field->fld_source_field = global_field;
local_field->fld_flags |= fld_local;
return global_field;
}
2003-03-09 03:25:58 +01:00
#ifdef FLINT_CACHE
2001-05-23 15:26:42 +02:00
static FIL define_cache(void)
{
/**************************************
*
* d e f i n e _ c a c h e
*
**************************************
*
* Functional description
* Add a shared cache to an existing database.
*
**************************************/
FIL file = (FIL) DDL_alloc(sizeof(fil));
2001-05-23 15:26:42 +02:00
file->fil_name = PARSE_symbol(tok_quoted);
2003-09-10 19:52:12 +02:00
if (!check_filename(file->fil_name, false))
2001-05-23 15:26:42 +02:00
PARSE_error(322, 0, 0); /* msg 322: a node name is not permitted in a shared cache file name */
if (PARSE_match(KW_LENGTH)) {
2001-05-23 15:26:42 +02:00
if ((file->fil_length = PARSE_number()) < MIN_CACHE_BUFFERS)
PARSE_error(339, (TEXT *) MIN_CACHE_BUFFERS, 0); /* msg 339: minimum of %d cache pages required */
PARSE_match(KW_PAGES);
2001-05-23 15:26:42 +02:00
}
else
file->fil_length = DEF_CACHE_BUFFERS; /* default cache buffers */
return file;
}
2003-03-09 03:25:58 +01:00
#endif
2001-05-23 15:26:42 +02:00
static void define_database( enum act_t action_type)
{
/**************************************
*
* d e f i n e _ d a t a b a s e
*
**************************************
*
* Functional description
* Parse the tail of a DEFINE, MODIFY, or DELETE DATABASE statement.
*
**************************************/
if (dudleyGlob.database)
DDL_error_abort(0, 120, NULL, NULL, NULL, NULL, NULL);
// msg 120: GDEF processes only one database at a time
2001-05-23 15:26:42 +02:00
dudleyGlob.database = (DBB) DDL_alloc(sizeof(dbb));
dudleyGlob.database->dbb_name = PARSE_symbol(tok_quoted);
dudleyGlob.DB_file_name = dudleyGlob.database->dbb_name->sym_name;
dudleyGlob.database->dbb_grp_cmt_wait = -1; /* Initialized for default value */
2001-05-23 15:26:42 +02:00
/* parse options for the database parameter block */
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_LENGTH)) {
dudleyGlob.database->dbb_length = PARSE_number();
PARSE_match(KW_PAGES);
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_USER)) {
SYM symbol = PARSE_symbol(tok_quoted);
dudleyGlob.DDL_default_user = symbol->sym_name;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_PASSWORD)) {
SYM symbol = PARSE_symbol(tok_quoted);
dudleyGlob.DDL_default_password = symbol->sym_name;
2001-05-23 15:26:42 +02:00
}
else
break;
}
if (action_type == act_d_database) {
// if (PARSE_match(KW_CASCADE))
// dudleyGlob.database->dbb_flags |= DBB_cascade;
EXE_drop_database(dudleyGlob.database);
dudleyGlob.DDL_drop_database = true;
2001-05-23 15:26:42 +02:00
return;
}
/* parse add/drop items */
2003-09-10 19:52:12 +02:00
while (true) {
PARSE_match(KW_ADD);
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
dudleyGlob.database->dbb_description = parse_description();
else if (PARSE_match(KW_SECURITY_CLASS))
dudleyGlob.database->dbb_security_class = PARSE_symbol(tok_ident);
else if (PARSE_match(KW_DROP)) {
if (PARSE_match(KW_DESCRIP))
dudleyGlob.database->dbb_flags |= DBB_null_description;
else if (PARSE_match(KW_SECURITY_CLASS))
dudleyGlob.database->dbb_flags |= DBB_null_security_class;
/*
else if (PARSE_match(KW_LOG_FILE)) {
if ((dudleyGlob.database->dbb_flags & DBB_log_default)
|| (dudleyGlob.database->dbb_logfiles))
{
PARSE_error(337, 0, 0);
}
2001-05-23 15:26:42 +02:00
dudleyGlob.database->dbb_flags |= DBB_drop_log;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_CASCADE))
dudleyGlob.database->dbb_flags |= DBB_cascade;
2001-05-23 15:26:42 +02:00
#ifdef FLINT_CACHE
else if (PARSE_match(KW_CACHE))
dudleyGlob.database->dbb_flags |= DBB_drop_cache;
#endif // FLINT_CACHE
*/
2001-05-23 15:26:42 +02:00
else
PARSE_error(121, 0, 0);
// msg 121 only SECURITY_CLASS, DESCRIPTION and CACHE can be dropped
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_FILE)) {
FIL file = define_file();
file->fil_next = dudleyGlob.database->dbb_files;
dudleyGlob.database->dbb_files = file;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_PAGE_SIZE)) {
2001-05-23 15:26:42 +02:00
if (action_type == act_m_database)
PARSE_error(122, 0, 0); /* msg 122: PAGE_SIZE can not be modified */
dudleyGlob.database->dbb_page_size = parse_page_size();
2001-05-23 15:26:42 +02:00
}
/*
else if (PARSE_match(KW_CHECK_POINT_LEN)) {
PARSE_match(KW_EQUALS);
dudleyGlob.database->dbb_chkptlen = PARSE_number();
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_NUM_LOG_BUFS)) {
PARSE_match(KW_EQUALS);
dudleyGlob.database->dbb_numbufs = PARSE_number();
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_LOG_BUF_SIZE)) {
PARSE_match(KW_EQUALS);
dudleyGlob.database->dbb_bufsize = PARSE_number();
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_GROUP_COMMIT_WAIT)) {
PARSE_match(KW_EQUALS);
dudleyGlob.database->dbb_grp_cmt_wait = PARSE_number();
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_LOG_FILE)) {
if ((dudleyGlob.database->dbb_flags & DBB_log_default)
|| (dudleyGlob.database->dbb_logfiles))
{
PARSE_error(338, 0, 0);
}
2001-05-23 15:26:42 +02:00
if (dudleyGlob.database->dbb_flags & DBB_drop_log)
2001-05-23 15:26:42 +02:00
PARSE_error(337, 0, 0);
if (PARSE_match(KW_LEFT_PAREN)) {
dudleyGlob.database->dbb_flags |= DBB_log_preallocated;
2003-09-10 19:52:12 +02:00
while (true) {
FIL file = define_log_file(DBB_log_preallocated);
file->fil_next = dudleyGlob.database->dbb_logfiles;
dudleyGlob.database->dbb_logfiles = file;
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
if (!PARSE_match(KW_RIGHT_PAREN))
{
PARSE_error(341, dudleyGlob.DDL_token.tok_string, 0);
// msg 341: expected comma or ')', encountered \"%s\"
}
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_OVERFLOW))
dudleyGlob.database->dbb_overflow = define_log_file(DBB_log_serial);
2001-05-23 15:26:42 +02:00
else
PARSE_error(340, 0, 0);
}
else if (PARSE_match(KW_BASE_NAME)) {
dudleyGlob.database->dbb_flags |= DBB_log_serial;
dudleyGlob.database->dbb_logfiles = define_log_file(DBB_log_serial);
2001-05-23 15:26:42 +02:00
}
else
dudleyGlob.database->dbb_flags |= DBB_log_default;
2001-05-23 15:26:42 +02:00
}
#ifdef FLINT_CACHE
else if (PARSE_match(KW_CACHE))
dudleyGlob.database->dbb_cache_file = define_cache();
#endif // FLINT_CACHE
*/
2001-05-23 15:26:42 +02:00
else
break;
}
parse_end();
if (action_type == act_c_database) {
dudleyGlob.database->dbb_flags |= DBB_create_database;
EXE_create_database(dudleyGlob.database);
2001-05-23 15:26:42 +02:00
}
else {
EXE_modify_database(dudleyGlob.database);
2001-05-23 15:26:42 +02:00
}
make_action(action_type, dudleyGlob.database);
2001-05-23 15:26:42 +02:00
}
static void define_field(void)
{
/**************************************
*
* d e f i n e _ f i e l d
*
**************************************
*
* Functional description
* Parse a DEFINE FIELD statement.
*
**************************************/
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
parse_field(field);
field->fld_database = dudleyGlob.database;
2001-05-23 15:26:42 +02:00
if (!field->fld_dtype)
PARSE_error(123, 0, 0); /* msg 123: data type required for global field */
if (field->fld_security_class)
PARSE_error(124, 0, 0); /* msg 124: Security class can appear only on local field references */
parse_end();
make_global_field(field);
}
static FIL define_file(void)
{
/**************************************
*
* d e f i n e _ f i l e
*
**************************************
*
* Functional description
* Add a new file to an existing database.
*
**************************************/
FIL file = (FIL) DDL_alloc(sizeof(fil));
2001-05-23 15:26:42 +02:00
file->fil_name = PARSE_symbol(tok_quoted);
2003-09-10 19:52:12 +02:00
if (!check_filename(file->fil_name, false))
2001-05-23 15:26:42 +02:00
PARSE_error(297, 0, 0); /* msg 297: A node name is not permitted in a shadow or secondary file name */
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_LENGTH)) {
2001-05-23 15:26:42 +02:00
file->fil_length = PARSE_number();
PARSE_match(KW_PAGES);
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_STARTS)) {
PARSE_match(KW_AT);
PARSE_match(KW_PAGE);
2001-05-23 15:26:42 +02:00
file->fil_start = PARSE_number();
}
else
break;
}
return file;
}
static void define_filter(void)
{
/**************************************
*
* d e f i n e _ f i l t e r
*
**************************************
*
* Functional description
* Parse a DEFINE FILTER statement.
*
**************************************/
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(126, dudleyGlob.DDL_token.tok_string, 0); /* msg 126: expected filter name, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
FILTER new_filter = (FILTER) DDL_alloc(sizeof(filter));
2003-09-30 12:39:11 +02:00
new_filter->filter_name = PARSE_symbol(tok_ident);
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2003-09-30 12:39:11 +02:00
new_filter->filter_description = parse_description();
else if (PARSE_match(KW_INPUT_TYPE))
2003-09-30 12:39:11 +02:00
new_filter->filter_input_sub_type = PARSE_number();
else if (PARSE_match(KW_OUTPUT_TYPE))
2003-09-30 12:39:11 +02:00
new_filter->filter_output_sub_type = PARSE_number();
else if (PARSE_match(KW_FUNCTION_MODULE_NAME))
2003-09-30 12:39:11 +02:00
new_filter->filter_module_name = PARSE_symbol(tok_quoted);
else if (PARSE_match(KW_FUNCTION_ENTRY_POINT))
2003-09-30 12:39:11 +02:00
new_filter->filter_entry_point = PARSE_symbol(tok_quoted);
2001-05-23 15:26:42 +02:00
else
break;
}
2003-09-30 12:39:11 +02:00
if (!new_filter->filter_entry_point)
2001-05-23 15:26:42 +02:00
PARSE_error(127, 0, 0); /* msg 127: Filter entry point must be specified */
#if (defined WIN_NT)
2003-09-30 12:39:11 +02:00
if (!new_filter->filter_module_name)
2001-05-23 15:26:42 +02:00
PARSE_error(128, 0, 0); /* msg 128: Filter module name must be specified */
#endif
parse_end();
2003-09-30 12:39:11 +02:00
make_action(act_a_filter, (DBB) new_filter);
2001-05-23 15:26:42 +02:00
}
static void define_function(void)
{
/**************************************
*
* d e f i n e _ f u n c t i o n
*
**************************************
*
* Functional description
* Parse a DEFINE FUNCTION statement.
*
**************************************/
FUNC function = PARSE_function(FALSE);
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
function->func_description = parse_description();
else if (PARSE_match(KW_FUNCTION_MODULE_NAME))
2001-05-23 15:26:42 +02:00
function->func_module_name = PARSE_symbol(tok_quoted);
else if (PARSE_match(KW_FUNCTION_ENTRY_POINT))
2001-05-23 15:26:42 +02:00
function->func_entry_point = PARSE_symbol(tok_quoted);
else if (PARSE_match(KW_QUERY_NAME))
2001-05-23 15:26:42 +02:00
function->func_query_name = PARSE_symbol(tok_ident);
else
break;
}
if (!function->func_entry_point)
PARSE_error(130, 0, 0); /* msg 130: Function entry point must be specified */
#if (defined WIN_NT)
2001-05-23 15:26:42 +02:00
if (!function->func_module_name)
PARSE_error(131, 0, 0); /* msg 131: Function module name must be specified */
#endif
/* Gobble function arguments */
SSHORT position = 1;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (dudleyGlob.DDL_token.tok_keyword == KW_SEMI)
2001-05-23 15:26:42 +02:00
break;
FUNCARG function_arg = parse_function_arg(function, (USHORT*) &position);
2001-05-23 15:26:42 +02:00
function_arg->funcarg_funcname = function->func_name;
2001-07-12 07:46:06 +02:00
make_action(act_a_function_arg, (DBB) function_arg);
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
if (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
PARSE_error(132, dudleyGlob.DDL_token.tok_string, 0); /* msg 132: expected comma or semi-colon, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
2001-07-12 07:46:06 +02:00
make_action(act_a_function, (DBB) function);
2001-05-23 15:26:42 +02:00
}
static void define_generator(void)
{
/**************************************
*
* d e f i n e _ g e n e r a t o r
*
**************************************
*
* Functional description
* Parse a DEFINE GENERATOR statement.
*
**************************************/
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(274, dudleyGlob.DDL_token.tok_string, 0); /* msg 274: expected generator name, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
SYM symbol = PARSE_symbol(tok_ident);
2001-05-23 15:26:42 +02:00
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_a_generator, (DBB) symbol);
2001-05-23 15:26:42 +02:00
}
static void define_index(void)
{
/**************************************
*
* d e f i n e _ i n d e x
*
**************************************
*
* Functional description
* Define a new index.
*
**************************************/
2003-09-10 19:52:12 +02:00
TXT description = NULL;
bool unique = false;
bool inactive = false;
2003-09-15 04:15:27 +02:00
idx_direction descending = IDX_type_none;
2001-05-23 15:26:42 +02:00
SYM index_name = PARSE_symbol(tok_ident);
PARSE_match(KW_FOR);
SYM rel_name = PARSE_symbol(tok_ident);
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_DUPLICATES))
2003-09-10 19:52:12 +02:00
unique = false;
else if (PARSE_match(KW_UNIQUE))
2003-09-10 19:52:12 +02:00
unique = true;
else if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
description = parse_description();
else if (PARSE_match(KW_ACTIVE))
2003-09-10 19:52:12 +02:00
inactive = false;
else if (PARSE_match(KW_INACTIVE))
2003-09-10 19:52:12 +02:00
inactive = true;
else if (PARSE_match(KW_ASCENDING))
2003-09-15 04:15:27 +02:00
descending = IDX_type_none;
else if (PARSE_match(KW_DESCENDING))
2003-09-15 04:15:27 +02:00
descending = IDX_type_descend;
2001-05-23 15:26:42 +02:00
else
break;
}
SSHORT count = 0;
2001-05-23 15:26:42 +02:00
dudley_lls* stack = NULL;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
LLS_PUSH((DUDLEY_NOD) PARSE_symbol(tok_ident), &stack);
2001-05-23 15:26:42 +02:00
count++;
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
if (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
PARSE_error(135, dudleyGlob.DDL_token.tok_string, 0);
// msg 135: expected comma or semi-colon, encountered \"%s\"
2003-08-12 12:02:27 +02:00
DUDLEY_IDX index = (DUDLEY_IDX) DDL_alloc(IDX_LEN(count == 0 ? 1 : count));
2001-05-23 15:26:42 +02:00
index->idx_count = count;
index->idx_name = index_name;
index->idx_relation = rel_name;
index->idx_unique = unique;
index->idx_description = description;
index->idx_inactive = inactive;
2003-09-15 04:15:27 +02:00
index->idx_type = descending;
2001-05-23 15:26:42 +02:00
while (stack)
index->idx_field[--count] = (SYM) LLS_POP(&stack);
2001-05-23 15:26:42 +02:00
2001-07-12 07:46:06 +02:00
make_action(act_a_index, (DBB) index);
2001-05-23 15:26:42 +02:00
}
/*
2001-05-23 15:26:42 +02:00
static FIL define_log_file( USHORT log_type)
{
// **************************************
// *
// * d e f i n e _ l o g _ f i l e
// *
// **************************************
// *
// * Functional description
// * define a log file
// *
// **************************************
FIL file = (FIL) DDL_alloc(sizeof(fil));
2001-05-23 15:26:42 +02:00
file->fil_name = PARSE_symbol(tok_quoted);
2003-09-10 19:52:12 +02:00
if (!check_filename(file->fil_name, false))
PARSE_error(297, 0, 0);
// msg 297: A node name is not permitted in a shadow or secondary file name
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_SIZE)) {
PARSE_match(KW_EQUALS);
2001-05-23 15:26:42 +02:00
file->fil_length = PARSE_number();
}
else if (PARSE_match(KW_RAW_PARTITIONS)) {
2001-05-23 15:26:42 +02:00
if (log_type != DBB_log_preallocated)
PARSE_error(332, 0, 0);
// msg 332: Partitions not supported in series of log file specification
PARSE_match(KW_EQUALS);
2001-05-23 15:26:42 +02:00
file->fil_partitions = PARSE_number();
file->fil_raw = LOG_raw;
}
else
break;
}
// Check for the specified length of the log file
2001-05-23 15:26:42 +02:00
if (file->fil_partitions) {
if (!file->fil_length)
PARSE_error(335, file->fil_name->sym_string, 0);
// msg 335: Total length of the partitioned log <logname> must be specified
2001-05-23 15:26:42 +02:00
}
return file;
}
*/
2001-05-23 15:26:42 +02:00
static void define_old_trigger(void)
{
/**************************************
*
* d e f i n e _ o l d _ t r i g g e r
*
**************************************
*
* Functional description
* Parse old style trigger definition
*
**************************************/
SYM name = NULL;
DUDLEY_TRG trigger = NULL;
DUDLEY_REL relation = PARSE_relation();
2001-05-23 15:26:42 +02:00
while (!PARSE_match(KW_END_TRIGGER)) {
2003-09-30 12:39:11 +02:00
trigger = (DUDLEY_TRG) DDL_alloc(sizeof(dudley_trg));
2001-05-23 15:26:42 +02:00
trigger->trg_relation = relation;
if (PARSE_match(KW_STORE))
2001-05-23 15:26:42 +02:00
trigger->trg_type = trg_store;
else if (PARSE_match(KW_MODIFY))
2001-05-23 15:26:42 +02:00
trigger->trg_type = trg_modify;
else if (PARSE_match(KW_ERASE))
2001-05-23 15:26:42 +02:00
trigger->trg_type = trg_erase;
else
PARSE_error(136, dudleyGlob.DDL_token.tok_string, 0);
// msg 136: expected STORE, MODIFY, ERASE, END_TRIGGER, encountered \"%s\"
PARSE_match(KW_COLON);
2001-05-23 15:26:42 +02:00
name = gen_trigger_name(trigger->trg_type, relation);
trigger->trg_name = name;
trigger->trg_source = start_text();
trigger->trg_statement = EXPR_statement();
end_text(trigger->trg_source);
2001-07-12 07:46:06 +02:00
make_action(act_a_trigger, (DBB) trigger);
2001-05-23 15:26:42 +02:00
}
parse_end();
if (trigger) {
name->sym_type = SYM_trigger;
name->sym_object = (DUDLEY_CTX) trigger;
2001-05-23 15:26:42 +02:00
HSH_insert(name);
}
}
static void define_relation(void)
{
/**************************************
*
* d e f i n e _ r e l a t i o n
*
**************************************
*
* Functional description
* Parse a DEFINE RELATION statement.
*
**************************************/
DUDLEY_REL relation = PARSE_relation();
2001-05-23 15:26:42 +02:00
if (!(relation->rel_flags & rel_marked_for_delete) &&
((relation->rel_flags & rel_marked_for_creation)
2003-09-10 19:52:12 +02:00
|| EXE_relation(relation)))
{
PARSE_error(137, relation->rel_name->sym_string, 0);
// msg 137: relation %s already exists
}
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_EXTERNAL_FILE)) {
2001-05-23 15:26:42 +02:00
relation->rel_filename = PARSE_symbol(tok_quoted);
2003-09-10 19:52:12 +02:00
if (!check_filename(relation->rel_filename, true))
PARSE_error(298, 0, 0);
// msg 298: A non-Decnet node name is not permitted in an external file name
2001-05-23 15:26:42 +02:00
}
ACT action = make_action(act_a_relation, (DBB) relation);
ACT rel_actions = action;
2001-05-23 15:26:42 +02:00
action->act_flags |= ACT_ignore;
SSHORT position = 1;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true)
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
relation->rel_description = parse_description();
else if (PARSE_match(KW_SECURITY_CLASS))
2001-05-23 15:26:42 +02:00
relation->rel_security_class = PARSE_symbol(tok_ident);
else if (PARSE_match(KW_SYSTEM_FLAG)) {
2001-05-23 15:26:42 +02:00
relation->rel_system = get_system_flag();
relation->rel_flags |= rel_explicit_system;
}
else
break;
/* Gobble fields */
DUDLEY_FLD global;
2003-09-10 19:52:12 +02:00
while (true) {
PARSE_match(KW_ADD);
PARSE_match(KW_FIELD);
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
parse_field(field);
field->fld_relation = relation;
field->fld_database = dudleyGlob.database;
2001-05-23 15:26:42 +02:00
if (field->fld_computed)
make_computed_field(field);
else if (!(field->fld_flags & fld_local))
make_global_field(create_global_field(field));
else if (global = lookup_global_field(field)) {
field->fld_dtype = global->fld_dtype;
field->fld_length = global->fld_length;
field->fld_scale = global->fld_scale;
field->fld_segment_length = global->fld_segment_length;
field->fld_sub_type = global->fld_sub_type;
field->fld_has_sub_type = global->fld_has_sub_type;
}
if (field->fld_flags & fld_explicit_position)
position = field->fld_position + 1;
else
field->fld_position = position++;
field->fld_flags |= fld_explicit_position;
field->fld_name->sym_type = SYM_field;
HSH_insert(field->fld_name);
2001-07-12 07:46:06 +02:00
action = make_action(act_a_field, (DBB) field);
2001-05-23 15:26:42 +02:00
action->act_flags |= ACT_ignore;
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
if (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
PARSE_error(138, dudleyGlob.DDL_token.tok_string, 0);
// msg 138: expected comma or semi-colon, encountered \"%s\"
2001-05-23 15:26:42 +02:00
// We started off by assuming that the relation and field actions that
// have been defined would have to be ignored. Everything has gone well so
// turn them on.
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
2001-05-23 15:26:42 +02:00
action->act_flags &= ~ACT_ignore;
if (action == rel_actions)
break;
action = action->act_next;
}
HSH_insert(relation->rel_name);
relation->rel_flags &= ~rel_marked_for_delete;
relation->rel_flags |= rel_marked_for_creation;
}
static void define_security_class(void)
{
/**************************************
*
* d e f i n e _ s e c u r i t y _ c l a s s
*
**************************************
*
* Functional description
* Parse an access control list.
*
**************************************/
SCL sec_class = (SCL) DDL_alloc(sizeof(scl));
sec_class->scl_name = PARSE_symbol(tok_ident);
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
sec_class->scl_description = parse_description();
2001-05-23 15:26:42 +02:00
/* Pick up entries. Use the users's order */
2003-09-10 19:52:12 +02:00
while (true) {
SCE element = parse_identifier();
if (!element)
2001-05-23 15:26:42 +02:00
return;
SCE* next;
for (next = &sec_class->scl_entries; *next; next = &(*next)->sce_next);
2001-05-23 15:26:42 +02:00
*next = element;
element->sce_privileges = parse_privileges();
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
parse_end();
make_action(act_a_security, (DBB) sec_class);
2001-05-23 15:26:42 +02:00
}
static void define_shadow(void)
{
/**************************************
*
* d e f i n e _ s h a d o w
*
**************************************
*
* Functional description
* Define a shadow file to the database.
* Parse it as a set of normal file additions,
* setting the shadow number on all files.
*
**************************************/
FIL shadow = (FIL) DDL_alloc(sizeof(fil));
2001-05-23 15:26:42 +02:00
/* get the shadow number, defaulting to 1 */
int number;
if (dudleyGlob.DDL_token.tok_type != tok_number)
2001-05-23 15:26:42 +02:00
number = 1;
else {
number = PARSE_number();
if (number < 1)
PARSE_error(139, 0, 0); /* msg 139: shadow number must be a positive integer */
}
/* match the keywords MANUAL or AUTO to imply whether the shadow
should be automatically deleted when something goes awry */
if (PARSE_match(KW_MANUAL))
2001-05-23 15:26:42 +02:00
shadow->fil_manual = 1;
else
PARSE_match(KW_AUTO);
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_CONDITIONAL))
2001-05-23 15:26:42 +02:00
shadow->fil_conditional = 1;
shadow->fil_name = PARSE_symbol(tok_quoted);
2003-09-10 19:52:12 +02:00
if (!check_filename(shadow->fil_name, false))
PARSE_error(297, 0, 0);
// msg 297: A node name is not permitted in a shadow or secondary file name
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_LENGTH)) {
2001-05-23 15:26:42 +02:00
shadow->fil_length = PARSE_number();
PARSE_match(KW_PAGES);
2001-05-23 15:26:42 +02:00
}
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_FILE)) {
FIL file = define_file();
2001-05-23 15:26:42 +02:00
file->fil_next = shadow;
shadow = file;
}
else
break;
}
parse_end();
for (FIL file = shadow; file; file = file->fil_next)
2001-05-23 15:26:42 +02:00
file->fil_shadow_number = number;
2001-07-12 07:46:06 +02:00
make_action(act_a_shadow, (DBB) shadow);
2001-05-23 15:26:42 +02:00
}
static void define_trigger(void)
{
/**************************************
*
* d e f i n e _ t r i g g e r
*
**************************************
*
* Functional description
* Parse new trigger definition
* syntax, being a little loose about
* what comes when.
*
**************************************/
if (PARSE_match(KW_FOR)) {
2001-05-23 15:26:42 +02:00
define_old_trigger();
return;
}
DUDLEY_TRG trigger = (DUDLEY_TRG) DDL_alloc(sizeof(dudley_trg));
2001-05-23 15:26:42 +02:00
trigger->trg_name = PARSE_symbol(tok_ident);
PARSE_match(KW_FOR);
2001-05-23 15:26:42 +02:00
trigger->trg_relation = PARSE_relation();
int flags = 0, trg_state = 0, trg_sequence = 0;
2001-05-23 15:26:42 +02:00
get_trigger_attributes(&flags, &trg_state, &trg_sequence);
trigger->trg_type = trig_table[trg_state & ~trig_inact];
trigger->trg_inactive = (trg_state & trig_inact);
trigger->trg_sequence = trg_sequence;
if (!(int) trigger->trg_type) /* still none */
PARSE_error(141, dudleyGlob.DDL_token.tok_string, 0);
2003-08-19 10:59:45 +02:00
/* msg 141: expected STORE, MODIFY, ERASE, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
bool action = false;
bool end = false;
2001-05-23 15:26:42 +02:00
while (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI)) {
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
trigger->trg_description = parse_description();
else if (PARSE_match(KW_END_TRIGGER))
2003-09-10 19:52:12 +02:00
action = end = true;
2001-05-23 15:26:42 +02:00
else if (!action) {
trigger->trg_source = start_text();
trigger->trg_statement = EXPR_statement();
end_text(trigger->trg_source);
2003-09-10 19:52:12 +02:00
action = true;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_MESSAGE)) {
TRGMSG trigmsg = (TRGMSG) DDL_alloc(sizeof(trgmsg));
2001-05-23 15:26:42 +02:00
trigmsg->trgmsg_trg_name = trigger->trg_name;
trigmsg->trgmsg_number = PARSE_number();
if (trigmsg->trgmsg_number > 255)
2004-03-14 06:51:54 +01:00
PARSE_error(142, (TEXT *)(IPTR)(trigmsg->trgmsg_number), 0);
2003-08-19 10:59:45 +02:00
/* msg 142: message number %d exceeds 255 */
PARSE_match(KW_COLON);
2001-05-23 15:26:42 +02:00
trigmsg->trgmsg_text = PARSE_symbol(tok_quoted);
2001-07-12 07:46:06 +02:00
make_action(act_a_trigger_msg, (DBB) trigmsg);
PARSE_match(KW_COMMA);
2001-05-23 15:26:42 +02:00
}
else {
/* if none of the other cases were true, we must be stuck on a bum token */
if (end)
PARSE_error(304, dudleyGlob.DDL_token.tok_string, 0);
2003-08-19 10:59:45 +02:00
/* msg 304: expected message keyword, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
else if (!action)
PARSE_error(305, dudleyGlob.DDL_token.tok_string, 0);
2003-08-19 10:59:45 +02:00
/* msg 305: expected trigger action, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
else
PARSE_error(306, dudleyGlob.DDL_token.tok_string, 0);
2003-08-19 10:59:45 +02:00
/* msg 306: expected end_trigger or description keyword, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
break;
}
}
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_a_trigger, (DBB) trigger);
2001-05-23 15:26:42 +02:00
trigger->trg_name->sym_type = SYM_trigger;
trigger->trg_name->sym_object = (DUDLEY_CTX) trigger;
2001-05-23 15:26:42 +02:00
HSH_insert(trigger->trg_name);
}
2002-07-06 07:32:02 +02:00
static void define_type(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* d e f i n e _ t y p e
*
**************************************
*
* Functional description
* Parse a type for a field.
*
**************************************/
PARSE_match(KW_FOR);
SYM fldname = PARSE_symbol(tok_ident);
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
TYP fldtype = (TYP) DDL_alloc(sizeof(typ));
2001-05-23 15:26:42 +02:00
fldtype->typ_field_name = fldname;
fldtype->typ_name = PARSE_symbol(tok_ident);
PARSE_match(KW_COLON);
2001-05-23 15:26:42 +02:00
fldtype->typ_type = PARSE_number();
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
fldtype->typ_description = parse_description();
2001-07-12 07:46:06 +02:00
make_action(act_a_type, (DBB) fldtype);
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
parse_end();
}
2002-07-06 07:32:02 +02:00
static void define_view(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* d e f i n e _ v i e w
*
**************************************
*
* Functional description
* Parse a DEFINE VIEW statement.
*
**************************************/
/* Pick up relation name */
DUDLEY_REL relation = PARSE_relation();
2001-05-23 15:26:42 +02:00
if (!(relation->rel_flags & rel_marked_for_delete) &&
((relation->rel_flags & rel_marked_for_creation)
2003-09-10 19:52:12 +02:00
|| EXE_relation(relation)))
{
PARSE_error(300, relation->rel_name->sym_string, 0);
// msg 300: relation %s already exists
}
2001-05-23 15:26:42 +02:00
PARSE_match(KW_OF);
2001-05-23 15:26:42 +02:00
/* Parse record selection expression */
dudley_lls* contexts = NULL;
2001-05-23 15:26:42 +02:00
relation->rel_view_source = start_text();
2003-09-10 19:52:12 +02:00
relation->rel_rse = EXPR_rse(true);
2001-05-23 15:26:42 +02:00
end_text(relation->rel_view_source);
/* add my context to the context stack */
2004-02-02 12:02:12 +01:00
contexts = (dudley_lls*) relation->rel_rse->nod_arg[s_rse_contexts];
DUDLEY_CTX my_context = make_context(0, relation);
LLS_PUSH((DUDLEY_NOD) my_context, &contexts);
relation->rel_rse->nod_arg[s_rse_contexts] = (DUDLEY_NOD) contexts;
2001-05-23 15:26:42 +02:00
ACT action = make_action(act_a_relation, (DBB) relation);
ACT rel_actions = action;
2001-05-23 15:26:42 +02:00
action->act_flags |= ACT_ignore;
/* Pick up various fields and clauses */
2003-09-10 19:52:12 +02:00
while (true) {
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
relation->rel_description = parse_description();
else if (PARSE_match(KW_SECURITY_CLASS))
2001-05-23 15:26:42 +02:00
relation->rel_security_class = PARSE_symbol(tok_ident);
else if (PARSE_match(KW_SYSTEM_FLAG)) {
2001-05-23 15:26:42 +02:00
relation->rel_system = get_system_flag();
relation->rel_flags |= rel_explicit_system;
}
else
break;
}
/* Gobble fields */
SSHORT position = 1;
DUDLEY_FLD* ptr = &relation->rel_fields;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
PARSE_match(KW_ADD);
PARSE_match(KW_FIELD);
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_local;
field->fld_relation = relation;
*ptr = field;
ptr = &field->fld_next;
SYM symbol = PARSE_symbol(tok_ident);
field->fld_name = symbol;
DUDLEY_CTX context = lookup_context(symbol, contexts);
if (context) {
if (!PARSE_match(KW_DOT))
PARSE_error(144, dudleyGlob.DDL_token.tok_string, 0); /* msg 144: expected period, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
field->fld_name = field->fld_base = PARSE_symbol(tok_ident);
}
else {
if (PARSE_match(KW_FROM)) {
2001-05-23 15:26:42 +02:00
symbol = PARSE_symbol(tok_ident);
if (!(context = lookup_context(symbol, contexts)))
PARSE_error(145, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 145: expected qualified field name, encountered \"%s\" */
if (!PARSE_match(KW_DOT))
PARSE_error(146, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 146: expected period, encountered \"%s\" */
field->fld_base = PARSE_symbol(tok_ident);
}
else {
parse_field_dtype(field);
if (field->fld_dtype == blr_cstring)
PARSE_error(147, 0, 0); /* msg 147: datatype cstring not supported for fields */
if (PARSE_match(KW_COMPUTED)) {
PARSE_match(KW_BY);
if (!(PARSE_match(KW_LEFT_PAREN)))
2001-05-23 15:26:42 +02:00
PARSE_error(148, 0, 0); /* msg 148: computed by expression must be parenthesized */
field->fld_compute_src = start_text();
2003-09-10 19:52:12 +02:00
field->fld_computed = EXPR_value(0, NULL);
2001-05-23 15:26:42 +02:00
end_text(field->fld_compute_src);
if (!(PARSE_match(KW_RIGHT_PAREN)))
2001-05-23 15:26:42 +02:00
PARSE_error(149, 0, 0); /* msg 149: unmatched parenthesis */
context = my_context;
}
else
PARSE_error(150, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 150: expected FROM, COMPUTED, or qualified field, encountered \"%s\" */
}
}
field->fld_context = context;
parse_field_clauses(field);
if (field->fld_computed)
make_computed_field(field);
if (field->fld_flags & fld_explicit_position)
position = field->fld_position + 1;
else
field->fld_position = position++;
field->fld_flags |= fld_explicit_position;
field->fld_name->sym_type = SYM_field;
field->fld_name->sym_object = (DUDLEY_CTX) field;
2001-05-23 15:26:42 +02:00
HSH_insert(field->fld_name);
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
parse_end();
/* We started off by assuming that the relation and field actions that
have been defined would have to be ignored. Everything has gone well so
turn them on. */
2003-09-10 19:52:12 +02:00
while (true) {
2001-05-23 15:26:42 +02:00
action->act_flags &= ~ACT_ignore;
if (action == rel_actions)
break;
action = action->act_next;
}
HSH_insert(relation->rel_name);
relation->rel_flags &= ~rel_marked_for_delete;
relation->rel_flags |= rel_marked_for_creation;
}
static void drop_filter(void)
{
/**************************************
*
* d r o p _ f i l t e r
*
**************************************
*
* Functional description
* Parse the DROP (DELETE) filter statement.
*
**************************************/
FILTER filter_to_drop = (FILTER) DDL_alloc(sizeof(filter));
2003-09-30 12:39:11 +02:00
filter_to_drop->filter_name = PARSE_symbol(tok_ident);
2001-05-23 15:26:42 +02:00
parse_end();
2003-09-30 12:39:11 +02:00
make_action(act_d_filter, (DBB) filter_to_drop);
2001-05-23 15:26:42 +02:00
}
static void drop_function(void)
{
/**************************************
*
* d r o p _ f u n c t i o n
*
**************************************
*
* Functional description
* Parse the DROP (DELETE) function statement.
*
**************************************/
FUNC function = (FUNC) DDL_alloc(sizeof(func));
2001-05-23 15:26:42 +02:00
function->func_name = PARSE_symbol(tok_ident);
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_d_function, (DBB) function);
2001-05-23 15:26:42 +02:00
}
static void drop_gfield(void)
{
/**************************************
*
* d r o p _ g f i e l d
*
**************************************
*
* Functional description
* Parse the DROP (DELETE) field statement.
*
**************************************/
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
field->fld_name = PARSE_symbol(tok_ident);
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_d_gfield, (DBB) field);
2001-05-23 15:26:42 +02:00
}
static void drop_index(void)
{
/**************************************
*
* d r o p _ i n d e x
*
**************************************
*
* Functional description
* Parse DROP INDEX statement.
*
**************************************/
2003-08-12 12:02:27 +02:00
DUDLEY_IDX index = (DUDLEY_IDX) DDL_alloc(IDX_LEN(1)); // 0 is invalid
2001-05-23 15:26:42 +02:00
index->idx_name = PARSE_symbol(tok_ident);
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_d_index, (DBB) index);
2001-05-23 15:26:42 +02:00
}
static void drop_relation(void)
{
/**************************************
*
* d r o p _ r e l a t i o n
*
**************************************
*
* Functional description
* Parse DROP RELATION statement.
*
**************************************/
DUDLEY_REL relation = PARSE_relation();
2001-05-23 15:26:42 +02:00
parse_end();
if (relation->rel_flags & rel_marked_for_creation)
PARSE_error(303, 0, 0); /* msg 303: A relation or view may not be defined and then deleted in a single execution of GDEF */
relation->rel_flags |= rel_marked_for_delete;
2001-07-12 07:46:06 +02:00
make_action(act_d_relation, (DBB) relation);
2001-05-23 15:26:42 +02:00
}
static void drop_security_class(void)
{
/**************************************
*
* d r o p _ s e c u r i t y _ c l a s s
*
**************************************
*
* Functional description
* Parse DROP SECURITY_CLASS statement.
*
**************************************/
SCL sec_class = (SCL) DDL_alloc(sizeof(scl));
sec_class->scl_name = PARSE_symbol(tok_ident);
2001-05-23 15:26:42 +02:00
parse_end();
make_action(act_d_security, (DBB) sec_class);
2001-05-23 15:26:42 +02:00
}
static void drop_shadow(void)
{
/**************************************
*
* d r o p _ s h a d o w
*
**************************************
*
* Functional description
* Parse DROP SHADOW statement.
*
**************************************/
const int number = PARSE_number();
2001-05-23 15:26:42 +02:00
parse_end();
2004-03-14 06:51:54 +01:00
make_action(act_d_shadow, (DBB)(IPTR) number);
2001-05-23 15:26:42 +02:00
}
static void drop_trigger(void)
{
/**************************************
*
* d r o p _ t r i g g e r
*
**************************************
*
* Functional description
* Parse trigger deletion
* (old and new trigger syntax).
*
**************************************/
if (PARSE_match(KW_FOR)) {
DUDLEY_REL relation = PARSE_relation();
while (!PARSE_match(KW_END_TRIGGER)) {
DUDLEY_TRG trigger = (DUDLEY_TRG) DDL_alloc(sizeof(dudley_trg));
if (PARSE_match(KW_STORE))
2001-05-23 15:26:42 +02:00
trigger->trg_type = trg_store;
else if (PARSE_match(KW_MODIFY))
2001-05-23 15:26:42 +02:00
trigger->trg_type = trg_modify;
else if (PARSE_match(KW_ERASE))
2001-05-23 15:26:42 +02:00
trigger->trg_type = trg_erase;
else
PARSE_error(153, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 153: "expected STORE, MODIFY, ERASE, or END_TRIGGER, encountered \"%s\" */
trigger->trg_name = gen_trigger_name(trigger->trg_type, relation);
2001-05-23 15:26:42 +02:00
trigger->trg_relation = relation;
2001-07-12 07:46:06 +02:00
make_action(act_d_trigger, (DBB) trigger);
2001-05-23 15:26:42 +02:00
}
}
else {
DUDLEY_TRG trigger = (DUDLEY_TRG) DDL_alloc(sizeof(dudley_trg));
trigger->trg_name = PARSE_symbol(tok_ident);
2001-07-12 07:46:06 +02:00
make_action(act_d_trigger, (DBB) trigger);
2001-05-23 15:26:42 +02:00
}
parse_end();
}
static void drop_type(void)
{
/**************************************
*
* d r o p _ t y p e
*
**************************************
*
* Functional description
* Parse the DROP (DELETE) type statement.
*
**************************************/
PARSE_match(KW_FOR);
if (PARSE_match(KW_ALL)) {
TYP fldtype = (TYP) DDL_alloc(sizeof(typ));
2001-05-23 15:26:42 +02:00
fldtype->typ_field_name = PARSE_symbol(tok_ident);
fldtype->typ_name->sym_length = 3;
//strncpy(fldtype->typ_name->sym_string, "ALL", 3);
// Bug: writing in null pointer?
fldtype->typ_name->sym_string = "ALL";
2001-07-12 07:46:06 +02:00
make_action(act_d_type, (DBB) fldtype);
2001-05-23 15:26:42 +02:00
}
else {
SYM fldname = PARSE_symbol(tok_ident);
2003-09-10 19:52:12 +02:00
while (true) {
TYP fldtype = (TYP) DDL_alloc(sizeof(typ));
2001-05-23 15:26:42 +02:00
fldtype->typ_field_name = fldname;
fldtype->typ_name = PARSE_symbol(tok_ident);
2001-07-12 07:46:06 +02:00
make_action(act_d_type,(DBB) fldtype);
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
}
parse_end();
}
static void end_text( TXT text)
{
/**************************************
*
* e n d _ t e x t
*
**************************************
*
* Functional description
* Mark end of a text description.
*
**************************************/
text->txt_length =
dudleyGlob.DDL_token.tok_position - dudleyGlob.DDL_token.tok_length - text->txt_position;
2001-05-23 15:26:42 +02:00
#if (defined WIN_NT)
2001-05-23 15:26:42 +02:00
/* the length of the text field should subtract out the
line feeds, since they are automatically filtered out
when reading from a file */
text->txt_length -= (dudleyGlob.DDL_line - text->txt_start_line);
2001-05-23 15:26:42 +02:00
#endif
}
static SYM gen_trigger_name( TRG_T type, DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e n _ t r i g g e r _ n a m e
*
**************************************
*
* Functional description
* Generate a trigger name for an old style trigger.
*
**************************************/
SYM symbol = (SYM) DDL_alloc(SYM_LEN + GDS_NAME_LEN);
2001-05-23 15:26:42 +02:00
symbol->sym_string = symbol->sym_name;
TEXT* p = symbol->sym_name;
const TEXT* const end = p + GDS_NAME_LEN;
2001-05-23 15:26:42 +02:00
/* Start by copying relation name */
const TEXT* q = relation->rel_name->sym_string;
2001-05-23 15:26:42 +02:00
while (*q && p < end)
*p++ = *q++;
switch (type) {
case trg_store:
q = "$STORE";
break;
case trg_modify:
q = "$MODIFY";
break;
case trg_erase:
q = "$ERASE";
break;
default:
DDL_err(156, NULL, NULL, NULL, NULL, NULL); /* msg 156: gen_trigger_name: invalid trigger type */
}
while (*q && p < end)
*p++ = *q++;
*p = 0;
symbol->sym_length = p - symbol->sym_string;
return symbol;
}
static int get_system_flag(void)
{
/**************************************
*
* g e t _ s y s t e m _ f l a g
*
**************************************
*
* Functional description
* Return the (signed) numeric system flag value.
*
**************************************/
const SSHORT number = PARSE_number();
2001-05-23 15:26:42 +02:00
if (number == 1)
PARSE_error(157, 0, 0); /* msg 157: System flag value of 1 is reserved for system relations */
return number;
}
static void get_trigger_attributes( int *flags, int *type, int *sequence)
{
/**************************************
*
* g e t _ t r i g g e r _ a t t r i b u t e s
*
**************************************
*
* Functional description
*
* trigger attributes include [[PRE | POST]
* {STORE | MODIFY | ERASE } [SEQUENCE]].
* All are optional on a new style modify,
* PRE and POST are optional in new style definitions.
* For STORE & MODIFY PRE is the default.
* For ERASE, POST is the default.
*
**************************************/
if (PARSE_match(KW_INACTIVE)) {
2001-05-23 15:26:42 +02:00
*flags |= trg_mflag_onoff;
*type |= trig_inact;
}
else if (PARSE_match(KW_ACTIVE))
2001-05-23 15:26:42 +02:00
*flags |= trg_mflag_onoff;
*flags |= trg_mflag_order;
if (PARSE_match(KW_PRE_STORE))
2001-05-23 15:26:42 +02:00
*type |= trig_sto;
else if (PARSE_match(KW_PRE_MODIFY))
2001-05-23 15:26:42 +02:00
*type |= trig_mod;
else if (PARSE_match(KW_PRE_ERASE))
2001-05-23 15:26:42 +02:00
*type |= trig_era;
else if (!(PARSE_match(KW_PRE))) {
2001-05-23 15:26:42 +02:00
*type |= trig_post;
if (PARSE_match(KW_POST_STORE))
2001-05-23 15:26:42 +02:00
*type |= trig_sto;
else if (PARSE_match(KW_POST_MODIFY))
2001-05-23 15:26:42 +02:00
*type |= trig_mod;
else if (PARSE_match(KW_POST_ERASE))
2001-05-23 15:26:42 +02:00
*type |= trig_era;
else if (!(PARSE_match(KW_POST))) {
2001-05-23 15:26:42 +02:00
*type &= ~trig_post;
*flags &= ~trg_mflag_order;
}
}
if (!(*type & ~(trig_inact | trig_post))) {
if (PARSE_match(KW_STORE))
2001-05-23 15:26:42 +02:00
*type |= trig_sto;
else if (PARSE_match(KW_MODIFY))
2001-05-23 15:26:42 +02:00
*type |= trig_mod;
else if (PARSE_match(KW_ERASE)) {
2001-05-23 15:26:42 +02:00
*type |= trig_era;
if (!(*flags & trg_mflag_order))
*type |= trig_post;
}
}
if ((!PARSE_match(KW_COLON)) && ((*flags & trg_mflag_order) ||
(*type & (trig_sto | trig_mod | trig_era))))
{
2001-05-23 15:26:42 +02:00
*sequence = PARSE_number();
*flags |= trg_mflag_seqnum;
PARSE_match(KW_COLON);
2001-05-23 15:26:42 +02:00
}
if ((*type & ~trig_inact) || (*flags & trg_mflag_order))
*flags |= trg_mflag_type;
}
static void grant_user_privilege(void)
{
/**************************************
*
* g r a n t _ u s e r _ p r i v i l e g e
*
**************************************
*
* Functional description
* Parse a SQL grant statement.
*
**************************************/
USERPRIV upriv = (USERPRIV) DDL_alloc(sizeof(userpriv));
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags = 0;
2003-09-10 19:52:12 +02:00
while (true) {
2001-05-23 15:26:42 +02:00
/* ALL is translated to mean four individual privileges */
if (PARSE_match(KW_ALL)) {
2001-05-23 15:26:42 +02:00
/* optional keyword following ALL */
PARSE_match(KW_PRIVILEGES);
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_select;
upriv->userpriv_flags |= USERPRIV_delete;
upriv->userpriv_flags |= USERPRIV_insert;
upriv->userpriv_flags |= USERPRIV_update;
if (!PARSE_match(KW_ON))
PARSE_error(159, dudleyGlob.DDL_token.tok_string, 0); /* msg 159: expected ON, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
break;
}
else if (PARSE_match(KW_SELECT))
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_select;
else if (PARSE_match(KW_DELETE))
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_delete;
else if (PARSE_match(KW_INSERT))
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_insert;
else if (PARSE_match(KW_UPDATE)) {
2001-05-23 15:26:42 +02:00
/* look for a field list for the update privilege */
upriv->userpriv_flags |= USERPRIV_update;
if (PARSE_match(KW_ON))
2001-05-23 15:26:42 +02:00
break;
if (PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
continue;
if (!PARSE_match(KW_LEFT_PAREN))
PARSE_error(313, dudleyGlob.DDL_token.tok_string, 0); /* msg 313: expected ON or '(', encountered "%s" */
2001-05-23 15:26:42 +02:00
do {
if (dudleyGlob.DDL_token.tok_keyword == KW_SELECT
|| dudleyGlob.DDL_token.tok_keyword == KW_INSERT
|| dudleyGlob.DDL_token.tok_keyword == KW_DELETE
|| dudleyGlob.DDL_token.tok_keyword == KW_UPDATE)
{
2001-05-23 15:26:42 +02:00
break;
}
UPFE upf = (UPFE) DDL_alloc(sizeof(upfe));
2001-05-23 15:26:42 +02:00
upf->upfe_fldname = PARSE_symbol(tok_ident);
upf->upfe_next = upriv->userpriv_upflist;
upriv->userpriv_upflist = upf;
} while (PARSE_match(KW_COMMA));
2001-05-23 15:26:42 +02:00
if (!PARSE_match(KW_RIGHT_PAREN))
PARSE_error(314, dudleyGlob.DDL_token.tok_string, 0); /* msg 314: expected ')', encountered "%s" */
2001-05-23 15:26:42 +02:00
continue;
}
if (!PARSE_match(KW_COMMA)) {
if (!PARSE_match(KW_ON))
PARSE_error(159, dudleyGlob.DDL_token.tok_string, 0); /* msg 159: expected ON, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
break;
}
}
if (!upriv->userpriv_flags)
PARSE_error(160, 0, 0); /* msg 160: GRANT privilege was not specified */
upriv->userpriv_relation = PARSE_symbol(tok_ident);
if (!PARSE_match(KW_TO))
PARSE_error(161, dudleyGlob.DDL_token.tok_string, 0); /* msg 161: expected TO, encountered "%s" */
2001-05-23 15:26:42 +02:00
/* get the userlist */
2003-09-10 19:52:12 +02:00
while (true) {
USRE usr = (USRE) DDL_alloc(sizeof(usre));
2001-05-23 15:26:42 +02:00
usr->usre_name = PARSE_symbol(tok_ident);
usr->usre_next = upriv->userpriv_userlist;
upriv->userpriv_userlist = usr;
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
/* check for the optional WITH GRANT OPTION specification */
if (PARSE_match(KW_WITH)) {
if (!PARSE_match(KW_GRANT))
PARSE_error(162, dudleyGlob.DDL_token.tok_string, 0); /* msg 162:expected GRANT, encountered \"%s\" */
if (!PARSE_match(KW_OPTION))
PARSE_error(163, dudleyGlob.DDL_token.tok_string, 0); /* msg 163: expected OPTION, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_grant;
}
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_grant, (DBB) upriv);
2001-05-23 15:26:42 +02:00
}
2004-02-02 12:02:12 +01:00
static DUDLEY_CTX lookup_context( SYM symbol, dudley_lls* contexts)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* l o o k u p _ c o n t e x t
*
**************************************
*
* Functional description
* Search the context stack. If a context name is given, consider
* only named contexts; otherwise return the first unnamed context.
* In either case, if nothing matches, return NULL.
*
**************************************/
/* If no name is given, look for a nameless one. */
if (!symbol) {
for (; contexts; contexts = contexts->lls_next) {
DUDLEY_CTX context = (DUDLEY_CTX) contexts->lls_object;
2001-05-23 15:26:42 +02:00
if (!context->ctx_name && !context->ctx_view_rse)
return context;
}
return NULL;
}
/* Other search by name */
for (; contexts; contexts = contexts->lls_next) {
DUDLEY_CTX context = (DUDLEY_CTX) contexts->lls_object;
SYM name = context->ctx_name;
if (name && !strcmp(name->sym_string, symbol->sym_string))
return context;
2001-05-23 15:26:42 +02:00
}
return NULL;
}
static DUDLEY_FLD lookup_global_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* l o o k u p _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
*
**************************************/
/* Find symbol */
SYM name = (field->fld_source) ? field->fld_source : field->fld_name;
2001-05-23 15:26:42 +02:00
SYM symbol = HSH_typed_lookup(name->sym_string, name->sym_length,
SYM_global);
if (symbol)
return (DUDLEY_FLD) symbol->sym_object;
2001-05-23 15:26:42 +02:00
PARSE_error(230, name->sym_string, 0); /* msg 230: global field %s isn't defined */
return NULL;
}
static ACT make_action( enum act_t type, DBB object)
{
/**************************************
*
* m a k e _ a c t i o n
*
**************************************
*
* Functional description
* Allocate and link an action block.
*
**************************************/
ACT action = (ACT) DDL_alloc(sizeof(act));
2001-05-23 15:26:42 +02:00
action->act_type = type;
action->act_next = dudleyGlob.DDL_actions;
2001-05-23 15:26:42 +02:00
action->act_object = object;
action->act_line = dudleyGlob.DDL_line;
dudleyGlob.DDL_actions = action;
2001-05-23 15:26:42 +02:00
return action;
}
static ACT make_computed_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m a k e _ c o m p u t e d _ f i e l d
*
**************************************
*
* Functional description
*
**************************************/
TEXT s[64];
/* Start by generating a unique name */
USHORT l;
for (USHORT i = 1;; i++) {
2001-05-23 15:26:42 +02:00
sprintf(s, "RDB$%d", i);
l = strlen(s);
if (!HSH_lookup(s, l))
break;
}
/* Make up new symbol block */
SYM symbol = (SYM) DDL_alloc(SYM_LEN + l);
field->fld_source = symbol;
2001-05-23 15:26:42 +02:00
symbol->sym_type = SYM_global;
symbol->sym_length = l;
symbol->sym_string = symbol->sym_name;
strcpy(symbol->sym_name, s);
DUDLEY_FLD computed = create_global_field(field);
field->fld_source_field = computed;
symbol->sym_object = (DUDLEY_CTX) computed;
2001-05-23 15:26:42 +02:00
return make_global_field(computed);
}
static DUDLEY_CTX make_context( TEXT * string, DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m a k e _ c o n t e x t
*
**************************************
*
* Functional description
* Make context for trigger.
*
**************************************/
DUDLEY_CTX context = (DUDLEY_CTX) DDL_alloc(sizeof(dudley_ctx));
2001-05-23 15:26:42 +02:00
context->ctx_relation = relation;
if (string) {
SYM symbol = (SYM) DDL_alloc(SYM_LEN);
context->ctx_name = symbol;
2001-05-23 15:26:42 +02:00
symbol->sym_object = context;
symbol->sym_string = string;
symbol->sym_length = strlen(string);
symbol->sym_type = SYM_context;
}
return context;
}
static ACT make_global_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m a k e _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
*
**************************************/
/* Make sure symbol is unique */
SYM symbol = field->fld_name;
symbol->sym_object = (DUDLEY_CTX) field;
2001-05-23 15:26:42 +02:00
symbol->sym_type = SYM_global;
if (symbol = HSH_typed_lookup(symbol->sym_string,
symbol->sym_length,
SYM_global))
PARSE_error(164, symbol->sym_string, 0); /* msg 164: global field %s already exists */
HSH_insert(field->fld_name);
2001-07-12 07:46:06 +02:00
return make_action(act_a_gfield, (DBB) field);
2001-05-23 15:26:42 +02:00
}
static void mod_old_trigger(void)
{
/**************************************
*
* m o d _ o l d _ t r i g g e r
*
**************************************
*
* Functional description
* Parse and old style modify trigger.
* (first part was done earlier)
*
**************************************/
DUDLEY_REL relation = PARSE_relation();
2001-05-23 15:26:42 +02:00
while (!PARSE_match(KW_END_TRIGGER)) {
int flags = 0, type = 0, sequence = 0;
2001-05-23 15:26:42 +02:00
get_trigger_attributes(&flags, &type, &sequence);
if (!type)
PARSE_error(165, dudleyGlob.DDL_token.tok_string, 0); /* msg 165: expected STORE, MODIFY, ERASE, END_TRIGGER, encountered \"%s\" */
DUDLEY_TRG trigger = (DUDLEY_TRG) DDL_alloc(sizeof(dudley_trg));
2001-05-23 15:26:42 +02:00
trigger->trg_relation = relation;
trigger->trg_mflag = flags & ~trg_mflag_order;
if (trigger->trg_mflag & trg_mflag_type)
trigger->trg_type = trig_table[type & ~trig_inact];
SYM name = gen_trigger_name(trigger->trg_type, relation);
trigger->trg_name = name;
SYM symbol = HSH_typed_lookup(name->sym_string, name->sym_length,
SYM_trigger);
if (!symbol)
PARSE_error(166, name->sym_string, 0); /* msg 166: Trigger %s does not exist */
2001-05-23 15:26:42 +02:00
modify_trigger_action(trigger, relation);
2001-07-12 07:46:06 +02:00
make_action(act_m_trigger, (DBB) trigger);
2001-05-23 15:26:42 +02:00
}
parse_end();
}
static void modify_field(void)
{
/**************************************
*
* m o d i f y _ f i e l d
*
**************************************
*
* Functional description
* Parse a MODIFY FIELD statement.
*
**************************************/
if (!local_context)
LLS_PUSH((DUDLEY_NOD) DDL_alloc(sizeof(dudley_ctx)), &local_context);
2001-05-23 15:26:42 +02:00
/* Lookup global field */
SYM symbol;
for (symbol = dudleyGlob.DDL_token.tok_symbol; symbol; symbol = symbol->sym_homonym)
2001-05-23 15:26:42 +02:00
if (symbol->sym_type == SYM_global)
break;
if (!symbol)
PARSE_error(167, dudleyGlob.DDL_token.tok_string, 0); /*msg 167: expected global field name, encountered \"%s\" */
DUDLEY_FLD field = (DUDLEY_FLD) symbol->sym_object;
2001-05-23 15:26:42 +02:00
LEX_token();
field->fld_flags |= fld_modify;
parse_field_dtype(field);
if (field->fld_dtype == blr_cstring)
PARSE_error(168, 0, 0); /*msg 168: datatype cstring not supported for fields */
parse_field_clauses(field);
if (field->fld_computed)
PARSE_error(169, 0, 0); /* msg 169: A computed expression can not be changed or added */
if (field->fld_security_class)
PARSE_error(170, 0, 0); /* msg 170: Security class can appear only on local field references */
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_m_gfield, (DBB) field);
2001-05-23 15:26:42 +02:00
}
static void modify_index(void)
{
/**************************************
*
* m o d i f y _ i n d e x
*
**************************************
*
* Functional description
* Alter an index. Does not currently
* allow adding or dropping fields from
* an index
*
**************************************/
2003-08-12 12:02:27 +02:00
DUDLEY_IDX index = (DUDLEY_IDX) DDL_alloc(IDX_LEN(1)); // 0 is invalid
2001-05-23 15:26:42 +02:00
index->idx_name = PARSE_symbol(tok_ident);
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_DUPLICATES)) {
2003-09-10 19:52:12 +02:00
index->idx_unique = false;
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_unique_flag;
}
else if (PARSE_match(KW_UNIQUE)) {
2003-09-10 19:52:12 +02:00
index->idx_unique = true;
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_unique_flag;
}
else if (PARSE_match(KW_ACTIVE)) {
2003-09-10 19:52:12 +02:00
index->idx_inactive = false;
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_active_flag;
}
else if (PARSE_match(KW_INACTIVE)) {
2003-09-10 19:52:12 +02:00
index->idx_inactive = true;
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_active_flag;
}
else if (PARSE_match(KW_ASCENDING)) {
2003-09-15 04:15:27 +02:00
index->idx_type = IDX_type_none;
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_type_flag;
}
else if (PARSE_match(KW_DESCENDING)) {
2003-09-15 04:15:27 +02:00
index->idx_type = IDX_type_descend;
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_type_flag;
}
else if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION) {
2001-05-23 15:26:42 +02:00
index->idx_description = parse_description();
}
else if (PARSE_match(KW_DROP)) {
if (PARSE_match(KW_DESCRIP))
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_null_description;
else
PARSE_error(172, dudleyGlob.DDL_token.tok_string, 0); /*msg 172: expected DESCRIPTION, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_STATISTICS))
2001-05-23 15:26:42 +02:00
index->idx_flags |= IDX_statistics_flag;
else
break;
}
2001-07-12 07:46:06 +02:00
make_action(act_m_index, (DBB) index);
2001-05-23 15:26:42 +02:00
}
static void modify_relation(void)
{
/**************************************
*
* m o d i f y _ r e l a t i o n
*
**************************************
*
* Functional description
* Parse a MODIFY RELATION statement.
*
**************************************/
DUDLEY_REL relation = PARSE_relation();
2001-07-12 07:46:06 +02:00
make_action(act_m_relation, (DBB) relation);
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_EXTERNAL_FILE)) {
2001-05-23 15:26:42 +02:00
relation->rel_filename = PARSE_symbol(tok_quoted);
2003-09-10 19:52:12 +02:00
if (!check_filename(relation->rel_filename, true))
2001-05-23 15:26:42 +02:00
PARSE_error(298, 0, 0); /* msg 298: A non-Decnet node name is not permitted in an external file name */
}
2003-09-10 19:52:12 +02:00
bool modify_relation = false;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION) {
2001-05-23 15:26:42 +02:00
relation->rel_description = parse_description();
2003-09-10 19:52:12 +02:00
modify_relation = true;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_SECURITY_CLASS))
2001-05-23 15:26:42 +02:00
{
2003-09-10 19:52:12 +02:00
modify_relation = true;
2001-05-23 15:26:42 +02:00
relation->rel_security_class = PARSE_symbol(tok_ident);
}
else if (PARSE_match(KW_SYSTEM_FLAG)) {
2001-05-23 15:26:42 +02:00
relation->rel_system = get_system_flag();
relation->rel_flags |= rel_explicit_system;
2003-09-10 19:52:12 +02:00
modify_relation = true;
2001-05-23 15:26:42 +02:00
}
else
break;
}
/* Act on field actions */
if (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_ADD)) {
PARSE_match(KW_FIELD);
2001-05-23 15:26:42 +02:00
{
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
parse_field(field);
field->fld_relation = relation;
field->fld_database = dudleyGlob.database;
DUDLEY_FLD global;
2001-05-23 15:26:42 +02:00
if (field->fld_computed)
make_computed_field(field);
else if (!(field->fld_flags & fld_local))
make_global_field(create_global_field(field));
else if (global = lookup_global_field(field)) {
field->fld_dtype = global->fld_dtype;
field->fld_length = global->fld_length;
field->fld_scale = global->fld_scale;
field->fld_segment_length =
global->fld_segment_length;
field->fld_sub_type = global->fld_sub_type;
field->fld_has_sub_type = global->fld_has_sub_type;
}
if (!(field->fld_flags & fld_explicit_position))
field->fld_position = ++relation->rel_field_position;
field->fld_name->sym_type = SYM_field;
HSH_insert(field->fld_name);
2001-07-12 07:46:06 +02:00
make_action(act_a_field, (DBB) field);
2001-05-23 15:26:42 +02:00
}
}
else if (PARSE_match(KW_MODIFY)) {
PARSE_match(KW_FIELD);
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
field->fld_flags |= (fld_modify | fld_local);
parse_field(field);
field->fld_relation = relation;
field->fld_database = dudleyGlob.database;
2001-05-23 15:26:42 +02:00
if (field->fld_computed)
PARSE_error(173, 0, 0); /* msg 173: A computed expression can not be changed or added */
2001-07-12 07:46:06 +02:00
make_action(act_m_field, (DBB) field);
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_DROP)) {
if (PARSE_match(KW_SECURITY_CLASS)) {
2001-05-23 15:26:42 +02:00
relation->rel_flags |= rel_null_security_class;
2003-09-10 19:52:12 +02:00
modify_relation = true;
PARSE_match(KW_COMMA);
if (dudleyGlob.DDL_token.tok_keyword == KW_SEMI)
2001-05-23 15:26:42 +02:00
break;
else
continue;
}
else if (PARSE_match(KW_DESCRIP)) {
2003-09-10 19:52:12 +02:00
modify_relation = true;
2001-05-23 15:26:42 +02:00
relation->rel_flags |= rel_null_description;
PARSE_match(KW_COMMA);
if (dudleyGlob.DDL_token.tok_keyword == KW_SEMI)
2001-05-23 15:26:42 +02:00
break;
else
continue;
}
else {
PARSE_match(KW_FIELD);
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_local;
field->fld_relation = relation;
field->fld_database = dudleyGlob.database;
2001-05-23 15:26:42 +02:00
field->fld_name = PARSE_symbol(tok_ident);
2001-07-12 07:46:06 +02:00
make_action(act_d_field, (DBB) field);
2001-05-23 15:26:42 +02:00
}
}
else
PARSE_error(174, dudleyGlob.DDL_token.tok_string, 0); /* msg 174: expected field action, encountered \"%s\" */
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
parse_end();
if (modify_relation)
relation->rel_flags |= rel_marked_for_modify;
}
static void modify_security_class(void)
{
/**************************************
*
* m o d i f y _ s e c u r i t y _ c l a s s
*
**************************************
*
* Functional description
* Modify an existing security class.
*
**************************************/
/* return error msg for now until fully coded */
PARSE_error(247, 0, 0); /* msg 247: action not implemented yet */
SCL sec_class = (SCL) DDL_alloc(sizeof(scl));
sec_class->scl_name = PARSE_symbol(tok_ident);
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
sec_class->scl_description = parse_description();
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
SCE element = parse_identifier();
if (!element)
2001-05-23 15:26:42 +02:00
return;
const USHORT score = score_entry(element);
for (SCE* next = &sec_class->scl_entries;; next = &(*next)->sce_next)
2001-05-23 15:26:42 +02:00
if (!*next || score > score_entry(*next)) {
element->sce_next = *next;
*next = element;
break;
}
element->sce_privileges = parse_privileges();
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
parse_end();
make_action(act_m_security, (DBB) sec_class);
2001-05-23 15:26:42 +02:00
}
static void modify_trigger(void)
{
/**************************************
*
* m o d i f y _ t r i g g e r
*
**************************************
*
* Functional description
* Parse new trigger modification
* (go elsewhere if this is an old trigger).
*
**************************************/
TRGMSG_T msg_type = trgmsg_none;
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_FOR)) { /* modify trigger for ... is the old syntax */
2001-05-23 15:26:42 +02:00
mod_old_trigger();
return;
}
/* lookup the trigger name, complain and quit if it's unknown */
SYM name;
for (name = dudleyGlob.DDL_token.tok_symbol;
2001-05-23 15:26:42 +02:00
name && (name->sym_type != SYM_trigger); name = name->sym_homonym);
2003-09-10 19:52:12 +02:00
{
if (!name)
PARSE_error(176, dudleyGlob.DDL_token.tok_string, 0);
2003-09-10 19:52:12 +02:00
// msg 176: expected trigger name, encountered \"%s\"
}
DUDLEY_TRG trigger = (DUDLEY_TRG) name->sym_object;
2001-05-23 15:26:42 +02:00
LEX_token();
/* in case somebody compulsive specifies the relation name */
DUDLEY_REL relation;
if (PARSE_match(KW_FOR)) {
2001-05-23 15:26:42 +02:00
relation = PARSE_relation();
if (relation != trigger->trg_relation)
2003-08-19 10:59:45 +02:00
PARSE_error(177, 0, 0);
/* msg 177: Unsuccesful attempt to modify trigger relation */
2001-05-23 15:26:42 +02:00
}
else
relation = trigger->trg_relation;
2003-09-10 19:52:12 +02:00
SLONG flags = 0;
SLONG type = 0;
SLONG sequence = 0;
2001-07-12 07:46:06 +02:00
get_trigger_attributes((int*) &flags, (int*) &type, (int*) &sequence);
2001-05-23 15:26:42 +02:00
bool action = false;
bool end = false;
while (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI)) {
if ((PARSE_match(KW_MESSAGE)) || (PARSE_match(KW_MSGADD)) ||
(PARSE_match(KW_MSGMODIFY)))
{
msg_type = trgmsg_modify;
}
else if ((PARSE_match(KW_MSGDROP)) || (PARSE_match(KW_DROP)))
{
PARSE_match(KW_MESSAGE);
2001-05-23 15:26:42 +02:00
msg_type = trgmsg_drop;
}
if (msg_type) {
TRGMSG trigmsg = (TRGMSG) DDL_alloc(sizeof(trgmsg));
2001-05-23 15:26:42 +02:00
trigmsg->trgmsg_trg_name = trigger->trg_name;
trigmsg->trgmsg_number = PARSE_number();
if (trigmsg->trgmsg_number > 255)
2004-03-14 06:51:54 +01:00
PARSE_error(178, (TEXT *)(IPTR) trigmsg->trgmsg_number, 0);
2003-08-19 10:59:45 +02:00
/* msg 178: message number %d exceeds 255 */
2001-05-23 15:26:42 +02:00
if (msg_type == trgmsg_drop)
2001-07-12 07:46:06 +02:00
make_action(act_d_trigger_msg, (DBB) trigmsg);
2001-05-23 15:26:42 +02:00
else if (msg_type == trgmsg_modify) {
PARSE_match(KW_COLON);
2001-05-23 15:26:42 +02:00
trigmsg->trgmsg_text = PARSE_symbol(tok_quoted);
2001-07-12 07:46:06 +02:00
make_action(act_m_trigger_msg, (DBB) trigmsg);
2001-05-23 15:26:42 +02:00
}
PARSE_match(KW_COMMA);
2001-05-23 15:26:42 +02:00
msg_type = trgmsg_none;
}
else if (PARSE_match(KW_END_TRIGGER))
2003-09-10 19:52:12 +02:00
end = true;
else if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
trigger->trg_description = parse_description();
else if (!action && !end) {
modify_trigger_action(trigger, relation);
2003-09-10 19:52:12 +02:00
action = true;
2001-05-23 15:26:42 +02:00
}
else
PARSE_error(179, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 179: expected message modification keyword, encountered \"%s\" */
}
if (flags || type || sequence)
sort_out_attributes(trigger, flags, type, sequence);
2001-07-12 07:46:06 +02:00
make_action(act_m_trigger, (DBB) trigger);
2001-05-23 15:26:42 +02:00
}
static void modify_trigger_action( DUDLEY_TRG trigger, DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m o d i f y _ t r i g g e r _ a c t i o n
*
**************************************
*
* Functional description
* Parse a trigger statement.
*
**************************************/
trigger->trg_source = start_text();
trigger->trg_statement = EXPR_statement();
end_text(trigger->trg_source);
}
static void modify_type(void)
{
/**************************************
*
* m o d i f y _ t y p e
*
**************************************
*
* Functional description
* Parse a modify of an existing type value for a field.
*
**************************************/
PARSE_match(KW_FOR);
SYM fldname = PARSE_symbol(tok_ident);
2003-09-10 19:52:12 +02:00
while (true) {
TYP fldtype = (TYP) DDL_alloc(sizeof(typ));
2001-05-23 15:26:42 +02:00
fldtype->typ_field_name = fldname;
fldtype->typ_name = PARSE_symbol(tok_ident);
PARSE_match(KW_COLON);
2001-05-23 15:26:42 +02:00
fldtype->typ_type = PARSE_number();
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION)
2001-05-23 15:26:42 +02:00
fldtype->typ_description = parse_description();
2001-07-12 07:46:06 +02:00
make_action(act_m_type, (DBB) fldtype);
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
parse_end();
}
static void modify_view(void)
{
/**************************************
*
* m o d i f y _ v i e w
*
**************************************
*
* Functional description
* Parse a MODIFY VIEW statement.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool view_modify = false;
2001-05-23 15:26:42 +02:00
DUDLEY_REL relation = PARSE_relation();
2001-07-12 07:46:06 +02:00
make_action(act_m_relation, (DBB) relation);
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (dudleyGlob.DDL_token.tok_keyword == KW_DESCRIPTION) {
2001-05-23 15:26:42 +02:00
relation->rel_description = parse_description();
2003-09-10 19:52:12 +02:00
view_modify = true;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_SECURITY_CLASS)) {
2001-05-23 15:26:42 +02:00
relation->rel_security_class = PARSE_symbol(tok_ident);
2003-09-10 19:52:12 +02:00
view_modify = true;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_SYSTEM_FLAG)) {
2001-05-23 15:26:42 +02:00
relation->rel_system = get_system_flag();
relation->rel_flags |= rel_explicit_system;
2003-09-10 19:52:12 +02:00
view_modify = true;
2001-05-23 15:26:42 +02:00
}
else
break;
}
/* Act on field actions */
if (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_MODIFY)) {
PARSE_match(KW_FIELD);
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
field->fld_flags |= (fld_modify | fld_local);
parse_field(field);
field->fld_relation = relation;
field->fld_database = dudleyGlob.database;
2001-05-23 15:26:42 +02:00
if (field->fld_computed)
PARSE_error(181, 0, 0); /* msg 181: A computed expression can not be changed or added */
2001-07-12 07:46:06 +02:00
make_action(act_m_field, (DBB) field);
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_DROP)) {
if (PARSE_match(KW_DESCRIP)) {
2003-09-10 19:52:12 +02:00
view_modify = true;
2001-05-23 15:26:42 +02:00
relation->rel_flags |= rel_null_description;
if (dudleyGlob.DDL_token.tok_keyword == KW_SEMI)
2001-05-23 15:26:42 +02:00
break;
else
continue;
}
else if (PARSE_match(KW_SECURITY_CLASS)) {
2003-09-10 19:52:12 +02:00
view_modify = true;
2001-05-23 15:26:42 +02:00
relation->rel_flags |= rel_null_security_class;
if (dudleyGlob.DDL_token.tok_keyword == KW_SEMI)
2001-05-23 15:26:42 +02:00
break;
else
continue;
}
else {
PARSE_match(KW_FIELD);
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_local;
field->fld_relation = relation;
field->fld_database = dudleyGlob.database;
2001-05-23 15:26:42 +02:00
field->fld_name = PARSE_symbol(tok_ident);
2001-07-12 07:46:06 +02:00
make_action(act_d_field, (DBB) field);
2001-05-23 15:26:42 +02:00
}
}
else
PARSE_error(182, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 182: expected drop/modify of field or security class, encountered \"%s\" */
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
if (view_modify)
relation->rel_flags |= rel_marked_for_modify;
parse_end();
}
2003-09-04 15:45:44 +02:00
static bool parse_action(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p a r s e _ a c t i o n
*
**************************************
*
* Functional description
2003-09-10 19:52:12 +02:00
* Parse a single action. If an token flush is required, return true.
2001-05-23 15:26:42 +02:00
*
**************************************/
/* Set up an environment to catch syntax errors. If one occurs, scan looking
for semi-colon to continue processing. */
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
dudleyGlob.DDL_prompt = PROMPT;
2001-05-23 15:26:42 +02:00
LEX_token();
dudleyGlob.DDL_prompt = CONTINUATION;
if (dudleyGlob.DDL_eof)
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_DEFINE))
2001-05-23 15:26:42 +02:00
switch (parse_object()) {
case obj_database:
define_database(act_c_database);
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_relation:
define_relation();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_view:
define_view();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_field:
define_field();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_index:
define_index();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_security_class:
define_security_class();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_trigger:
define_trigger();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_file:
define_file();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_function:
define_function();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_type:
define_type();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_filter:
define_filter();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_shadow:
define_shadow();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_generator:
define_generator();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
default:
if (dudleyGlob.database) {
2001-05-23 15:26:42 +02:00
define_relation();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
PARSE_error(183, dudleyGlob.DDL_token.tok_string, 0); /* msg 183: expected object for DEFINE, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_MODIFY))
2001-05-23 15:26:42 +02:00
switch (parse_object()) {
case obj_database:
define_database(act_m_database);
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_relation:
modify_relation();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_view:
modify_view();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_field:
modify_field();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_index:
modify_index();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_security_class:
modify_security_class();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_trigger:
modify_trigger();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_function:
PARSE_error(233, 0, 0); /* msg 233: action not implemented yet */
case obj_type:
modify_type();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_filter:
PARSE_error(231, 0, 0); /* msg 231: action not implemented yet */
case obj_shadow:
PARSE_error(232, 0, 0); /* msg 232: action not implemented yet */
default:
PARSE_error(184, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 184: expected object for MODIFY, encountered \"%s\" */
}
else if (PARSE_match(KW_DROP))
2001-05-23 15:26:42 +02:00
switch (parse_object()) {
case obj_database:
define_database(act_d_database);
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_relation:
case obj_view:
drop_relation();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_field:
drop_gfield();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_index:
drop_index();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_security_class:
drop_security_class();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_trigger:
drop_trigger();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_function:
drop_function();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_type:
drop_type();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_filter:
drop_filter();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
case obj_shadow:
drop_shadow();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
default:
PARSE_error(185, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 185: expected object for DROP, encountered \"%s\" */
}
else if (PARSE_match(KW_GRANT)) {
2001-05-23 15:26:42 +02:00
grant_user_privilege();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_REVOKE)) {
2001-05-23 15:26:42 +02:00
revoke_user_privilege();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_SET_GENERATOR)) {
2001-05-23 15:26:42 +02:00
set_generator();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
else if (PARSE_match(KW_SET)) {
if (!PARSE_match(KW_GENERATOR))
PARSE_error(318, dudleyGlob.DDL_token.tok_string, 0); /* msg 318: expected GENERATOR, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
set_generator();
2003-09-04 15:45:44 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
else if (dudleyGlob.DDL_interactive && dudleyGlob.DDL_token.tok_keyword == KW_EXIT) {
dudleyGlob.DDL_eof = true;
2003-09-04 15:45:44 +02:00
return false;
2001-05-23 15:26:42 +02:00
}
else if (dudleyGlob.DDL_interactive && dudleyGlob.DDL_token.tok_keyword == KW_QUIT) {
dudleyGlob.DDL_quit = dudleyGlob.DDL_eof = true;
2003-09-04 15:45:44 +02:00
return false;
2001-05-23 15:26:42 +02:00
}
PARSE_error(186, dudleyGlob.DDL_token.tok_string, 0); /* msg 186: expected command, encountered \"%s\" */
2003-09-10 19:52:12 +02:00
return false;
2001-12-24 03:51:06 +01:00
} // try
2003-02-13 13:01:28 +01:00
catch (const std::exception&) {
if (dudleyGlob.DDL_interactive)
2001-12-24 03:51:06 +01:00
LEX_flush();
else
while (!dudleyGlob.DDL_eof && !(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
2001-12-24 03:51:06 +01:00
LEX_token();
2003-09-04 15:45:44 +02:00
return true;
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
}
static void parse_array( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p a r s e _ a r r a y
*
**************************************
*
* Functional description
* Parse the multi-dimensional array specification.
*
**************************************/
if (!PARSE_match(KW_LEFT_PAREN))
2001-05-23 15:26:42 +02:00
return;
/* Pick up ranges */
SLONG ranges[2 * MAX_DIMENSION];
SLONG* range = ranges;
for (;;) {
2001-05-23 15:26:42 +02:00
++field->fld_dimension;
range[0] = 1;
range[1] = PARSE_number();
if (PARSE_match(KW_COLON)) {
2001-05-23 15:26:42 +02:00
range[0] = range[1];
range[1] = PARSE_number();
}
if ((range[1] - range[0]) <= 0)
PARSE_error(188, 0, 0); /* msg 188: array size must be positive */
range += 2;
if (PARSE_match(KW_RIGHT_PAREN))
2001-05-23 15:26:42 +02:00
break;
if (!PARSE_match(KW_COMMA))
PARSE_error(189, dudleyGlob.DDL_token.tok_string, 0); /* msg 189: expected comma, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
}
/* Allocate and copy block to hold ranges */
const SLONG n = field->fld_dimension * sizeof(SLONG) * 2;
SLONG* ptr = (SLONG*) DDL_alloc(n);
field->fld_ranges = ptr;
2001-05-23 15:26:42 +02:00
const SLONG* const end = range;
for (const SLONG* range2 = ranges; range2 < end;)
*ptr++ = *range2++;
2001-05-23 15:26:42 +02:00
}
static TXT parse_description(void)
{
/**************************************
*
* p a r s e _ d e s c r i p t i o n
*
**************************************
*
* Functional description
* Create a text block to hold the pointer and length
* of the description of a metadata item.
*
**************************************/
dudleyGlob.DDL_description = true;
TXT description = start_text();
description->txt_position = dudleyGlob.DDL_token.tok_position;
2001-05-23 15:26:42 +02:00
while (!dudleyGlob.DDL_eof && (!(dudleyGlob.DDL_token.tok_keyword == KW_END_DESCRIPTION)))
2001-05-23 15:26:42 +02:00
LEX_token();
if (dudleyGlob.DDL_eof)
2001-05-23 15:26:42 +02:00
return NULL;
end_text(description);
PARSE_match(KW_END_DESCRIPTION);
dudleyGlob.DDL_description = false;
2001-05-23 15:26:42 +02:00
return description;
}
static void parse_end(void)
{
/**************************************
*
* p a r s e _ e n d
*
**************************************
*
* Functional description
* Parse the end of command. Better be a semi-colon.
*
**************************************/
if (!(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
PARSE_error(190, dudleyGlob.DDL_token.tok_string, 0); /* msg 190: expected semi-colon, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
}
static DUDLEY_FLD parse_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p a r s e _ f i e l d
*
**************************************
*
* Functional description
* Parse a field definition, complete with data type and clauses.
*
**************************************/
field->fld_name = PARSE_symbol(tok_ident);
field->fld_name->sym_object = (DUDLEY_CTX) field;
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_BASED)) {
PARSE_match(KW_ON);
2001-05-23 15:26:42 +02:00
field->fld_source = PARSE_symbol(tok_ident);
field->fld_flags |= fld_local;
}
else {
parse_field_dtype(field);
if (field->fld_dtype == blr_cstring)
PARSE_error(191, 0, 0); /* msg 191: datatype cstring not supported for fields */
}
if (!field->fld_dtype)
field->fld_flags |= fld_local;
parse_field_clauses(field);
if (!(dudleyGlob.DDL_token.tok_keyword == KW_COMMA) && !(dudleyGlob.DDL_token.tok_keyword == KW_SEMI))
PARSE_error(192, dudleyGlob.DDL_token.tok_string, 0); /* msg 192: expected field clause, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
validate_field(field);
return field;
}
static void parse_field_clauses( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p a r s e _ f i e l d _ c l a u s e s
*
**************************************
*
* Functional description
* Parse a field definition, complete with data type and clauses.
*
**************************************/
/* Pick up purely optional clauses */
2003-09-10 19:52:12 +02:00
while (true)
2001-05-23 15:26:42 +02:00
switch (PARSE_keyword()) {
case KW_POSITION:
LEX_token();
field->fld_position = PARSE_number();
field->fld_flags |= fld_explicit_position;
break;
case KW_SECURITY_CLASS:
LEX_token();
field->fld_security_class = PARSE_symbol(tok_ident);
break;
case KW_DROP:
LEX_token();
if (PARSE_match(KW_SECURITY_CLASS))
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_null_security_class;
else if (PARSE_match(KW_VALID_IF))
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_null_validation;
else if (PARSE_match(KW_DESCRIP))
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_null_description;
else if (PARSE_match(KW_QUERY_NAME))
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_null_query_name;
else if (PARSE_match(KW_QUERY_HEADER))
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_null_query_header;
else if (PARSE_match(KW_EDIT_STRING))
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_null_edit_string;
else if (PARSE_match(KW_MISSING)) {
PARSE_match(KW_VALUE);
2001-05-23 15:26:42 +02:00
field->fld_flags |= fld_null_missing_value;
}
else
PARSE_error(193, dudleyGlob.DDL_token.tok_string, 0);
2001-05-23 15:26:42 +02:00
/* msg 193: expected DESCRIPTION, EDIT_STRING, MISSING VALUE, SECURITY_CLASS or VALID_IF", encountered \"%s\" */
break;
case KW_QUERY_NAME:
LEX_token();
PARSE_match(KW_IS);
2001-05-23 15:26:42 +02:00
field->fld_query_name = PARSE_symbol(tok_ident);
break;
case KW_EDIT_STRING:
LEX_token();
field->fld_edit_string = PARSE_symbol(tok_quoted);
break;
case KW_QUERY_HEADER:
{
LEX_token();
PARSE_match(KW_IS);
dudley_lls* stack = NULL;
for (;;) {
LLS_PUSH((DUDLEY_NOD) PARSE_symbol(tok_quoted), &stack);
if (!PARSE_match(KW_SLASH))
break;
}
field->fld_query_header = PARSE_make_list(stack);
break;
2001-05-23 15:26:42 +02:00
}
case KW_COMPUTED:
LEX_token();
PARSE_match(KW_BY);
if (!(PARSE_match(KW_LEFT_PAREN)))
2001-05-23 15:26:42 +02:00
PARSE_error(194, 0, 0); /* msg 194: computed by expression must be parenthesized */
field->fld_compute_src = start_text();
2003-09-10 19:52:12 +02:00
field->fld_computed = EXPR_value(0, NULL);
2001-05-23 15:26:42 +02:00
end_text(field->fld_compute_src);
if (!(PARSE_match(KW_RIGHT_PAREN)))
2001-05-23 15:26:42 +02:00
PARSE_error(195, 0, 0); /* msg 195: unmatched parenthesis */
break;
case KW_MISSING:
LEX_token();
PARSE_match(KW_VALUE);
PARSE_match(KW_IS);
2003-09-10 19:52:12 +02:00
field->fld_missing = EXPR_value(0, NULL);
2001-05-23 15:26:42 +02:00
break;
case KW_VALID_IF:
LEX_token();
PARSE_match(KW_IF);
if (!(PARSE_match(KW_LEFT_PAREN)))
2001-05-23 15:26:42 +02:00
PARSE_error(196, 0, 0); /* msg 196: validation expression must be parenthesized */
field->fld_valid_src = start_text();
field->fld_validation = EXPR_boolean(0);
end_text(field->fld_valid_src);
if (!(PARSE_match(KW_RIGHT_PAREN)))
2001-05-23 15:26:42 +02:00
PARSE_error(195, 0, 0); /* msg 195: unmatched parenthesis */
break;
case KW_SEGMENT_LENGTH:
{
LEX_token();
PARSE_match(KW_IS);
const int n = PARSE_number();
field->fld_segment_length = n;
if (n <= 0)
PARSE_error(197, 0, 0); /* msg 197: segment length must be positive */
break;
}
2001-05-23 15:26:42 +02:00
case KW_SUB_TYPE:
LEX_token();
parse_field_subtype(field);
break;
case KW_DEFAULT:
LEX_token();
PARSE_match(KW_VALUE);
PARSE_match(KW_IS);
2003-09-10 19:52:12 +02:00
field->fld_default = EXPR_value(0, NULL);
2001-05-23 15:26:42 +02:00
break;
case KW_DESCRIPTION:
field->fld_description = parse_description();
break;
case KW_SYSTEM_FLAG:
LEX_token();
field->fld_system = get_system_flag();
field->fld_flags |= fld_explicit_system;
break;
default:
return;
}
}
static void parse_field_dtype( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p a r s e _ f i e l d _ d t y p e
*
**************************************
*
* Functional description
* Parse a field definition, complete with data type and clauses.
*
**************************************/
switch (PARSE_keyword()) {
case KW_CHAR:
field->fld_dtype = blr_text;
break;
case KW_VARYING:
field->fld_dtype = blr_varying;
break;
case KW_CSTRING:
field->fld_dtype = blr_cstring;
break;
case KW_SHORT:
field->fld_dtype = blr_short;
field->fld_length = sizeof(SSHORT);
break;
case KW_LONG:
field->fld_dtype = blr_long;
field->fld_length = sizeof(SLONG);
break;
case KW_QUAD:
field->fld_dtype = blr_quad;
field->fld_length = sizeof(ISC_QUAD);
2001-05-23 15:26:42 +02:00
break;
case KW_FLOAT:
field->fld_dtype = blr_float;
field->fld_length = sizeof(float);
break;
case KW_DOUBLE:
field->fld_dtype = blr_double;
field->fld_length = sizeof(double);
break;
case KW_DATE:
field->fld_dtype = blr_timestamp;
field->fld_length = sizeof(ISC_QUAD);
2001-05-23 15:26:42 +02:00
break;
case KW_BLOB:
field->fld_dtype = blr_blob;
field->fld_length = sizeof(ISC_QUAD);
2001-05-23 15:26:42 +02:00
break;
default:
return;
}
LEX_token();
if (field->fld_dtype == blr_text ||
field->fld_dtype == blr_varying || field->fld_dtype == blr_cstring)
{
if (!PARSE_match(KW_L_BRCKET) && !PARSE_match(KW_LT))
PARSE_error(200, dudleyGlob.DDL_token.tok_string, 0); /* msg 200: expected \"[\", encountered \"%s\" */
const int n = PARSE_number();
field->fld_length = n;
2001-05-23 15:26:42 +02:00
if (n <= 0)
PARSE_error(201, 0, 0); /* msg 201: character field length must be positive */
if (!PARSE_match(KW_R_BRCKET) && !PARSE_match(KW_GT))
PARSE_error(202, dudleyGlob.DDL_token.tok_string, 0); /* msg 202: expected \"]\", encountered \"%s\" */
2001-05-23 15:26:42 +02:00
if (PARSE_match(KW_SUB_TYPE))
2001-05-23 15:26:42 +02:00
parse_field_subtype(field);
}
if (field->fld_dtype != blr_blob)
parse_array(field);
field->fld_scale = 0;
if ((field->fld_dtype == blr_short ||
field->fld_dtype == blr_long || field->fld_dtype == blr_quad))
{
if (PARSE_match(KW_SCALE))
2001-05-23 15:26:42 +02:00
field->fld_scale = PARSE_number();
}
2001-05-23 15:26:42 +02:00
}
static void parse_field_subtype( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* p a r s e _ f i e l d _ s u b t y p e
*
**************************************
*
* Functional description
* Match a datatype sub_type clause. Set the (fld_has_sub_type) flag
* so we know this type is a type set by the user.
*
**************************************/
PARSE_match(KW_IS);
if (PARSE_match(KW_TEXT) || PARSE_match(KW_FIXED))
2001-05-23 15:26:42 +02:00
field->fld_sub_type = 1;
else if (PARSE_match(KW_BLR))
2001-05-23 15:26:42 +02:00
field->fld_sub_type = 2;
else if (PARSE_match(KW_ACL))
2001-05-23 15:26:42 +02:00
field->fld_sub_type = 3;
else if (PARSE_keyword() == KW_MINUS)
field->fld_sub_type = PARSE_number();
else if (dudleyGlob.DDL_token.tok_type != tok_number)
PARSE_error(198, dudleyGlob.DDL_token.tok_string, 0); /* msg 198: expected field sub_type, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
else
field->fld_sub_type = PARSE_number();
field->fld_has_sub_type = TRUE;
}
static FUNCARG parse_function_arg( FUNC function, USHORT * position)
{
/**************************************
*
* p a r s e _ f u n c t i o n _ a r g
*
**************************************
*
* Functional description
* Parse a function argument definition, complete with data type.
*
**************************************/
FUNCARG func_arg = (FUNCARG) DDL_alloc(sizeof(funcarg));
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2001-05-23 15:26:42 +02:00
parse_field_dtype(field);
func_arg->funcarg_dtype = field->fld_dtype;
func_arg->funcarg_scale = field->fld_scale;
func_arg->funcarg_length = field->fld_length;
func_arg->funcarg_sub_type = field->fld_sub_type;
func_arg->funcarg_has_sub_type = field->fld_has_sub_type;
func_arg->funcarg_position = (*position)++;
PARSE_match(KW_BY);
2001-05-23 15:26:42 +02:00
LEX_token();
switch (PARSE_keyword()) {
case KW_VALUE:
LEX_token();
func_arg->funcarg_mechanism = FUNCARG_mechanism_value;
if (field->fld_dtype == blr_text ||
field->fld_dtype == blr_varying ||
field->fld_dtype == blr_cstring ||
field->fld_dtype == blr_blob || field->fld_dtype == blr_timestamp)
{
2001-05-23 15:26:42 +02:00
PARSE_error(203, 0, 0); /* msg 203: argument mode by value not allowed for this data type */
}
2001-05-23 15:26:42 +02:00
break;
case KW_REFERENCE:
LEX_token();
if (field->fld_dtype == blr_blob)
func_arg->funcarg_mechanism = FUNCARG_mechanism_blob_struc;
else
func_arg->funcarg_mechanism = FUNCARG_mechanism_reference;
break;
case KW_SCALAR_ARRAY_DESCRIPTOR:
LEX_token();
func_arg->funcarg_mechanism = FUNCARG_mechanism_sc_array_desc;
break;
default:
PARSE_error(204, 0, 0); /* msg 204: argument mode is by value, or by reference */
}
/* (kw_comma or kw_semi) here means this argument is not a
return_value or a return_argument in which case it had
better not be passed by value */
if (dudleyGlob.DDL_token.tok_keyword == KW_COMMA || dudleyGlob.DDL_token.tok_keyword == KW_SEMI) {
2001-05-23 15:26:42 +02:00
if (func_arg->funcarg_mechanism == FUNCARG_mechanism_value)
PARSE_error(293, 0, 0); /* msg 293: argument mode 'by value' requires a return mode */
}
else {
if (func_arg->funcarg_mechanism == FUNCARG_mechanism_sc_array_desc)
PARSE_error(295, 0, 0); /* msg 295: "Functions can't return arrays." */
switch (PARSE_keyword()) {
case KW_RETURN_VALUE:
--(*position);
LEX_token();
function->func_return_arg = func_arg->funcarg_position = 0;
function->func_return = func_arg;
break;
case KW_RETURN_ARGUMENT:
LEX_token();
if (func_arg->funcarg_mechanism == FUNCARG_mechanism_value)
PARSE_error(292, 0, 0); /* msg 292: argument mode of a return_argument must be 'by reference' */
function->func_return_arg = func_arg->funcarg_position;
function->func_return = func_arg;
break;
default:
PARSE_error(205, 0, 0); /* msg 205: return mode must be return_value or return_argument */
}
}
if (*position > 11)
PARSE_error(310, 0, 0); /* msg 310: UDF is limited to 10 parameters */
return func_arg;
}
static SCE parse_identifier(void)
{
/**************************************
*
* p a r s e _ i d e n t i f i e r
*
**************************************
*
* Functional description
* Parse the hard part of an access control element.
*
**************************************/
TEXT* idents[10];
TEXT** s;
const TEXT* const* end;
TEXT strings[256];
2001-05-23 15:26:42 +02:00
const TEXT* q;
TEXT* p = strings;
2001-05-23 15:26:42 +02:00
for (s = idents, end = s + 10; s < end; s++)
*s = NULL;
/* Get explicit identifiers, if any */
switch (dudleyGlob.DDL_token.tok_keyword) {
2001-05-23 15:26:42 +02:00
case (KW_VIEW):
LEX_token();
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(117, dudleyGlob.DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
idents[id_view] = p;
q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
while (*p++ = *q++);
LEX_token();
break;
case (KW_USER):
LEX_token();
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(117, dudleyGlob.DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
idents[id_user] = p;
q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
while (*p++ = *q++);
LEX_token();
if (PARSE_match(KW_GROUP)) {
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(117, dudleyGlob.DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
idents[id_group] = p;
q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
while (*p++ = *q++);
LEX_token();
}
break;
case (KW_GROUP):
LEX_token();
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(117, dudleyGlob.DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
idents[id_group] = p;
q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
while (*p++ = *q++);
LEX_token();
if (PARSE_match(KW_USER)) {
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(117, dudleyGlob.DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
idents[id_user] = p;
q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
while (*p++ = *q++);
LEX_token();
}
break;
case (KW_L_BRCKET):
case (KW_LT):
LEX_token();
if (!PARSE_match(KW_ASTERISK)) {
if (dudleyGlob.DDL_token.tok_type != tok_number)
PARSE_error(206, dudleyGlob.DDL_token.tok_string, 0); /* msg 206: expected number, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
idents[id_group] = p;
q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
while (*p++ = *q++);
LEX_token();
}
if (!PARSE_match(KW_COMMA))
PARSE_error(207, dudleyGlob.DDL_token.tok_string, 0); /* msg 207: expected comma between group and user ids, encountered \"%s\" */
if (!PARSE_match(KW_ASTERISK)) {
if (dudleyGlob.DDL_token.tok_type != tok_number)
PARSE_error(206, dudleyGlob.DDL_token.tok_string, 0); /* msg 206: expected number, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
idents[id_user] = p;
q = dudleyGlob.DDL_token.tok_string;
2001-05-23 15:26:42 +02:00
while (*p++ = *q++);
LEX_token();
}
if (!(PARSE_match(KW_R_BRCKET) || PARSE_match(KW_GT)))
PARSE_error(208, dudleyGlob.DDL_token.tok_string, 0); /* msg 208: expected trailing bracket, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
break;
}
/* Build access control element */
SCE element = (SCE) DDL_alloc(sizeof(sce) + (p - strings));
2001-05-23 15:26:42 +02:00
p = (TEXT *) element->sce_strings;
TEXT** s1 = (TEXT **) element->sce_idents;
for (s = idents, end = s + 10; s < end; s++, s1++)
{
2001-05-23 15:26:42 +02:00
if (q = *s) {
*s1 = p;
while (*p++ = *q++);
}
}
2001-05-23 15:26:42 +02:00
return element;
}
static OBJ_T parse_object(void)
{
/**************************************
*
* p a r s e _ o b j e c t
*
**************************************
*
* Functional description
* Parse on object name returning what we found.
*
**************************************/
if (PARSE_match(KW_DATABASE))
2001-05-23 15:26:42 +02:00
return obj_database;
else if (!dudleyGlob.database || !dudleyGlob.database->dbb_handle)
2001-05-23 15:26:42 +02:00
PARSE_error(209, 0, 0); /* msg 209: no database declared */
if (PARSE_match(KW_RELATION))
2001-05-23 15:26:42 +02:00
return obj_relation;
if (PARSE_match(KW_FIELD))
2001-05-23 15:26:42 +02:00
return obj_field;
if (PARSE_match(KW_INDEX))
2001-05-23 15:26:42 +02:00
return obj_index;
if (PARSE_match(KW_VIEW))
2001-05-23 15:26:42 +02:00
return obj_view;
if (PARSE_match(KW_SECURITY_CLASS))
2001-05-23 15:26:42 +02:00
return obj_security_class;
if (PARSE_match(KW_TRIGGER))
2001-05-23 15:26:42 +02:00
return obj_trigger;
if (PARSE_match(KW_FILE))
2001-05-23 15:26:42 +02:00
return obj_file;
if (PARSE_match(KW_FUNCTION))
2001-05-23 15:26:42 +02:00
return obj_function;
if (PARSE_match(KW_TYPES))
2001-05-23 15:26:42 +02:00
return obj_type;
if (PARSE_match(KW_FILTER))
2001-05-23 15:26:42 +02:00
return obj_filter;
if (PARSE_match(KW_SHADOW))
2001-05-23 15:26:42 +02:00
return obj_shadow;
if (PARSE_match(KW_GENERATOR))
2001-05-23 15:26:42 +02:00
return obj_generator;
return obj_none;
}
static int parse_page_size(void)
{
/**************************************
*
* p a r s e _ p a g e _ s i z e
*
**************************************
*
* Functional description
* parse the page_size clause of a
* define database statement
*
*
**************************************/
PARSE_match(KW_EQUALS);
int n1, n2;
2001-05-23 15:26:42 +02:00
n2 = n1 = PARSE_number();
if (n1 <= 1024)
n2 = 1024;
else if (n1 <= 2048)
n2 = 2048;
else if (n1 <= 4096)
n2 = 4096;
else if (n1 <= 8192)
n2 = 8192;
else
2004-03-14 06:51:54 +01:00
PARSE_error(210, (TEXT *)(IPTR) n1, (TEXT *)(IPTR) MAX_PAGE_LEN);
2001-05-23 15:26:42 +02:00
/* msg 210: PAGE_SIZE specified (%d) longer than limit of %d bytes */
if (n1 != n2)
2004-03-14 06:51:54 +01:00
DDL_msg_put(211, (TEXT *)(IPTR) n1, (TEXT *)(IPTR) n2, NULL, NULL, NULL);
2001-05-23 15:26:42 +02:00
/* msg 211: PAGE_SIZE specified (%d) was rounded up to %d bytes\n */
return n2;
}
static SLONG parse_privileges(void)
{
/**************************************
*
* p a r s e _ p r i v i l e g e s
*
**************************************
*
* Functional description
* Parse an access control list.
*
**************************************/
SLONG privileges = 0;
2001-05-23 15:26:42 +02:00
if (!PARSE_match(KW_MINUS)) {
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(117, dudleyGlob.DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
const TEXT* p = dudleyGlob.DDL_token.tok_string;
TEXT c;
2001-05-23 15:26:42 +02:00
while (c = *p++)
switch (UPPER(c)) {
case 'P':
privileges |= 1 << priv_protect;
break;
case 'G':
privileges |= 1 << priv_grant;
break;
case 'D':
privileges |= 1 << priv_delete;
break;
case 'R':
privileges |= 1 << priv_read;
break;
case 'W':
privileges |= 1 << priv_write;
break;
case 'C':
privileges |= 1 << priv_control;
break;
default:
2004-03-14 06:51:54 +01:00
PARSE_error(212, (TEXT *)(IPTR) p[-1], 0);
2001-05-23 15:26:42 +02:00
/* msg 212: Unrecognized privilege \"%c\" or unrecognized identifier */
}
LEX_token();
}
return privileges;
}
static void revoke_user_privilege(void)
{
/**************************************
*
* r e v o k e _ u s e r _ p r i v i l e g e
*
**************************************
*
* Functional description
* Parse a SQL grant statement.
*
**************************************/
USERPRIV upriv = (USERPRIV) DDL_alloc(sizeof(userpriv));
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
while (true) {
if (PARSE_match(KW_ALL)) {
2001-05-23 15:26:42 +02:00
/* optional keyword following ALL */
PARSE_match(KW_PRIVILEGES);
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_select;
upriv->userpriv_flags |= USERPRIV_delete;
upriv->userpriv_flags |= USERPRIV_insert;
upriv->userpriv_flags |= USERPRIV_update;
}
else if (PARSE_match(KW_SELECT))
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_select;
else if (PARSE_match(KW_DELETE))
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_delete;
else if (PARSE_match(KW_INSERT))
2001-05-23 15:26:42 +02:00
upriv->userpriv_flags |= USERPRIV_insert;
else if (PARSE_match(KW_UPDATE)) {
2001-05-23 15:26:42 +02:00
/* revoke update privilege applies to all fields in the grant
update list */
upriv->userpriv_flags |= USERPRIV_update;
if (PARSE_match(KW_ON))
2001-05-23 15:26:42 +02:00
break;
if (PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
continue;
if (!PARSE_match(KW_LEFT_PAREN))
PARSE_error(315, dudleyGlob.DDL_token.tok_string, 0); /* msg 315: expected ON or '(', encountered "%s" */
2001-05-23 15:26:42 +02:00
do {
if (dudleyGlob.DDL_token.tok_keyword == KW_SELECT
|| dudleyGlob.DDL_token.tok_keyword == KW_INSERT
|| dudleyGlob.DDL_token.tok_keyword == KW_DELETE
|| dudleyGlob.DDL_token.tok_keyword == KW_UPDATE)
{
2001-05-23 15:26:42 +02:00
break;
}
UPFE upf = (UPFE) DDL_alloc(sizeof(upfe));
2001-05-23 15:26:42 +02:00
upf->upfe_fldname = PARSE_symbol(tok_ident);
upf->upfe_next = upriv->userpriv_upflist;
upriv->userpriv_upflist = upf;
} while (PARSE_match(KW_COMMA));
2001-05-23 15:26:42 +02:00
if (!PARSE_match(KW_RIGHT_PAREN))
PARSE_error(316, dudleyGlob.DDL_token.tok_string, 0); /* msg 316: expected ')', encountered "%s" */
2001-05-23 15:26:42 +02:00
continue;
}
if (!PARSE_match(KW_COMMA)) {
if (!PARSE_match(KW_ON))
PARSE_error(214, dudleyGlob.DDL_token.tok_string, 0); /* msg 214: expected ON, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
break;
}
2003-09-10 19:52:12 +02:00
} // while (true)
2001-05-23 15:26:42 +02:00
if (!upriv->userpriv_flags)
PARSE_error(215, 0, 0); /* msg 215: REVOKE privilege was not specified */
upriv->userpriv_relation = PARSE_symbol(tok_ident);
if (!PARSE_match(KW_FROM))
PARSE_error(216, dudleyGlob.DDL_token.tok_string, 0); /* msg 216: expected FROM, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
/* get the userlist */
2003-09-10 19:52:12 +02:00
while (true) {
USRE usr = (USRE) DDL_alloc(sizeof(usre));
2001-05-23 15:26:42 +02:00
usr->usre_name = PARSE_symbol(tok_ident);
usr->usre_next = upriv->userpriv_userlist;
upriv->userpriv_userlist = usr;
if (!PARSE_match(KW_COMMA))
2001-05-23 15:26:42 +02:00
break;
}
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_revoke, (DBB) upriv);
2001-05-23 15:26:42 +02:00
}
static SLONG score_entry( SCE element)
{
/**************************************
*
* s c o r e _ e n t r y
*
**************************************
*
* Functional description
* Compute a value to determine placement of an
* access control element in an Apollo access
* control list.
*
**************************************/
SLONG score = 0;
2001-05-23 15:26:42 +02:00
if (element->sce_idents[id_view])
score++;
const TEXT* const* ptr = (TEXT**) element->sce_idents;
for (const TEXT* const* const end = ptr + id_max; ptr < end;
ptr++)
{
2001-05-23 15:26:42 +02:00
score <<= 1;
if (*ptr)
score |= 1;
}
return score;
}
static DUDLEY_NOD set_generator(void)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s e t _ g e n e r a t o r
*
**************************************
*
* Functional description
* get the name and new value for generator
**************************************/
if (dudleyGlob.DDL_token.tok_type != tok_ident)
PARSE_error(274, dudleyGlob.DDL_token.tok_string, 0); /* msg 274: expected generator name, encountered \"%s\" */
2001-05-23 15:26:42 +02:00
DUDLEY_NOD node = PARSE_make_node(nod_set_generator, 2);
2001-05-23 15:26:42 +02:00
node->nod_count = 1;
node->nod_arg[1] = (DUDLEY_NOD) PARSE_symbol(tok_ident);
PARSE_match(KW_TO);
2003-09-10 19:52:12 +02:00
node->nod_arg[0] = EXPR_value(0, NULL);
2001-05-23 15:26:42 +02:00
parse_end();
2001-07-12 07:46:06 +02:00
make_action(act_s_generator, (DBB) node);
2002-04-04 07:36:37 +02:00
return 0;
2001-05-23 15:26:42 +02:00
}
static void sort_out_attributes(
DUDLEY_TRG trigger,
2001-05-23 15:26:42 +02:00
SLONG flags, SLONG type, SLONG sequence)
{
/**************************************
*
* s o r t _ o u t _ a t t r i b u t e s
*
**************************************
*
* Functional description
* Somebody is being very cute and changing
* attributes of a trigger. We're going to do
* it, but we'd better remember the other, unchanged
* attributes so we don't make a big mess.
*
**************************************/
trigger->trg_mflag = flags & ~trg_mflag_order;
if (flags & trg_mflag_type)
switch (trigger->trg_type) {
case trg_store:
case trg_post_store:
if (!(type & (trig_mod | trig_era)))
type |= trig_sto;
else if (!trigger->trg_statement && (type & trig_era))
PARSE_error(217, 0, 0); /* msg 217: Attempt change trigger type from STORE to ERASE */
break;
case trg_modify:
case trg_post_modify:
if (!(type & (trig_sto | trig_era)))
type |= trig_mod;
else if (!trigger->trg_statement)
if (type & trig_sto)
PARSE_error(218, 0, 0); /* msg 218: Attempt change trigger type from MODIFY to STORE */
else
PARSE_error(219, 0, 0); /* msg 219: Attempt change trigger type from MODIFY to ERASE */
break;
case trg_pre_erase:
case trg_erase:
if (!(type & (trig_sto | trig_mod)))
type |= trig_era;
else if (!trigger->trg_statement && (type & trig_sto))
PARSE_error(220, 0, 0); /* msg 220: Attempt to change trigger type from ERASE to STORE */
}
if ((!(flags & trg_mflag_order)) && (flags & trg_mflag_type))
switch (trigger->trg_type) {
case trg_erase:
case trg_post_modify:
case trg_post_store:
type |= trig_post;
break;
case trg_store:
case trg_modify:
case trg_pre_erase:
type &= ~trig_post;
}
if (trigger->trg_mflag & trg_mflag_type)
trigger->trg_type = trig_table[type & ~trig_inact];
if (trigger->trg_mflag & trg_mflag_seqnum)
trigger->trg_sequence = sequence;
if (trigger->trg_mflag & trg_mflag_onoff)
trigger->trg_inactive = type & trig_inact;
}
static TXT start_text(void)
{
/**************************************
*
* s t a r t _ t e x t
*
**************************************
*
* Functional description
* Make the current position to save description text.
*
**************************************/
TXT text = (TXT) DDL_alloc(sizeof(txt));
text->txt_position = dudleyGlob.DDL_token.tok_position - dudleyGlob.DDL_token.tok_length;
text->txt_start_line = dudleyGlob.DDL_line;
2001-05-23 15:26:42 +02:00
return text;
}
static void validate_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* v a l i d a t e _ f i e l d
*
**************************************
*
* Functional description
* Validate that the field clauses make sense
* together.
*
**************************************/
TEXT option[128];
*option = 0;
if (field->fld_flags & fld_local) {
if (field->fld_validation)
gds__msg_format(0, DDL_MSG_FAC, 221, sizeof(option), option, NULL,
NULL, NULL, NULL, NULL);
/* msg 221 /'valid if/' */
if (field->fld_missing)
gds__msg_format(0, DDL_MSG_FAC, 222, sizeof(option), option, NULL,
NULL, NULL, NULL, NULL);
/* msg 222: missing value */
if ((field->fld_dtype) && !(field->fld_computed))
gds__msg_format(0, DDL_MSG_FAC, 223, sizeof(option), option, NULL,
NULL, NULL, NULL, NULL);
/* msg 223: data type */
if ((field->fld_has_sub_type) && !(field->fld_computed))
gds__msg_format(0, DDL_MSG_FAC, 224, sizeof(option), option, NULL,
NULL, NULL, NULL, NULL);
/* msg 224: sub type */
if ((field->fld_segment_length) && !(field->fld_computed))
gds__msg_format(0, DDL_MSG_FAC, 225, sizeof(option), option, NULL,
NULL, NULL, NULL, NULL);
/* msg 225: segment_length */
if (*option)
PARSE_error(226, option, 0); /* msg 226: %s is a global, not local, attribute */
return;
}
if (field->fld_computed && !(field->fld_dtype))
PARSE_error(227, 0, 0); /* msg 227: computed fields need datatypes */
if (field->fld_flags & fld_modify)
return;
if ((field->fld_has_sub_type) &&
(field->fld_dtype != blr_blob) &&
(field->fld_dtype != blr_text) && (field->fld_dtype != blr_varying))
PARSE_error(228, 0, 0); /* msg 228: subtypes are valid only for blobs and text */
if (field->fld_segment_length && (field->fld_dtype != blr_blob))
PARSE_error(229, 0, 0); /* msg 229: segment length is valid only for blobs */
if ((field->fld_dtype == blr_blob) && !(field->fld_segment_length))
field->fld_segment_length = 80;
}