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-31 06:06:02 +01:00
|
|
|
*
|
|
|
|
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <stdlib.h>
|
2004-01-06 11:33:18 +01:00
|
|
|
#include <stdio.h> // a single call to sprintf()
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <string.h>
|
|
|
|
#define PARSER_MAIN
|
2003-11-08 00:27:24 +01:00
|
|
|
#include "../jrd/y_ref.h"
|
|
|
|
#include "../jrd/ibase.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/flags.h"
|
|
|
|
#include "../dudley/ddl.h"
|
|
|
|
#include "../dudley/parse.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> ";
|
2003-10-03 04:00:40 +02:00
|
|
|
const int GDS_NAME_LEN = 31;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-03 04:00:40 +02:00
|
|
|
const int MAX_DIMENSION = 16;
|
2003-03-09 03:25:58 +01:00
|
|
|
#ifdef FLINT_CACHE
|
2003-10-03 04:00:40 +02:00
|
|
|
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
|
|
|
|
|
|
|
#define STUFF(c) *p++ = c
|
|
|
|
#define STUFF_WORD(c) {STUFF (c); STUFF (c >> 8);}
|
|
|
|
#define STUFF_LONG(c) {STUFF (c); STUFF (c >> 8); STUFF (c >> 16); STUFF (c >> 24); }
|
|
|
|
|
|
|
|
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,
|
|
|
|
} OBJ_T;
|
|
|
|
|
2003-04-03 04:00:35 +02:00
|
|
|
/* 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-10-05 08:42:28 +02:00
|
|
|
extern const TEXT* DDL_prompt;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
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);
|
2002-11-30 18:45:02 +01:00
|
|
|
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);
|
|
|
|
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);
|
2002-11-17 01:04:19 +01:00
|
|
|
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*);
|
2002-11-30 18:45:02 +01:00
|
|
|
static DUDLEY_FLD lookup_global_field(DUDLEY_FLD);
|
2001-05-23 15:26:42 +02:00
|
|
|
static ACT make_action(enum act_t, DBB);
|
2002-11-30 18:45:02 +01:00
|
|
|
static ACT make_computed_field(DUDLEY_FLD);
|
2002-11-17 01:04:19 +01:00
|
|
|
static DUDLEY_CTX make_context(TEXT *, DUDLEY_REL);
|
2002-11-30 18:45:02 +01:00
|
|
|
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);
|
2002-11-17 01:04:19 +01:00
|
|
|
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);
|
2002-11-30 18:45:02 +01:00
|
|
|
static void parse_array(DUDLEY_FLD);
|
2001-05-23 15:26:42 +02:00
|
|
|
static TXT parse_description(void);
|
|
|
|
static void parse_end(void);
|
2002-11-30 18:45:02 +01:00
|
|
|
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);
|
2002-11-11 20:11:52 +01:00
|
|
|
static DUDLEY_NOD set_generator(void);
|
2002-11-17 01:04:19 +01:00
|
|
|
static void sort_out_attributes(DUDLEY_TRG, SLONG, SLONG, SLONG);
|
2001-05-23 15:26:42 +02:00
|
|
|
static TXT start_text(void);
|
2002-11-30 18:45:02 +01:00
|
|
|
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 (!DDL_eof && DDL_errors < 20) {
|
|
|
|
if ((!database || !database->dbb_handle) && (!DDL_drop_database)) {
|
|
|
|
DDL_err(111, NULL, NULL, NULL, NULL, NULL); /* msg 111: no database declared */
|
|
|
|
if (database) {
|
|
|
|
gds__free(database);
|
|
|
|
database = NULL;
|
|
|
|
}
|
|
|
|
if (DDL_interactive)
|
|
|
|
parse_action();
|
|
|
|
else {
|
|
|
|
DDL_err(112, NULL, NULL, NULL, NULL, NULL); /* msg 112: ceasing processing */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2003-09-10 19:52:12 +02:00
|
|
|
DDL_drop_database = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
parse_action();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PARSE_error( USHORT number, TEXT * arg1, TEXT * arg2)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* P A R S E _ e r r o r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Generate a syntax error.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
DDL_err(number, arg1, arg2, NULL, NULL, NULL);
|
2004-03-01 04:35:23 +01:00
|
|
|
Firebird::status_exception::raise();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FUNC PARSE_function( int flag)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
|
|
|
FUNC function;
|
|
|
|
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(113, DDL_token.tok_string, 0); /* msg 113: expected function, encountered \"%s\" */
|
|
|
|
|
|
|
|
symbol = HSH_typed_lookup(DDL_token.tok_string, DDL_token.tok_length,
|
|
|
|
SYM_function);
|
|
|
|
|
|
|
|
if (symbol && (function = (FUNC) symbol->sym_object) &&
|
|
|
|
function->func_database == database) {
|
|
|
|
LEX_token();
|
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flag)
|
|
|
|
PARSE_error(114, DDL_token.tok_string, 0); /* msg 114: expected function, encountered \"%s\" */
|
|
|
|
else {
|
2003-09-30 12:39:11 +02:00
|
|
|
function = (FUNC) DDL_alloc(sizeof(func));
|
2001-05-23 15:26:42 +02:00
|
|
|
function->func_name = symbol = PARSE_symbol(tok_ident);
|
|
|
|
symbol->sym_type = SYM_function;
|
2002-11-17 01:04:19 +01:00
|
|
|
symbol->sym_object = (DUDLEY_CTX) function;
|
2001-05-23 15:26:42 +02:00
|
|
|
HSH_insert(symbol);
|
|
|
|
|
|
|
|
if (!(function->func_database = database))
|
|
|
|
PARSE_error(111, 0, 0); /* msg 111: no database declared */
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
|
|
|
|
|
|
|
LEX_real();
|
|
|
|
|
|
|
|
for (symbol = DDL_token.tok_symbol; symbol; symbol = symbol->sym_homonym)
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-10-18 01:47:04 +02:00
|
|
|
DUDLEY_NOD node;
|
2004-02-02 12:02:12 +01:00
|
|
|
dudley_lls* temp;
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT count;
|
|
|
|
|
|
|
|
temp = stack;
|
|
|
|
count = 0;
|
|
|
|
|
|
|
|
while (temp) {
|
|
|
|
count++;
|
|
|
|
temp = temp->lls_next;
|
|
|
|
}
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
node = PARSE_make_node(nod_list, count);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
while (stack)
|
2003-10-18 01:47:04 +02:00
|
|
|
node->nod_arg[--count] = LLS_POP(&stack);
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-11 20:11:52 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-11 20:11:52 +01:00
|
|
|
DUDLEY_NOD node;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-11-11 20:11:52 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (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 (symbol = DDL_token.tok_symbol; symbol; symbol = symbol->sym_homonym)
|
|
|
|
if (symbol->sym_type == SYM_keyword &&
|
|
|
|
symbol->sym_keyword == (int) keyword) {
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SSHORT negate;
|
|
|
|
int number;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
negate = PARSE_match(KW_MINUS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (DDL_token.tok_type != tok_number)
|
|
|
|
PARSE_error(115, DDL_token.tok_string, 0); /* msg 115: expected number, encountered \"%s\" */
|
|
|
|
|
|
|
|
number = atoi(DDL_token.tok_string);
|
|
|
|
LEX_token();
|
|
|
|
|
|
|
|
if (negate)
|
|
|
|
return -number;
|
|
|
|
|
|
|
|
return number;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:04:19 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(116, DDL_token.tok_string, 0); /* msg 116: expected relation name, encountered \"%s\" */
|
|
|
|
|
|
|
|
symbol = HSH_typed_lookup(DDL_token.tok_string, DDL_token.tok_length,
|
|
|
|
SYM_relation);
|
2002-11-17 01:04:19 +01:00
|
|
|
if (symbol && (relation = (DUDLEY_REL) symbol->sym_object) &&
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_database == database) {
|
|
|
|
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;
|
2002-11-17 01:04:19 +01:00
|
|
|
symbol->sym_object = (DUDLEY_CTX) relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!(relation->rel_database = database))
|
|
|
|
PARSE_error(111, 0, 0); /* msg 111: no database declared */
|
|
|
|
|
|
|
|
relation->rel_next = database->dbb_relations;
|
|
|
|
database->dbb_relations = relation;
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
|
|
|
TEXT c, *p, *q;
|
|
|
|
USHORT l;
|
|
|
|
|
|
|
|
if (DDL_token.tok_type != type)
|
|
|
|
switch (type) {
|
|
|
|
case tok_ident:
|
|
|
|
PARSE_error(117, DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
|
|
|
|
case tok_quoted:
|
|
|
|
PARSE_error(118, DDL_token.tok_string, 0); /* msg 118: expected quoted string, encountered \"%s\" */
|
|
|
|
default:
|
|
|
|
PARSE_error(119, DDL_token.tok_string, 0); /* msg 119: expected symbol, encountered \"%s\" */
|
|
|
|
}
|
|
|
|
l = DDL_token.tok_length;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
|
|
|
|
if (type == tok_quoted) {
|
|
|
|
if (l < 2)
|
|
|
|
PARSE_error(118, DDL_token.tok_string, 0); /* msg 118: expected quoted string, encountered \"%s\" */
|
|
|
|
q++;
|
|
|
|
l -= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
symbol = (SYM) DDL_alloc(SYM_LEN + l);
|
|
|
|
symbol->sym_length = l;
|
|
|
|
p = symbol->sym_string = symbol->sym_name;
|
|
|
|
|
|
|
|
if (l)
|
|
|
|
if (type == tok_ident)
|
|
|
|
do {
|
|
|
|
c = *q++;
|
|
|
|
*p++ = UPPER(c);
|
|
|
|
}
|
|
|
|
while (--l);
|
|
|
|
else
|
|
|
|
do
|
|
|
|
*p++ = *q++;
|
|
|
|
while (--l);
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
USHORT l;
|
|
|
|
TEXT file_name[256], *p, *q;
|
|
|
|
|
|
|
|
if (!(l = name->sym_length))
|
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);
|
|
|
|
for (p = file_name, q = name->sym_string; l--; *p++ = *q++);
|
|
|
|
*p = 0;
|
|
|
|
|
|
|
|
for (p = file_name; *p; p++)
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2003-11-07 09:06:35 +01: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;
|
|
|
|
|
|
|
|
new_name = (SYM) DDL_alloc(SYM_LEN + old_name->sym_length);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD global_field;
|
2001-05-23 15:26:42 +02:00
|
|
|
SYM old_name, new_name;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
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 {
|
|
|
|
old_name = local_field->fld_name;
|
|
|
|
global_field->fld_name = new_name = copy_symbol(old_name);
|
|
|
|
new_name->sym_type = SYM_global;
|
2002-11-17 01:04:19 +01:00
|
|
|
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;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
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 */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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 */
|
2003-10-18 01:47:04 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
FIL file;
|
|
|
|
SYM symbol;
|
|
|
|
|
|
|
|
if (database)
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
database = (DBB) DDL_alloc(sizeof(dbb));
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_name = PARSE_symbol(tok_quoted);
|
|
|
|
DB_file_name = database->dbb_name->sym_name;
|
|
|
|
database->dbb_grp_cmt_wait = -1; /* Initialized for default value */
|
|
|
|
|
|
|
|
/* parse options for the database parameter block */
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_LENGTH)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_length = PARSE_number();
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_PAGES);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_USER)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
symbol = PARSE_symbol(tok_quoted);
|
|
|
|
DDL_default_user = symbol->sym_name;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_PASSWORD)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
symbol = PARSE_symbol(tok_quoted);
|
|
|
|
DDL_default_password = symbol->sym_name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action_type == act_d_database) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_CASCADE))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_flags |= DBB_cascade;
|
|
|
|
EXE_drop_database(database);
|
2003-09-10 19:52:12 +02:00
|
|
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_ADD);
|
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_description = parse_description();
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_SECURITY_CLASS))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_security_class = PARSE_symbol(tok_ident);
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_DROP)) {
|
|
|
|
if (PARSE_match(KW_DESCRIP))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_flags |= DBB_null_description;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_SECURITY_CLASS))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_flags |= DBB_null_security_class;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_LOG_FILE)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((database->dbb_flags & DBB_log_default)
|
|
|
|
|| (database->dbb_logfiles)) PARSE_error(337, 0, 0);
|
|
|
|
|
|
|
|
database->dbb_flags |= DBB_drop_log;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_CASCADE))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_flags |= DBB_cascade;
|
|
|
|
#ifdef FLINT_CACHE
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_CACHE))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_flags |= DBB_drop_cache;
|
|
|
|
#endif /* FLINT_CACHE */
|
|
|
|
else
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_error(121, 0, 0);
|
|
|
|
// msg 121 only SECURITY_CLASS, DESCRIPTION and CACHE can be dropped
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_FILE)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
file = define_file();
|
|
|
|
file->fil_next = database->dbb_files;
|
|
|
|
database->dbb_files = file;
|
|
|
|
}
|
2003-10-18 01:47:04 +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 */
|
|
|
|
database->dbb_page_size = parse_page_size();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_CHECK_POINT_LEN)) {
|
|
|
|
PARSE_match(KW_EQUALS);
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_chkptlen = PARSE_number();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_NUM_LOG_BUFS)) {
|
|
|
|
PARSE_match(KW_EQUALS);
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_numbufs = PARSE_number();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_LOG_BUF_SIZE)) {
|
|
|
|
PARSE_match(KW_EQUALS);
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_bufsize = PARSE_number();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_GROUP_COMMIT_WAIT)) {
|
|
|
|
PARSE_match(KW_EQUALS);
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_grp_cmt_wait = PARSE_number();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_LOG_FILE)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((database->dbb_flags & DBB_log_default)
|
|
|
|
|| (database->dbb_logfiles)) PARSE_error(338, 0, 0);
|
|
|
|
|
|
|
|
if (database->dbb_flags & DBB_drop_log)
|
|
|
|
PARSE_error(337, 0, 0);
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_LEFT_PAREN)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_flags |= DBB_log_preallocated;
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2001-05-23 15:26:42 +02:00
|
|
|
file = define_log_file(DBB_log_preallocated);
|
|
|
|
file->fil_next = database->dbb_logfiles;
|
|
|
|
database->dbb_logfiles = file;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_RIGHT_PAREN))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(341, DDL_token.tok_string, 0); /* msg 341: expected comma or ')', encountered \"%s\" */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_OVERFLOW))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_overflow = define_log_file(DBB_log_serial);
|
|
|
|
else
|
|
|
|
PARSE_error(340, 0, 0);
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_BASE_NAME)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_flags |= DBB_log_serial;
|
|
|
|
database->dbb_logfiles = define_log_file(DBB_log_serial);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
database->dbb_flags |= DBB_log_default;
|
|
|
|
}
|
|
|
|
#ifdef FLINT_CACHE
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_CACHE))
|
2001-05-23 15:26:42 +02:00
|
|
|
database->dbb_cache_file = define_cache();
|
|
|
|
#endif /* FLINT_CACHE */
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_end();
|
|
|
|
|
|
|
|
if (action_type == act_c_database) {
|
|
|
|
database->dbb_flags |= DBB_create_database;
|
|
|
|
EXE_create_database(database);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
EXE_modify_database(database);
|
|
|
|
}
|
|
|
|
|
|
|
|
make_action(action_type, database);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void define_field(void)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* d e f i n e _ f i e l d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Parse a DEFINE FIELD statement.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD field;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
|
2001-05-23 15:26:42 +02:00
|
|
|
parse_field(field);
|
|
|
|
field->fld_database = database;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_LENGTH)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
file->fil_length = PARSE_number();
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_PAGES);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-10-18 01:47:04 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-09-30 12:39:11 +02:00
|
|
|
FILTER new_filter;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(126, DDL_token.tok_string, 0); /* msg 126: expected filter name, encountered \"%s\" */
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
new_filter = (FILTER) DDL_alloc(sizeof(filter));
|
|
|
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2003-09-30 12:39:11 +02:00
|
|
|
new_filter->filter_description = parse_description();
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_INPUT_TYPE))
|
2003-09-30 12:39:11 +02:00
|
|
|
new_filter->filter_input_sub_type = PARSE_number();
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_OUTPUT_TYPE))
|
2003-09-30 12:39:11 +02:00
|
|
|
new_filter->filter_output_sub_type = PARSE_number();
|
2003-10-18 01:47:04 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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 */
|
|
|
|
|
2002-10-31 06:06:02 +01:00
|
|
|
#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;
|
|
|
|
FUNCARG function_arg;
|
|
|
|
SSHORT position;
|
|
|
|
|
|
|
|
function = PARSE_function(FALSE);
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
function->func_description = parse_description();
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_FUNCTION_MODULE_NAME))
|
2001-05-23 15:26:42 +02:00
|
|
|
function->func_module_name = PARSE_symbol(tok_quoted);
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_FUNCTION_ENTRY_POINT))
|
2001-05-23 15:26:42 +02:00
|
|
|
function->func_entry_point = PARSE_symbol(tok_quoted);
|
2003-10-18 01:47:04 +02:00
|
|
|
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 */
|
|
|
|
|
2002-10-31 06:06:02 +01:00
|
|
|
#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 */
|
|
|
|
|
|
|
|
position = 1;
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_SEMI)
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2001-07-12 07:46:06 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(DDL_token.tok_keyword == KW_SEMI))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(132, DDL_token.tok_string, 0); /* msg 132: expected comma or semi-colon, encountered \"%s\" */
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
|
|
|
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(274, DDL_token.tok_string, 0); /* msg 274: expected generator name, encountered \"%s\" */
|
|
|
|
|
|
|
|
symbol = PARSE_symbol(tok_ident);
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-02-02 12:02:12 +01:00
|
|
|
dudley_lls* stack;
|
2003-10-18 01:47:04 +02:00
|
|
|
SYM index_name, rel_name;
|
2003-09-10 19:52:12 +02:00
|
|
|
TXT description = NULL;
|
|
|
|
SSHORT count;
|
|
|
|
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
|
|
|
|
|
|
|
index_name = PARSE_symbol(tok_ident);
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_FOR);
|
2001-05-23 15:26:42 +02:00
|
|
|
rel_name = PARSE_symbol(tok_ident);
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_DUPLICATES))
|
2003-09-10 19:52:12 +02:00
|
|
|
unique = false;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_UNIQUE))
|
2003-09-10 19:52:12 +02:00
|
|
|
unique = true;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
description = parse_description();
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_ACTIVE))
|
2003-09-10 19:52:12 +02:00
|
|
|
inactive = false;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_INACTIVE))
|
2003-09-10 19:52:12 +02:00
|
|
|
inactive = true;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_ASCENDING))
|
2003-09-15 04:15:27 +02:00
|
|
|
descending = IDX_type_none;
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
|
|
|
|
stack = NULL;
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-03 04:00:40 +02:00
|
|
|
LLS_PUSH((DUDLEY_NOD) PARSE_symbol(tok_ident), &stack);
|
2001-05-23 15:26:42 +02:00
|
|
|
count++;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(DDL_token.tok_keyword == KW_SEMI))
|
|
|
|
PARSE_error(135, 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)
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
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))
|
2003-10-18 01:47:04 +02:00
|
|
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_SIZE)) {
|
|
|
|
PARSE_match(KW_EQUALS);
|
2001-05-23 15:26:42 +02:00
|
|
|
file->fil_length = PARSE_number();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_RAW_PARTITIONS)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (log_type != DBB_log_preallocated)
|
2003-10-18 01:47:04 +02:00
|
|
|
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 */
|
|
|
|
|
|
|
|
if (file->fil_partitions) {
|
|
|
|
if (!file->fil_length)
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
|
|
|
DUDLEY_TRG trigger;
|
2001-05-23 15:26:42 +02:00
|
|
|
SYM name;
|
|
|
|
|
|
|
|
trigger = NULL;
|
|
|
|
relation = PARSE_relation();
|
|
|
|
|
2003-10-18 01:47:04 +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;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_STORE))
|
2001-05-23 15:26:42 +02:00
|
|
|
trigger->trg_type = trg_store;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_MODIFY))
|
2001-05-23 15:26:42 +02:00
|
|
|
trigger->trg_type = trg_modify;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_ERASE))
|
2001-05-23 15:26:42 +02:00
|
|
|
trigger->trg_type = trg_erase;
|
|
|
|
else
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_error(136, 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;
|
2002-11-17 01:04:19 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD field, global;
|
2001-05-23 15:26:42 +02:00
|
|
|
SSHORT position;
|
|
|
|
ACT rel_actions, action;
|
|
|
|
|
|
|
|
relation = PARSE_relation();
|
|
|
|
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
|
|
|
|
2003-10-18 01:47:04 +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
|
|
|
}
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
rel_actions = action = make_action(act_a_relation, (DBB) relation);
|
2001-05-23 15:26:42 +02:00
|
|
|
action->act_flags |= ACT_ignore;
|
|
|
|
position = 1;
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true)
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_description = parse_description();
|
2003-10-18 01:47:04 +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-10-18 01:47:04 +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;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Gobble fields */
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_ADD);
|
|
|
|
PARSE_match(KW_FIELD);
|
2003-09-30 12:39:11 +02:00
|
|
|
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 = database;
|
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(DDL_token.tok_keyword == KW_SEMI))
|
|
|
|
PARSE_error(138, DDL_token.tok_string, 0);
|
|
|
|
// msg 138: expected comma or semi-colon, encountered \"%s\"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-18 01:47:04 +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 class_;
|
|
|
|
SCE element, *next;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
class_ = (SCL) DDL_alloc(sizeof(scl));
|
2001-05-23 15:26:42 +02:00
|
|
|
class_->scl_name = PARSE_symbol(tok_ident);
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
class_->scl_description = parse_description();
|
|
|
|
|
|
|
|
/* Pick up entries. Use the users's order */
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!(element = parse_identifier()))
|
|
|
|
return;
|
|
|
|
for (next = &class_->scl_entries; *next; next = &(*next)->sce_next);
|
|
|
|
*next = element;
|
|
|
|
element->sce_privileges = parse_privileges();
|
2003-10-18 01:47:04 +02:00
|
|
|
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_a_security, (DBB) 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, file;
|
|
|
|
int number;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
shadow = (FIL) DDL_alloc(sizeof(fil));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* get the shadow number, defaulting to 1 */
|
|
|
|
|
|
|
|
if (DDL_token.tok_type != tok_number)
|
|
|
|
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 */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_MANUAL))
|
2001-05-23 15:26:42 +02:00
|
|
|
shadow->fil_manual = 1;
|
|
|
|
else
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_AUTO);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-18 01:47:04 +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))
|
2003-10-18 01:47:04 +02:00
|
|
|
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-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_LENGTH)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
shadow->fil_length = PARSE_number();
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_PAGES);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_FILE)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
file = define_file();
|
|
|
|
file->fil_next = shadow;
|
|
|
|
shadow = file;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_end();
|
|
|
|
|
|
|
|
for (file = shadow; file; file = file->fil_next)
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_TRG trigger;
|
2001-05-23 15:26:42 +02:00
|
|
|
TRGMSG trigmsg;
|
|
|
|
int flags, trg_state, trg_sequence;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_FOR)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
define_old_trigger();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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_name = PARSE_symbol(tok_ident);
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_FOR);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
trigger->trg_relation = PARSE_relation();
|
|
|
|
|
2003-04-03 04:00:35 +02:00
|
|
|
flags = trg_state = 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 */
|
2003-08-19 10:59:45 +02:00
|
|
|
PARSE_error(141, DDL_token.tok_string, 0);
|
|
|
|
/* 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
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
while (!(DDL_token.tok_keyword == KW_SEMI)) {
|
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
trigger->trg_description = parse_description();
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_MESSAGE)) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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)
|
2003-08-19 10:59:45 +02:00
|
|
|
PARSE_error(142, (TEXT *)(SLONG)(trigmsg->trgmsg_number), 0);
|
|
|
|
/* msg 142: message number %d exceeds 255 */
|
2003-10-18 01:47:04 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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)
|
2003-08-19 10:59:45 +02:00
|
|
|
PARSE_error(304, DDL_token.tok_string, 0);
|
|
|
|
/* msg 304: expected message keyword, encountered \"%s\" */
|
2001-05-23 15:26:42 +02:00
|
|
|
else if (!action)
|
2003-08-19 10:59:45 +02:00
|
|
|
PARSE_error(305, DDL_token.tok_string, 0);
|
|
|
|
/* msg 305: expected trigger action, encountered \"%s\" */
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2003-08-19 10:59:45 +02:00
|
|
|
PARSE_error(306, DDL_token.tok_string, 0);
|
|
|
|
/* 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;
|
2002-11-17 01:04:19 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM fldname;
|
|
|
|
TYP fldtype;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_FOR);
|
2001-05-23 15:26:42 +02:00
|
|
|
fldname = PARSE_symbol(tok_ident);
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_COLON);
|
2001-05-23 15:26:42 +02:00
|
|
|
fldtype->typ_type = PARSE_number();
|
2003-10-18 01:47:04 +02:00
|
|
|
if (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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD field, *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
SYM symbol;
|
|
|
|
SSHORT position;
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_CTX context, my_context;
|
2004-02-02 12:02:12 +01:00
|
|
|
dudley_lls* contexts;
|
2001-05-23 15:26:42 +02:00
|
|
|
ACT rel_actions, action;
|
|
|
|
|
|
|
|
/* Pick up relation name */
|
|
|
|
|
|
|
|
relation = PARSE_relation();
|
|
|
|
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
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_OF);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* Parse record selection expression */
|
|
|
|
|
|
|
|
contexts = NULL;
|
|
|
|
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];
|
2001-05-23 15:26:42 +02:00
|
|
|
my_context = make_context(0, relation);
|
2003-10-03 04:00:40 +02:00
|
|
|
LLS_PUSH((DUDLEY_NOD) my_context, &contexts);
|
2002-11-11 20:11:52 +01:00
|
|
|
relation->rel_rse->nod_arg[s_rse_contexts] = (DUDLEY_NOD) contexts;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
rel_actions = action = make_action(act_a_relation, (DBB) relation);
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_description = parse_description();
|
2003-10-18 01:47:04 +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-10-18 01:47:04 +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;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Gobble fields */
|
|
|
|
|
|
|
|
position = 1;
|
|
|
|
ptr = &relation->rel_fields;
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_ADD);
|
|
|
|
PARSE_match(KW_FIELD);
|
2003-09-30 12:39:11 +02:00
|
|
|
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;
|
|
|
|
field->fld_name = symbol = PARSE_symbol(tok_ident);
|
|
|
|
if (context = lookup_context(symbol, contexts)) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_DOT))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(144, DDL_token.tok_string, 0); /* msg 144: expected period, encountered \"%s\" */
|
|
|
|
field->fld_name = field->fld_base = PARSE_symbol(tok_ident);
|
|
|
|
}
|
|
|
|
else {
|
2003-10-18 01:47:04 +02:00
|
|
|
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, DDL_token.tok_string, 0);
|
|
|
|
/* msg 145: expected qualified field name, encountered \"%s\" */
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_DOT))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(146, DDL_token.tok_string, 0);
|
|
|
|
/* 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 */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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, DDL_token.tok_string, 0);
|
|
|
|
/* 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;
|
2002-11-17 01:04:19 +01:00
|
|
|
field->fld_name->sym_object = (DUDLEY_CTX) field;
|
2001-05-23 15:26:42 +02:00
|
|
|
HSH_insert(field->fld_name);
|
2003-10-18 01:47:04 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-09-30 12:39:11 +02:00
|
|
|
FILTER filter_to_drop;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
filter_to_drop = (FILTER) DDL_alloc(sizeof(filter));
|
|
|
|
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;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD field;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
relation = PARSE_relation();
|
|
|
|
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 class_;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
class_ = (SCL) DDL_alloc(sizeof(scl));
|
2001-05-23 15:26:42 +02:00
|
|
|
class_->scl_name = PARSE_symbol(tok_ident);
|
|
|
|
parse_end();
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
make_action(act_d_security, (DBB) 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int number;
|
|
|
|
|
|
|
|
number = PARSE_number();
|
|
|
|
parse_end();
|
|
|
|
|
|
|
|
make_action(act_d_shadow, (DBB) number);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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).
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM name;
|
2003-09-10 19:52:12 +02:00
|
|
|
bool old_style;
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
|
|
|
DUDLEY_TRG trigger;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_FOR)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
relation = PARSE_relation();
|
2003-09-10 19:52:12 +02:00
|
|
|
old_style = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
2003-09-10 19:52:12 +02:00
|
|
|
old_style = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
name = PARSE_symbol(tok_ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old_style) {
|
2003-10-18 01:47:04 +02:00
|
|
|
while (!PARSE_match(KW_END_TRIGGER)) {
|
2003-09-30 12:39:11 +02:00
|
|
|
trigger = (DUDLEY_TRG) DDL_alloc(sizeof(dudley_trg));
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_STORE))
|
2001-05-23 15:26:42 +02:00
|
|
|
trigger->trg_type = trg_store;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_MODIFY))
|
2001-05-23 15:26:42 +02:00
|
|
|
trigger->trg_type = trg_modify;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_ERASE))
|
2001-05-23 15:26:42 +02:00
|
|
|
trigger->trg_type = trg_erase;
|
|
|
|
else
|
|
|
|
PARSE_error(153, DDL_token.tok_string, 0);
|
|
|
|
/* msg 153: "expected STORE, MODIFY, ERASE, or END_TRIGGER, encountered \"%s\" */
|
|
|
|
trigger->trg_name = name =
|
|
|
|
gen_trigger_name(trigger->trg_type, relation);
|
|
|
|
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 {
|
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_name = name;
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM fldname;
|
|
|
|
TYP fldtype;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_FOR);
|
|
|
|
if (PARSE_match(KW_ALL)) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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);
|
2001-07-12 07:46:06 +02:00
|
|
|
make_action(act_d_type, (DBB) fldtype);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
fldname = PARSE_symbol(tok_ident);
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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 =
|
|
|
|
DDL_token.tok_position - DDL_token.tok_length - text->txt_position;
|
|
|
|
|
2002-10-31 06:06:02 +01: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 -= (DDL_line - text->txt_start_line);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:04:19 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TEXT *p, *q, *end;
|
|
|
|
SYM symbol;
|
|
|
|
|
|
|
|
symbol = (SYM) DDL_alloc(SYM_LEN + GDS_NAME_LEN);
|
|
|
|
symbol->sym_string = symbol->sym_name;
|
|
|
|
p = symbol->sym_string;
|
|
|
|
end = p + GDS_NAME_LEN;
|
|
|
|
|
|
|
|
/* Start by copying relation name */
|
|
|
|
|
|
|
|
q = relation->rel_name->sym_string;
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SSHORT number;
|
|
|
|
|
|
|
|
number = PARSE_number();
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_INACTIVE)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
*flags |= trg_mflag_onoff;
|
|
|
|
*type |= trig_inact;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_ACTIVE))
|
2001-05-23 15:26:42 +02:00
|
|
|
*flags |= trg_mflag_onoff;
|
|
|
|
|
|
|
|
*flags |= trg_mflag_order;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_PRE_STORE))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_sto;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_PRE_MODIFY))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_mod;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_PRE_ERASE))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_era;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (!(PARSE_match(KW_PRE))) {
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_post;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_POST_STORE))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_sto;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_POST_MODIFY))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_mod;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_POST_ERASE))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_era;
|
2003-10-18 01:47:04 +02:00
|
|
|
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))) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_STORE))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_sto;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_MODIFY))
|
2001-05-23 15:26:42 +02:00
|
|
|
*type |= trig_mod;
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
UPFE upf;
|
|
|
|
USRE usr;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
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 */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_ALL)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
/* optional keyword following ALL */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_ON))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(159, DDL_token.tok_string, 0); /* msg 159: expected ON, encountered \"%s\" */
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_SELECT))
|
2001-05-23 15:26:42 +02:00
|
|
|
upriv->userpriv_flags |= USERPRIV_select;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_DELETE))
|
2001-05-23 15:26:42 +02:00
|
|
|
upriv->userpriv_flags |= USERPRIV_delete;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_INSERT))
|
2001-05-23 15:26:42 +02:00
|
|
|
upriv->userpriv_flags |= USERPRIV_insert;
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_ON))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_LEFT_PAREN))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(313, DDL_token.tok_string, 0); /* msg 313: expected ON or '(', encountered "%s" */
|
|
|
|
|
|
|
|
do {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_SELECT
|
|
|
|
|| DDL_token.tok_keyword == KW_INSERT
|
|
|
|
|| DDL_token.tok_keyword == KW_DELETE
|
|
|
|
|| DDL_token.tok_keyword == KW_UPDATE)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2003-10-18 01:47:04 +02:00
|
|
|
}
|
2003-09-30 12:39:11 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
} while (PARSE_match(KW_COMMA));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_RIGHT_PAREN))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(314, DDL_token.tok_string, 0); /* msg 314: expected ')', encountered "%s" */
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA)) {
|
|
|
|
if (!PARSE_match(KW_ON))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(159, DDL_token.tok_string, 0); /* msg 159: expected ON, encountered \"%s\" */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!upriv->userpriv_flags)
|
|
|
|
PARSE_error(160, 0, 0); /* msg 160: GRANT privilege was not specified */
|
|
|
|
|
|
|
|
upriv->userpriv_relation = PARSE_symbol(tok_ident);
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_TO))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(161, DDL_token.tok_string, 0); /* msg 161: expected TO, encountered "%s" */
|
|
|
|
|
|
|
|
/* get the userlist */
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for the optional WITH GRANT OPTION specification */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_WITH)) {
|
|
|
|
if (!PARSE_match(KW_GRANT))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(162, DDL_token.tok_string, 0); /* msg 162:expected GRANT, encountered \"%s\" */
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_OPTION))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(163, DDL_token.tok_string, 0); /* msg 163: expected OPTION, encountered \"%s\" */
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_CTX context;
|
2001-05-23 15:26:42 +02:00
|
|
|
SYM name;
|
|
|
|
|
|
|
|
/* If no name is given, look for a nameless one. */
|
|
|
|
|
|
|
|
if (!symbol) {
|
|
|
|
for (; contexts; contexts = contexts->lls_next) {
|
2002-11-17 01:04:19 +01:00
|
|
|
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) {
|
2002-11-17 01:04:19 +01:00
|
|
|
context = (DUDLEY_CTX) contexts->lls_object;
|
2001-05-23 15:26:42 +02:00
|
|
|
if ((name = context->ctx_name) &&
|
|
|
|
!strcmp(name->sym_string, symbol->sym_string)) return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01:00
|
|
|
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
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol, name;
|
|
|
|
|
|
|
|
/* Find symbol */
|
|
|
|
|
|
|
|
name = (field->fld_source) ? field->fld_source : field->fld_name;
|
|
|
|
|
|
|
|
if (symbol = HSH_typed_lookup(name->sym_string, name->sym_length,
|
|
|
|
SYM_global))
|
2002-11-30 18:45:02 +01:00
|
|
|
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;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
action = (ACT) DDL_alloc(sizeof(act));
|
2001-05-23 15:26:42 +02:00
|
|
|
action->act_type = type;
|
|
|
|
action->act_next = DDL_actions;
|
|
|
|
action->act_object = object;
|
|
|
|
action->act_line = DDL_line;
|
|
|
|
DDL_actions = action;
|
|
|
|
|
|
|
|
return action;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01:00
|
|
|
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
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD computed;
|
2001-05-23 15:26:42 +02:00
|
|
|
SYM symbol;
|
|
|
|
TEXT s[64];
|
|
|
|
USHORT i, l;
|
|
|
|
|
|
|
|
/* Start by generating a unique name */
|
|
|
|
|
|
|
|
for (i = 1;; i++) {
|
|
|
|
sprintf(s, "RDB$%d", i);
|
|
|
|
l = strlen(s);
|
|
|
|
if (!HSH_lookup(s, l))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make up new symbol block */
|
|
|
|
|
|
|
|
field->fld_source = symbol = (SYM) DDL_alloc(SYM_LEN + l);
|
|
|
|
symbol->sym_type = SYM_global;
|
|
|
|
symbol->sym_length = l;
|
|
|
|
symbol->sym_string = symbol->sym_name;
|
|
|
|
strcpy(symbol->sym_name, s);
|
|
|
|
|
|
|
|
field->fld_source_field = computed = create_global_field(field);
|
2002-11-17 01:04:19 +01:00
|
|
|
symbol->sym_object = (DUDLEY_CTX) computed;
|
2001-05-23 15:26:42 +02:00
|
|
|
return make_global_field(computed);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:04:19 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_CTX context;
|
2001-05-23 15:26:42 +02:00
|
|
|
SYM symbol;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
context = (DUDLEY_CTX) DDL_alloc(sizeof(dudley_ctx));
|
2001-05-23 15:26:42 +02:00
|
|
|
context->ctx_relation = relation;
|
|
|
|
|
|
|
|
if (string) {
|
|
|
|
context->ctx_name = symbol = (SYM) DDL_alloc(SYM_LEN);
|
|
|
|
symbol->sym_object = context;
|
|
|
|
symbol->sym_string = string;
|
|
|
|
symbol->sym_length = strlen(string);
|
|
|
|
symbol->sym_type = SYM_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01:00
|
|
|
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
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
|
|
|
|
|
|
|
/* Make sure symbol is unique */
|
|
|
|
|
|
|
|
symbol = field->fld_name;
|
2002-11-17 01:04:19 +01:00
|
|
|
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)
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
|
|
|
DUDLEY_TRG trigger;
|
2001-05-23 15:26:42 +02:00
|
|
|
int flags, type, sequence;
|
|
|
|
SYM name, symbol;
|
|
|
|
|
|
|
|
relation = PARSE_relation();
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
while (!PARSE_match(KW_END_TRIGGER)) {
|
2003-04-03 04:00:35 +02:00
|
|
|
flags = type = sequence = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
get_trigger_attributes(&flags, &type, &sequence);
|
|
|
|
if (!type)
|
|
|
|
PARSE_error(165, DDL_token.tok_string, 0); /* msg 165: expected STORE, MODIFY, ERASE, END_TRIGGER, encountered \"%s\" */
|
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;
|
|
|
|
trigger->trg_mflag = flags & ~trg_mflag_order;
|
|
|
|
if (trigger->trg_mflag & trg_mflag_type)
|
|
|
|
trigger->trg_type = trig_table[type & ~trig_inact];
|
|
|
|
trigger->trg_name = name =
|
|
|
|
gen_trigger_name(trigger->trg_type, relation);
|
|
|
|
if (!
|
|
|
|
(symbol =
|
|
|
|
HSH_typed_lookup(name->sym_string, name->sym_length,
|
|
|
|
SYM_trigger))) PARSE_error(166,
|
|
|
|
name->sym_string, 0); /* msg 166: Trigger %s does not exist */
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM symbol;
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD field;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!local_context)
|
2003-10-03 04:00:40 +02:00
|
|
|
LLS_PUSH((DUDLEY_NOD) DDL_alloc(sizeof(dudley_ctx)), &local_context);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* Lookup global field */
|
|
|
|
|
|
|
|
for (symbol = DDL_token.tok_symbol; symbol; symbol = symbol->sym_homonym)
|
|
|
|
if (symbol->sym_type == SYM_global)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (!symbol)
|
|
|
|
PARSE_error(167, DDL_token.tok_string, 0); /*msg 167: expected global field name, encountered \"%s\" */
|
2002-11-30 18:45:02 +01:00
|
|
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (DDL_token.tok_keyword == KW_DESCRIPTION) {
|
2001-05-23 15:26:42 +02:00
|
|
|
index->idx_description = parse_description();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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, DDL_token.tok_string, 0); /*msg 172: expected DESCRIPTION, encountered \"%s\" */
|
|
|
|
}
|
2003-10-18 01:47:04 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD field, global;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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-10-18 01:47:04 +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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (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
|
|
|
}
|
2003-10-18 01:47:04 +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);
|
|
|
|
}
|
2003-10-18 01:47:04 +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
|
|
|
modify_relation = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Act on field actions */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(DDL_token.tok_keyword == KW_SEMI))
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_ADD)) {
|
|
|
|
PARSE_match(KW_FIELD);
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-09-30 12:39:11 +02:00
|
|
|
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 = database;
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_MODIFY)) {
|
|
|
|
PARSE_match(KW_FIELD);
|
2003-09-30 12:39:11 +02:00
|
|
|
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 = database;
|
|
|
|
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
|
|
|
}
|
2003-10-18 01:47:04 +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;
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_COMMA);
|
|
|
|
if (DDL_token.tok_keyword == KW_SEMI)
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_COMMA);
|
|
|
|
if (DDL_token.tok_keyword == KW_SEMI)
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else {
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_FIELD);
|
2003-09-30 12:39:11 +02:00
|
|
|
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 = database;
|
|
|
|
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, DDL_token.tok_string, 0); /* msg 174: expected field action, encountered \"%s\" */
|
2003-10-18 01:47:04 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SCL class_;
|
|
|
|
SCE element, *next;
|
|
|
|
USHORT score;
|
|
|
|
|
|
|
|
/* return error msg for now until fully coded */
|
|
|
|
|
|
|
|
PARSE_error(247, 0, 0); /* msg 247: action not implemented yet */
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
class_ = (SCL) DDL_alloc(sizeof(scl));
|
2001-05-23 15:26:42 +02:00
|
|
|
class_->scl_name = PARSE_symbol(tok_ident);
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_DESCRIPTION)
|
2001-05-23 15:26:42 +02:00
|
|
|
class_->scl_description = parse_description();
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!(element = parse_identifier()))
|
|
|
|
return;
|
|
|
|
score = score_entry(element);
|
|
|
|
for (next = &class_->scl_entries;; next = &(*next)->sce_next)
|
|
|
|
if (!*next || score > score_entry(*next)) {
|
|
|
|
element->sce_next = *next;
|
|
|
|
*next = element;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
element->sce_privileges = parse_privileges();
|
2003-10-18 01:47:04 +02:00
|
|
|
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_m_security, (DBB) 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).
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
|
|
|
DUDLEY_TRG trigger;
|
2001-05-23 15:26:42 +02:00
|
|
|
TRGMSG trigmsg;
|
|
|
|
TRGMSG_T msg_type;
|
|
|
|
SYM name;
|
2003-09-10 19:52:12 +02:00
|
|
|
bool action = false;
|
|
|
|
bool end = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
msg_type = trgmsg_none;
|
|
|
|
|
2003-10-18 01:47:04 +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 */
|
|
|
|
|
|
|
|
for (name = DDL_token.tok_symbol;
|
|
|
|
name && (name->sym_type != SYM_trigger); name = name->sym_homonym);
|
2003-09-10 19:52:12 +02:00
|
|
|
{
|
|
|
|
if (!name)
|
|
|
|
PARSE_error(176, DDL_token.tok_string, 0);
|
|
|
|
// msg 176: expected trigger name, encountered \"%s\"
|
|
|
|
}
|
2002-11-17 01:04:19 +01:00
|
|
|
trigger = (DUDLEY_TRG) name->sym_object;
|
2001-05-23 15:26:42 +02:00
|
|
|
LEX_token();
|
|
|
|
|
|
|
|
/* in case somebody compulsive specifies the relation name */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
while (!(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) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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)
|
2003-08-19 10:59:45 +02:00
|
|
|
PARSE_error(178, (TEXT *)(SLONG) trigmsg->trgmsg_number, 0);
|
|
|
|
/* 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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_COMMA);
|
2001-05-23 15:26:42 +02:00
|
|
|
msg_type = trgmsg_none;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_END_TRIGGER))
|
2003-09-10 19:52:12 +02:00
|
|
|
end = true;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (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, DDL_token.tok_string, 0);
|
|
|
|
/* 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-17 01:04:19 +01: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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SYM fldname;
|
|
|
|
TYP fldtype;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_FOR);
|
2001-05-23 15:26:42 +02:00
|
|
|
fldname = PARSE_symbol(tok_ident);
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_COLON);
|
2001-05-23 15:26:42 +02:00
|
|
|
fldtype->typ_type = PARSE_number();
|
2003-10-18 01:47:04 +02:00
|
|
|
if (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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-11-17 01:04:19 +01:00
|
|
|
DUDLEY_REL relation;
|
2003-02-05 20:35:02 +01:00
|
|
|
DUDLEY_FLD field;
|
2003-09-10 19:52:12 +02:00
|
|
|
bool view_modify = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (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
|
|
|
}
|
2003-10-18 01:47:04 +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
|
|
|
}
|
2003-10-18 01:47:04 +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 */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(DDL_token.tok_keyword == KW_SEMI))
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_MODIFY)) {
|
|
|
|
PARSE_match(KW_FIELD);
|
2003-09-30 12:39:11 +02:00
|
|
|
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 = database;
|
|
|
|
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
|
|
|
}
|
2003-10-18 01:47:04 +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;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_SEMI)
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_SEMI)
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else {
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_FIELD);
|
2003-09-30 12:39:11 +02:00
|
|
|
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 = database;
|
|
|
|
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, DDL_token.tok_string, 0);
|
|
|
|
/* msg 182: expected drop/modify of field or security class, encountered \"%s\" */
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
|
|
|
|
DDL_prompt = PROMPT;
|
|
|
|
LEX_token();
|
|
|
|
DDL_prompt = CONTINUATION;
|
|
|
|
if (DDL_eof)
|
2003-09-04 15:45:44 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-18 01:47:04 +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 (database) {
|
|
|
|
define_relation();
|
2003-09-04 15:45:44 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
PARSE_error(183, DDL_token.tok_string, 0); /* msg 183: expected object for DEFINE, encountered \"%s\" */
|
|
|
|
}
|
2003-10-18 01:47:04 +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, DDL_token.tok_string, 0);
|
|
|
|
/* msg 184: expected object for MODIFY, encountered \"%s\" */
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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, DDL_token.tok_string, 0);
|
|
|
|
/* msg 185: expected object for DROP, encountered \"%s\" */
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
}
|
2003-10-18 01:47:04 +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
|
|
|
}
|
2003-10-18 01:47:04 +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
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_SET)) {
|
|
|
|
if (!PARSE_match(KW_GENERATOR))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(318, DDL_token.tok_string, 0); /* msg 318: expected GENERATOR, encountered \"%s\" */
|
|
|
|
set_generator();
|
2003-09-04 15:45:44 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (DDL_interactive && DDL_token.tok_keyword == KW_EXIT) {
|
2003-09-10 19:52:12 +02:00
|
|
|
DDL_eof = true;
|
2003-09-04 15:45:44 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (DDL_interactive && DDL_token.tok_keyword == KW_QUIT) {
|
2003-09-10 19:52:12 +02:00
|
|
|
DDL_quit = DDL_eof = true;
|
2003-09-04 15:45:44 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
PARSE_error(186, 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&) {
|
2001-12-24 03:51:06 +01:00
|
|
|
if (DDL_interactive)
|
|
|
|
LEX_flush();
|
|
|
|
else
|
2003-10-18 01:47:04 +02:00
|
|
|
while (!DDL_eof && !(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
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01: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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SLONG n, *range, *end, *ptr, ranges[2 * MAX_DIMENSION];
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_LEFT_PAREN))
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* Pick up ranges */
|
|
|
|
|
|
|
|
for (range = ranges;;) {
|
|
|
|
++field->fld_dimension;
|
|
|
|
range[0] = 1;
|
|
|
|
range[1] = PARSE_number();
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_RIGHT_PAREN))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(189, DDL_token.tok_string, 0); /* msg 189: expected comma, encountered \"%s\" */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate and copy block to hold ranges */
|
|
|
|
|
|
|
|
n = field->fld_dimension * sizeof(SLONG) * 2;
|
|
|
|
field->fld_ranges = ptr = (SLONG *) DDL_alloc(n);
|
|
|
|
|
|
|
|
for (end = range, range = ranges; range < end;)
|
|
|
|
*ptr++ = *range++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TXT description;
|
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
DDL_description = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
description = start_text();
|
|
|
|
description->txt_position = DDL_token.tok_position;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
while (!DDL_eof && (!(DDL_token.tok_keyword == KW_END_DESCRIPTION)))
|
2001-05-23 15:26:42 +02:00
|
|
|
LEX_token();
|
|
|
|
|
|
|
|
if (DDL_eof)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
end_text(description);
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_END_DESCRIPTION);
|
2003-09-10 19:52:12 +02:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(DDL_token.tok_keyword == KW_SEMI))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(190, DDL_token.tok_string, 0); /* msg 190: expected semi-colon, encountered \"%s\" */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01: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);
|
2002-11-17 01:04:19 +01:00
|
|
|
field->fld_name->sym_object = (DUDLEY_CTX) field;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-18 01:47:04 +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);
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(DDL_token.tok_keyword == KW_COMMA) && !(DDL_token.tok_keyword == KW_SEMI))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(192, DDL_token.tok_string, 0); /* msg 192: expected field clause, encountered \"%s\" */
|
|
|
|
|
|
|
|
validate_field(field);
|
|
|
|
|
|
|
|
return field;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int n;
|
2004-02-02 12:02:12 +01:00
|
|
|
dudley_lls* stack;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* 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();
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_SECURITY_CLASS))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_flags |= fld_null_security_class;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_VALID_IF))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_flags |= fld_null_validation;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_DESCRIP))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_flags |= fld_null_description;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_QUERY_NAME))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_flags |= fld_null_query_name;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_QUERY_HEADER))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_flags |= fld_null_query_header;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_EDIT_STRING))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_flags |= fld_null_edit_string;
|
2003-10-18 01:47:04 +02:00
|
|
|
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, DDL_token.tok_string, 0);
|
|
|
|
/* msg 193: expected DESCRIPTION, EDIT_STRING, MISSING VALUE, SECURITY_CLASS or VALID_IF", encountered \"%s\" */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KW_QUERY_NAME:
|
|
|
|
LEX_token();
|
2003-10-18 01:47:04 +02:00
|
|
|
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();
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_IS);
|
2001-05-23 15:26:42 +02:00
|
|
|
stack = NULL;
|
|
|
|
for (;;) {
|
2003-10-03 04:00:40 +02:00
|
|
|
LLS_PUSH((DUDLEY_NOD) PARSE_symbol(tok_quoted), &stack);
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_SLASH))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
field->fld_query_header = PARSE_make_list(stack);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KW_COMPUTED:
|
|
|
|
LEX_token();
|
2003-10-18 01:47:04 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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();
|
2003-10-18 01:47:04 +02:00
|
|
|
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();
|
2003-10-18 01:47:04 +02:00
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
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();
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_IS);
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_segment_length = n = PARSE_number();
|
|
|
|
if (n <= 0)
|
|
|
|
PARSE_error(197, 0, 0); /* msg 197: segment length must be positive */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KW_SUB_TYPE:
|
|
|
|
LEX_token();
|
|
|
|
parse_field_subtype(field);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KW_DEFAULT:
|
|
|
|
LEX_token();
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int n;
|
|
|
|
|
|
|
|
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;
|
2003-11-11 13:19:20 +01:00
|
|
|
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;
|
2003-11-11 13:19:20 +01:00
|
|
|
field->fld_length = sizeof(ISC_QUAD);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case KW_BLOB:
|
|
|
|
field->fld_dtype = blr_blob;
|
2003-11-11 13:19:20 +01:00
|
|
|
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) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_L_BRCKET) && !PARSE_match(KW_LT))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(200, DDL_token.tok_string, 0); /* msg 200: expected \"[\", encountered \"%s\" */
|
|
|
|
field->fld_length = n = PARSE_number();
|
|
|
|
if (n <= 0)
|
|
|
|
PARSE_error(201, 0, 0); /* msg 201: character field length must be positive */
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_R_BRCKET) && !PARSE_match(KW_GT))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(202, DDL_token.tok_string, 0); /* msg 202: expected \"]\", encountered \"%s\" */
|
|
|
|
|
2003-10-18 01:47:04 +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))
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_SCALE))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_scale = PARSE_number();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01: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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_BLR))
|
2001-05-23 15:26:42 +02:00
|
|
|
field->fld_sub_type = 2;
|
2003-10-18 01:47:04 +02:00
|
|
|
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 (DDL_token.tok_type != tok_number)
|
|
|
|
PARSE_error(198, DDL_token.tok_string, 0); /* msg 198: expected field sub_type, encountered \"%s\" */
|
|
|
|
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;
|
2002-11-30 18:45:02 +01:00
|
|
|
DUDLEY_FLD field;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
func_arg = (FUNCARG) DDL_alloc(sizeof(funcarg));
|
|
|
|
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)++;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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)
|
|
|
|
PARSE_error(203, 0, 0); /* msg 203: argument mode by value not allowed for this data type */
|
|
|
|
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 */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_COMMA || 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], **s, **end, **s1, strings[256], *p, *q;
|
|
|
|
SCE element;
|
|
|
|
|
|
|
|
p = strings;
|
|
|
|
for (s = idents, end = s + 10; s < end; s++)
|
|
|
|
*s = NULL;
|
|
|
|
|
|
|
|
/* Get explicit identifiers, if any */
|
|
|
|
|
|
|
|
switch (DDL_token.tok_keyword) {
|
|
|
|
case (KW_VIEW):
|
|
|
|
LEX_token();
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(117, DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
|
|
|
|
idents[id_view] = p;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
LEX_token();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (KW_USER):
|
|
|
|
LEX_token();
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(117, DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
|
|
|
|
idents[id_user] = p;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
LEX_token();
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_GROUP)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(117, DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
|
|
|
|
idents[id_group] = p;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
LEX_token();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (KW_GROUP):
|
|
|
|
LEX_token();
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(117, DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
|
|
|
|
idents[id_group] = p;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
LEX_token();
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_USER)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(117, DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
|
|
|
|
idents[id_user] = p;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
LEX_token();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (KW_L_BRCKET):
|
|
|
|
case (KW_LT):
|
|
|
|
LEX_token();
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_ASTERISK)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (DDL_token.tok_type != tok_number)
|
|
|
|
PARSE_error(206, DDL_token.tok_string, 0); /* msg 206: expected number, encountered \"%s\" */
|
|
|
|
idents[id_group] = p;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
LEX_token();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(207, DDL_token.tok_string, 0); /* msg 207: expected comma between group and user ids, encountered \"%s\" */
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_ASTERISK)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (DDL_token.tok_type != tok_number)
|
|
|
|
PARSE_error(206, DDL_token.tok_string, 0); /* msg 206: expected number, encountered \"%s\" */
|
|
|
|
idents[id_user] = p;
|
|
|
|
q = DDL_token.tok_string;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
LEX_token();
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!(PARSE_match(KW_R_BRCKET) || PARSE_match(KW_GT)))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(208, DDL_token.tok_string, 0); /* msg 208: expected trailing bracket, encountered \"%s\" */
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Build access control element */
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
element = (SCE) DDL_alloc(sizeof(sce) + (p - strings));
|
2001-05-23 15:26:42 +02:00
|
|
|
p = (TEXT *) element->sce_strings;
|
|
|
|
|
|
|
|
for (s = idents, end = s + 10, s1 = (TEXT **) element->sce_idents;
|
|
|
|
s < end; s++, s1++)
|
|
|
|
if (q = *s) {
|
|
|
|
*s1 = p;
|
|
|
|
while (*p++ = *q++);
|
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_DATABASE))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_database;
|
|
|
|
else if (!database || !database->dbb_handle)
|
|
|
|
PARSE_error(209, 0, 0); /* msg 209: no database declared */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_RELATION))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_relation;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_FIELD))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_field;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_INDEX))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_index;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_VIEW))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_view;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_SECURITY_CLASS))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_security_class;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_TRIGGER))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_trigger;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_FILE))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_file;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_FUNCTION))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_function;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_TYPES))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_type;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_FILTER))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_filter;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_SHADOW))
|
2001-05-23 15:26:42 +02:00
|
|
|
return obj_shadow;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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
|
|
|
|
*
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
int n1, n2;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
PARSE_match(KW_EQUALS);
|
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
|
|
|
|
PARSE_error(210, (TEXT *) n1, (TEXT *) MAX_PAGE_LEN);
|
|
|
|
/* msg 210: PAGE_SIZE specified (%d) longer than limit of %d bytes */
|
|
|
|
if (n1 != n2)
|
|
|
|
DDL_msg_put(211, (TEXT *) n1, (TEXT *) n2, NULL, NULL, NULL);
|
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TEXT *p, c;
|
|
|
|
SLONG privileges;
|
|
|
|
|
|
|
|
privileges = 0;
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_MINUS)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(117, DDL_token.tok_string, 0); /* msg 117: expected identifier, encountered \"%s\" */
|
|
|
|
p = DDL_token.tok_string;
|
|
|
|
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:
|
2003-08-19 10:59:45 +02:00
|
|
|
PARSE_error(212, (TEXT *)(SLONG) 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
UPFE upf;
|
|
|
|
USERPRIV upriv;
|
|
|
|
USRE usr;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
upriv = (USERPRIV) DDL_alloc(sizeof(userpriv));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_ALL)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
/* optional keyword following ALL */
|
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_SELECT))
|
2001-05-23 15:26:42 +02:00
|
|
|
upriv->userpriv_flags |= USERPRIV_select;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_DELETE))
|
2001-05-23 15:26:42 +02:00
|
|
|
upriv->userpriv_flags |= USERPRIV_delete;
|
2003-10-18 01:47:04 +02:00
|
|
|
else if (PARSE_match(KW_INSERT))
|
2001-05-23 15:26:42 +02:00
|
|
|
upriv->userpriv_flags |= USERPRIV_insert;
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_ON))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (PARSE_match(KW_COMMA))
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_LEFT_PAREN))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(315, DDL_token.tok_string, 0); /* msg 315: expected ON or '(', encountered "%s" */
|
|
|
|
|
|
|
|
do {
|
2003-10-18 01:47:04 +02:00
|
|
|
if (DDL_token.tok_keyword == KW_SELECT
|
|
|
|
|| DDL_token.tok_keyword == KW_INSERT
|
|
|
|
|| DDL_token.tok_keyword == KW_DELETE
|
|
|
|
|| DDL_token.tok_keyword == KW_UPDATE)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2003-10-18 01:47:04 +02:00
|
|
|
}
|
2003-09-30 12:39:11 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
} while (PARSE_match(KW_COMMA));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_RIGHT_PAREN))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(316, DDL_token.tok_string, 0); /* msg 316: expected ')', encountered "%s" */
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_COMMA)) {
|
|
|
|
if (!PARSE_match(KW_ON))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(214, DDL_token.tok_string, 0); /* msg 214: expected ON, encountered \"%s\" */
|
|
|
|
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);
|
2003-10-18 01:47:04 +02:00
|
|
|
if (!PARSE_match(KW_FROM))
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_error(216, DDL_token.tok_string, 0); /* msg 216: expected FROM, encountered \"%s\" */
|
|
|
|
|
|
|
|
/* get the userlist */
|
2003-09-10 19:52:12 +02:00
|
|
|
while (true) {
|
2003-09-30 12:39:11 +02:00
|
|
|
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;
|
2003-10-18 01:47:04 +02:00
|
|
|
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;
|
|
|
|
TEXT **ptr, **end;
|
|
|
|
|
|
|
|
score = 0;
|
|
|
|
if (element->sce_idents[id_view])
|
|
|
|
score++;
|
|
|
|
|
|
|
|
for (ptr = (TEXT **) element->sce_idents, end = ptr + id_max; ptr < end;
|
|
|
|
ptr++) {
|
|
|
|
score <<= 1;
|
|
|
|
if (*ptr)
|
|
|
|
score |= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return score;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-11 20:11:52 +01:00
|
|
|
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
|
|
|
|
**************************************/
|
2002-11-11 20:11:52 +01:00
|
|
|
DUDLEY_NOD node;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (DDL_token.tok_type != tok_ident)
|
|
|
|
PARSE_error(274, DDL_token.tok_string, 0); /* msg 274: expected generator name, encountered \"%s\" */
|
|
|
|
|
|
|
|
node = PARSE_make_node(nod_set_generator, 2);
|
|
|
|
node->nod_count = 1;
|
2002-11-11 20:11:52 +01:00
|
|
|
node->nod_arg[1] = (DUDLEY_NOD) PARSE_symbol(tok_ident);
|
2003-10-18 01:47:04 +02:00
|
|
|
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(
|
2002-11-17 01:04:19 +01:00
|
|
|
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;
|
|
|
|
|
2003-09-30 12:39:11 +02:00
|
|
|
text = (TXT) DDL_alloc(sizeof(txt));
|
2001-05-23 15:26:42 +02:00
|
|
|
text->txt_position = DDL_token.tok_position - DDL_token.tok_length;
|
|
|
|
text->txt_start_line = DDL_line;
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-30 18:45:02 +01:00
|
|
|
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;
|
|
|
|
}
|