8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 14:43:04 +01:00
firebird-mirror/src/dudley/exe.epp

4186 lines
103 KiB
Plaintext
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Data Definition Utility
2003-10-05 08:42:03 +02:00
* MODULE: exe.epp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Meta-data update execution module.
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include <string.h>
#include "../dudley/ddl.h"
#include "../jrd/license.h"
2003-11-08 00:27:24 +01:00
#include "../jrd/ibase.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/flags.h"
#include "../jrd/acl.h"
#include "../jrd/intl.h"
#include "../jrd/obj.h"
#include "../dudley/ddl_proto.h"
#include "../dudley/exe_proto.h"
#include "../dudley/gener_proto.h"
#include "../dudley/hsh_proto.h"
#include "../dudley/lex_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/isc_f_proto.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
2001-05-23 15:26:42 +02:00
#ifdef WIN_NT
#include <io.h> // unlink
2001-05-23 15:26:42 +02:00
#endif
#define C_NUMERIC_SCALE(desc) ((DTYPE_IS_TEXT(make_dtype((desc).dsc_dtype))) ? 0 : (desc).dsc_scale)
2001-05-23 15:26:42 +02:00
2002-12-16 17:25:09 +01:00
DATABASE DB = FILENAME "yachts.lnk";
2001-05-23 15:26:42 +02:00
//static void add_cache(DBB);
static void add_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static void add_files(DBB, FIL);
static void add_filter(FILTER);
static void add_function(FUNC);
static void add_function_arg(FUNCARG);
static void add_generator(SYM);
static void add_global_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static void add_index(DUDLEY_IDX);
//static void add_log_files(DBB);
static void add_relation(DUDLEY_REL);
2001-05-23 15:26:42 +02:00
static void add_security_class(SCL);
static void add_trigger(DUDLEY_TRG);
2001-05-23 15:26:42 +02:00
static void add_trigger_msg(TRGMSG);
static void add_type(TYP);
static void add_user_privilege(USERPRIV);
static void add_view(DUDLEY_REL);
2001-05-23 15:26:42 +02:00
static void alloc_file_name(FIL *, UCHAR *);
static DUDLEY_FLD check_field(SYM, SYM);
2003-09-04 15:45:44 +02:00
static bool check_function(SYM);
static bool check_range(DUDLEY_FLD);
static bool check_relation(SYM);
2004-05-03 01:06:37 +02:00
static void close_blob(FB_API_HANDLE);
static FB_API_HANDLE create_blob(ISC_QUAD*, USHORT, const UCHAR*);
//static void drop_cache(DBB);
static void drop_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static void drop_filter(FILTER);
static void drop_function(FUNC);
static void drop_global_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static void drop_index(DUDLEY_IDX);
static void drop_relation(DUDLEY_REL);
2001-05-23 15:26:42 +02:00
static void drop_security_class(SCL);
static void drop_shadow(SLONG);
static void drop_trigger(DUDLEY_TRG);
2001-05-23 15:26:42 +02:00
static void drop_trigger_msg(TRGMSG);
static void drop_type(TYP);
static void drop_user_privilege(USERPRIV);
static void erase_userpriv(USERPRIV, TEXT *, USRE, UPFE);
static void get_field_desc(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static void get_global_fields(void);
static void get_relations(DBB);
static USHORT get_prot_mask(TEXT *, TEXT *);
static SYM get_symbol(enum sym_t, TEXT *, DUDLEY_CTX);
2001-05-23 15:26:42 +02:00
static void get_triggers(DBB);
static void get_udfs(DBB);
static void make_desc(DUDLEY_NOD, DSC *);
2001-05-23 15:26:42 +02:00
static int make_dtype(USHORT);
static void modify_field(DUDLEY_FLD);
static void modify_global_field(DUDLEY_FLD);
2001-05-23 15:26:42 +02:00
static void modify_index(DUDLEY_IDX);
static void modify_relation(DUDLEY_REL);
static void modify_trigger(DUDLEY_TRG);
2001-05-23 15:26:42 +02:00
static void modify_trigger_msg(TRGMSG);
static void modify_type(TYP);
static void move_symbol(SYM, SCHAR *, SSHORT);
static void set_generator(DUDLEY_NOD);
static void store_acl(SCL, ISC_QUAD*);
static void store_blr(DUDLEY_NOD, ISC_QUAD*, DUDLEY_REL);
static void store_query_header(DUDLEY_NOD, ISC_QUAD*);
static void store_range(DUDLEY_FLD);
static void store_text(TXT, ISC_QUAD*);
2001-05-23 15:26:42 +02:00
static void store_userpriv(USERPRIV, TEXT *, TEXT *, USRE, UPFE);
static int string_length(SCHAR);
static void wal_info(const UCHAR*, SLONG*, SCHAR*, SLONG*);
2001-05-23 15:26:42 +02:00
2004-02-02 12:02:12 +01:00
static dudley_lls* files_to_delete = NULL;
2003-11-08 00:27:24 +01:00
static const TEXT alloc_info[] = { isc_info_allocation, isc_info_end };
2001-05-23 15:26:42 +02:00
#define MOVE_SYMBOL(symbol, field) move_symbol (symbol, field, sizeof (field) - 1)
/*
static const SCHAR db_info[] =
2001-05-23 15:26:42 +02:00
{
2003-11-08 00:27:24 +01:00
isc_info_logfile,
isc_info_cur_logfile_name,
isc_info_cur_log_part_offset
2001-05-23 15:26:42 +02:00
};
*/
2001-05-23 15:26:42 +02:00
SLONG EXE_check_db_version( DBB dbb)
{
/**************************************
*
* E X E _ c h e c k _ d b _ v e r s i o n
*
**************************************
*
* Functional description
* Find the version number of the database.
*
**************************************/
SLONG db_version = DB_VERSION_DDL4;
FOR X IN RDB$RELATIONS
WITH X.RDB$RELATION_NAME = "RDB$TRIGGERS"
db_version = DB_VERSION_DDL6;
END_FOR;
FOR X IN RDB$RELATIONS
WITH X.RDB$RELATION_NAME = "RDB$LOG_FILES"
db_version = DB_VERSION_DDL8;
END_FOR;
return db_version;
}
void EXE_create_database( DBB dbb)
{
/**************************************
*
* E X E _ c r e a t e _ d a t a b a s e
*
**************************************
*
* Functional description
* Create a new database.
*
**************************************/
/* Generate a dpb for attempting to attach to, and
later to create, the specified database. */
2004-03-07 08:58:55 +01:00
USHORT dpb_length = 0;
TEXT dpb[128];
TEXT* d = dpb;
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_version1;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
TEXT* p;
if (p = dudleyGlob.DDL_default_user) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_user_name;
2001-05-23 15:26:42 +02:00
*d++ = strlen(p);
while (*p)
*d++ = *p++;
}
if (p = dudleyGlob.DDL_default_password) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_password;
2001-05-23 15:26:42 +02:00
*d++ = strlen(p);
while (*p)
*d++ = *p++;
}
dpb_length = d - dpb;
if (dpb_length == 1)
dpb_length = 0;
const TEXT* file_name = dbb->dbb_name->sym_string;
2001-05-23 15:26:42 +02:00
2003-11-08 00:27:24 +01:00
const SLONG result = isc_attach_database(gds_status, 0, file_name, &DB, dpb_length, dpb);
if (!dudleyGlob.DDL_replace) {
2001-05-23 15:26:42 +02:00
if (!result) {
2003-11-08 00:27:24 +01:00
isc_detach_database(gds_status, &DB);
2003-08-30 04:02:36 +02:00
DDL_msg_put(18, file_name, NULL, NULL, NULL, NULL);
/* msg 18: Database \"%s\" already exists */
if (dudleyGlob.DDL_interactive) {
2003-08-30 04:02:36 +02:00
DDL_msg_partial(19, NULL, NULL, NULL, NULL, NULL);
/* msg 19: Do you want to replace it? */
2001-05-23 15:26:42 +02:00
if (!DDL_yes_no(286))
DDL_exit(FINI_ERROR);
}
else
DDL_exit(FINI_ERROR);
}
2003-11-08 00:27:24 +01:00
else if (gds_status[1] != isc_io_error)
2003-08-30 04:02:36 +02:00
DDL_error_abort(gds_status, 20, file_name, NULL, NULL, NULL, NULL);
/* msg 20: Database \"%s\" exists but can't be opened */
2001-05-23 15:26:42 +02:00
}
else {
/* replacing the database so try to drop it first. */
if (!result) {
isc_drop_database(gds_status, &DB);
2001-05-23 15:26:42 +02:00
if (DB)
isc_detach_database(gds_status, &DB);
2001-05-23 15:26:42 +02:00
}
}
/* add the specified page size to the already defined dpb */
if (dbb->dbb_page_size) {
2004-03-07 08:58:55 +01:00
const USHORT page_size = MAX(dbb->dbb_page_size, 1024);
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_page_size;
2001-05-23 15:26:42 +02:00
*d++ = 2;
*d++ = page_size;
*d++ = page_size >> 8;
dpb_length = d - dpb;
}
2004-03-07 08:58:55 +01:00
USHORT len;
ULONG llen;
2001-05-23 15:26:42 +02:00
if (llen = dbb->dbb_chkptlen) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_chkptlen;
2001-05-23 15:26:42 +02:00
*d++ = 4;
for (len = 0; len < 4; len++, llen = llen >> 8)
*d++ = llen;
}
if (len = dbb->dbb_numbufs) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_numbufs;
2001-05-23 15:26:42 +02:00
*d++ = 2;
*d++ = len;
*d++ = len >> 8;
}
if (len = dbb->dbb_bufsize) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_bufsize;
2001-05-23 15:26:42 +02:00
*d++ = 2;
*d++ = len;
*d++ = len >> 8;
}
if ((llen = dbb->dbb_grp_cmt_wait) >= 0) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_grp_cmt_wait;
2001-05-23 15:26:42 +02:00
*d++ = 4;
for (len = 0; len < 4; len++, llen = llen >> 8)
*d++ = llen;
}
dpb_length = d - dpb;
if (dpb_length == 1)
dpb_length = 0;
2003-11-08 00:27:24 +01:00
if (isc_create_database(gds_status, 0, file_name, &DB, dpb_length, dpb, 0))
2003-08-30 04:02:36 +02:00
DDL_error_abort(gds_status, 21, file_name, NULL, NULL, NULL, NULL);
/* msg 21: Couldn't create database \"%s\" */
2001-05-23 15:26:42 +02:00
if (dudleyGlob.DDL_version) {
2003-08-30 04:02:36 +02:00
DDL_msg_put(23, file_name, NULL, NULL, NULL, NULL);
/* msg 23: Version(s) for database \"%s\" */
2003-11-08 00:27:24 +01:00
isc_version(&DB, NULL, NULL);
2001-05-23 15:26:42 +02:00
}
START_TRANSACTION;
2004-03-07 08:58:55 +01:00
const SLONG ods_version = EXE_check_db_version(dbb);
2001-05-23 15:26:42 +02:00
if (ods_version < DB_VERSION_DDL6)
DDL_error_abort(NULL, 32, NULL, NULL, NULL, NULL, NULL);
// msg 32: database version is too old to modify: use GBAK first */
2001-05-23 15:26:42 +02:00
2004-05-03 01:06:37 +02:00
dbb->dbb_handle = DB;
dbb->dbb_transaction = gds_trans;
2001-05-23 15:26:42 +02:00
/* Don't allow cache and WAL configurations for pre-ODS8 databases */
/*
2001-05-23 15:26:42 +02:00
if (ods_version < DB_VERSION_DDL8) {
if ((dbb->dbb_flags & DBB_log_default) ||
(dbb->dbb_logfiles) ||
(dbb->dbb_cache_file))
2004-03-07 08:58:55 +01:00
{
DDL_error_abort(NULL, 32, NULL, NULL, NULL, NULL, NULL);
// msg 32: database version is too old to modify: use GBAK first
2004-03-07 08:58:55 +01:00
}
2001-05-23 15:26:42 +02:00
}
*/
2001-05-23 15:26:42 +02:00
if (dbb->dbb_files)
add_files(dbb, dbb->dbb_files);
/*
2001-05-23 15:26:42 +02:00
if (dbb->dbb_cache_file)
add_cache(dbb);
if ((dbb->dbb_flags & DBB_log_default) || (dbb->dbb_logfiles))
add_log_files(dbb);
*/
2001-05-23 15:26:42 +02:00
/* If there is a description of the database, store it now */
FOR D IN RDB$DATABASE
2003-09-10 19:52:12 +02:00
MODIFY D USING
if (dbb->dbb_description) {
store_text(dbb->dbb_description, &D.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
D.RDB$DESCRIPTION.NULL = FALSE;
}
if (dbb->dbb_security_class) {
MOVE_SYMBOL(dbb->dbb_security_class, D.RDB$SECURITY_CLASS);
D.RDB$SECURITY_CLASS.NULL = FALSE;
}
END_MODIFY;
2001-05-23 15:26:42 +02:00
END_FOR;
get_global_fields();
get_relations(dbb);
get_udfs(dbb);
get_triggers(dbb);
/*
2001-05-23 15:26:42 +02:00
if ((dbb->dbb_flags & DBB_log_default) || (dbb->dbb_logfiles)) {
// setup enough information to drop log files created
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
SCHAR db_info_buffer[512];
2003-11-08 00:27:24 +01:00
if (isc_database_info(gds_status, &DB, sizeof(db_info), db_info,
2003-08-30 04:02:36 +02:00
sizeof(db_info_buffer), db_info_buffer))
DDL_error_abort(gds_status, 327, NULL, NULL, NULL, NULL, NULL);
// msg 327: error in getting write ahead log information
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
SLONG log = 0, part_offset;
SCHAR cur_log[512];
wal_info((const UCHAR*) db_info_buffer, &log, cur_log, &part_offset);
2001-05-23 15:26:42 +02:00
}
*/
2001-05-23 15:26:42 +02:00
}
void EXE_drop_database( DBB dbb)
{
/**************************************
*
* E X E _ d r o p _ d a t a b a s e
*
**************************************
*
* Functional description
* Drop an existing database, and all
* its files.
*
**************************************/
2004-03-07 08:58:55 +01:00
USHORT dpb_length = 0;
TEXT dpb[128];
TEXT* d = dpb;
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_version1;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
TEXT* p;
if (p = dudleyGlob.DDL_default_user) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_user_name;
2001-05-23 15:26:42 +02:00
*d++ = strlen(p);
while (*p)
*d++ = *p++;
}
if (p = dudleyGlob.DDL_default_password) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_password;
2001-05-23 15:26:42 +02:00
*d++ = strlen(p);
while (*p)
*d++ = *p++;
}
dpb_length = d - dpb;
if (dpb_length == 1)
dpb_length = 0;
2003-11-08 00:27:24 +01:00
if (isc_attach_database(gds_status, 0, dbb->dbb_name->sym_string, &DB,
2003-08-30 04:02:36 +02:00
dpb_length, dpb))
DDL_error_abort(gds_status, 25, NULL, NULL, NULL, NULL, NULL);
/* msg 25: Couldn't locate database */
2001-05-23 15:26:42 +02:00
START_TRANSACTION;
FOR F IN RDB$FILES SORTED BY F.RDB$FILE_START
alloc_file_name(&dbb->dbb_files, (UCHAR*) F.RDB$FILE_NAME);
2001-05-23 15:26:42 +02:00
END_FOR;
2003-08-30 04:02:36 +02:00
COMMIT ON_ERROR DDL_db_error(gds_status, 26, NULL, NULL, NULL, NULL, NULL);
/* msg 26: error commiting metadata changes */
2001-05-23 15:26:42 +02:00
ROLLBACK;
END_ERROR;
/*
2004-03-07 08:58:55 +01:00
SCHAR db_info_buffer[512];
2003-11-08 00:27:24 +01:00
if (isc_database_info(gds_status, &DB, sizeof(db_info), db_info,
2003-08-30 04:02:36 +02:00
sizeof(db_info_buffer), db_info_buffer))
DDL_error_abort(gds_status, 327, NULL, NULL, NULL, NULL, NULL);
// msg 327: error in getting write ahead log information
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
SLONG log, part_offset;
SCHAR cur_log[512];
wal_info((const UCHAR*) db_info_buffer, &log, cur_log, &part_offset);
2001-05-23 15:26:42 +02:00
2003-11-08 00:27:24 +01:00
if (isc_detach_database(gds_status, &DB))
2003-08-30 04:02:36 +02:00
DDL_error_abort(gds_status, 27, NULL, NULL, NULL, NULL, NULL);
// msg 27: Couldn't release database
*/
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
for (FIL file = dbb->dbb_files; file; file = file->fil_next)
{
if (unlink(file->fil_name->sym_name)) {
DDL_error_abort(NULL, 28, file->fil_name->sym_name, NULL,
NULL, NULL, NULL);
// msg 28: Could not delete file %s
2004-03-07 08:58:55 +01:00
}
}
2001-05-23 15:26:42 +02:00
if (unlink(dbb->dbb_name->sym_string))
DDL_error_abort(NULL, 28, dbb->dbb_name->sym_string, NULL, NULL,
NULL, NULL);
// msg 28: Could not delete file %s
2001-05-23 15:26:42 +02:00
}
void EXE_execute(void)
{
/**************************************
*
* E X E _ e x e c u t e
*
**************************************
*
* Functional description
* Execute the output of the parser.
* By this time we should have openned
* a database - by creating it or by
* preparing to modify it. If not,
* give up quietly.
*
**************************************/
if (!dudleyGlob.DDL_actions)
2001-05-23 15:26:42 +02:00
return;
if (!DB)
DDL_error_abort(NULL, 33, NULL, NULL, NULL, NULL, NULL);
// msg 33: no database specified
2001-05-23 15:26:42 +02:00
for (ACT action = dudleyGlob.DDL_actions; action; action = action->act_next)
2001-05-23 15:26:42 +02:00
if (!(action->act_flags & ACT_ignore)) {
dudleyGlob.DDL_line = action->act_line;
2001-05-23 15:26:42 +02:00
switch (action->act_type) {
case act_c_database:
case act_m_database:
break;
case act_a_field:
add_field((DUDLEY_FLD) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_m_field:
modify_field((DUDLEY_FLD) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_field:
drop_field((DUDLEY_FLD) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_filter:
add_filter((FILTER) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_filter:
drop_filter((FILTER) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_function:
add_function((FUNC) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_function_arg:
add_function_arg((FUNCARG) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_function:
drop_function((FUNC) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_gfield:
add_global_field((DUDLEY_FLD) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_m_gfield:
modify_global_field((DUDLEY_FLD) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_gfield:
drop_global_field((DUDLEY_FLD) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_index:
add_index((DUDLEY_IDX) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_m_index:
modify_index((DUDLEY_IDX) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_index:
drop_index((DUDLEY_IDX) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_relation:
add_relation((DUDLEY_REL) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_m_relation:
modify_relation((DUDLEY_REL) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_relation:
drop_relation((DUDLEY_REL) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_security:
add_security_class((SCL) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_security:
drop_security_class((SCL) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_trigger:
add_trigger((DUDLEY_TRG) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_m_trigger:
modify_trigger((DUDLEY_TRG) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_trigger:
drop_trigger((DUDLEY_TRG) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_trigger_msg:
add_trigger_msg((TRGMSG) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_m_trigger_msg:
modify_trigger_msg((TRGMSG) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_trigger_msg:
drop_trigger_msg((TRGMSG) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_type:
add_type((TYP) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_m_type:
modify_type((TYP) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_type:
drop_type((TYP) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_grant:
add_user_privilege((USERPRIV) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_revoke:
drop_user_privilege((USERPRIV) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_shadow:
add_files(NULL, (FIL) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_d_shadow:
2004-03-14 06:51:54 +01:00
drop_shadow((IPTR) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_a_generator:
add_generator((SYM) action->act_object);
2001-05-23 15:26:42 +02:00
break;
case act_s_generator:
set_generator((DUDLEY_NOD) action->act_object);
2001-05-23 15:26:42 +02:00
break;
default:
2003-08-30 04:02:36 +02:00
DDL_err(34, NULL, NULL, NULL, NULL, NULL);
/* msg 34: action not implemented yet */
2001-05-23 15:26:42 +02:00
}
}
}
void EXE_fini( DBB dbb)
{
/**************************************
*
* E X E _ f i n i
*
**************************************
*
* Functional description
* Sign off database -- commit or rollback depending on whether or
* not errors have occurred.
*
**************************************/
if (DB) {
if (dudleyGlob.DDL_errors) {
2001-05-23 15:26:42 +02:00
if (dbb && (dbb->dbb_flags & DBB_create_database)) {
FOR F IN RDB$FILES WITH F.RDB$SHADOW_NUMBER NE 0
alloc_file_name(&dbb->dbb_files, (UCHAR*)F.RDB$FILE_NAME);
2001-05-23 15:26:42 +02:00
END_FOR;
}
ROLLBACK
2003-08-30 04:02:36 +02:00
ON_ERROR DDL_db_error(gds_status, 35, NULL, NULL, NULL, NULL, NULL);
/* msg 35: error rolling back metadata changes */
2001-05-23 15:26:42 +02:00
END_ERROR}
else {
COMMIT
2003-08-30 04:02:36 +02:00
ON_ERROR DDL_db_error(gds_status, 36, NULL, NULL, NULL, NULL, NULL);
/* msg 36: error commiting metadata changes */
2001-05-23 15:26:42 +02:00
ROLLBACK;
END_ERROR}
FINISH;
}
/* We have previously committed the deletion of some files.
Do the actual deletion here. */
while (files_to_delete) {
2004-03-07 08:58:55 +01:00
SYM string = (SYM) DDL_pop(&files_to_delete);
2001-05-23 15:26:42 +02:00
unlink(string->sym_name);
gds__free(string);
}
}
void EXE_modify_database( DBB dbb)
{
/**************************************
*
* E X E _ m o d i f y _ d a t a b a s e
*
**************************************
*
* Functional description
* Modify an existing database.
*
**************************************/
2004-03-07 08:58:55 +01:00
USHORT dpb_length = 0;
TEXT dpb[128];
TEXT* d = dpb;
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_version1;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
TEXT* p;
if (p = dudleyGlob.DDL_default_user) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_user_name;
2001-05-23 15:26:42 +02:00
*d++ = strlen(p);
while (*p)
*d++ = *p++;
}
if (p = dudleyGlob.DDL_default_password) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_password;
2001-05-23 15:26:42 +02:00
*d++ = strlen(p);
while (*p)
*d++ = *p++;
}
/*
2001-05-23 15:26:42 +02:00
if (dbb->dbb_flags & DBB_drop_log) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_drop_walfile;
2001-05-23 15:26:42 +02:00
*d++ = 1;
*d++ = 1;
}
2004-03-07 08:58:55 +01:00
USHORT len;
ULONG llen;
2001-05-23 15:26:42 +02:00
if (llen = dbb->dbb_chkptlen) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_chkptlen;
2001-05-23 15:26:42 +02:00
*d++ = 4;
for (len = 0; len < 4; len++, llen = llen >> 8)
*d++ = llen;
}
if (len = dbb->dbb_numbufs) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_numbufs;
2001-05-23 15:26:42 +02:00
*d++ = 2;
*d++ = len;
*d++ = len >> 8;
}
if (len = dbb->dbb_bufsize) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_bufsize;
2001-05-23 15:26:42 +02:00
*d++ = 2;
*d++ = len;
*d++ = len >> 8;
}
if ((llen = dbb->dbb_grp_cmt_wait) >= 0) {
2003-11-08 00:27:24 +01:00
*d++ = isc_dpb_wal_grp_cmt_wait;
2001-05-23 15:26:42 +02:00
*d++ = 4;
for (len = 0; len < 4; len++, llen = llen >> 8)
*d++ = llen;
}
*/
2001-05-23 15:26:42 +02:00
dpb_length = d - dpb;
if (dpb_length == 1)
dpb_length = 0;
2003-11-08 00:27:24 +01:00
if (isc_attach_database(gds_status, 0, dbb->dbb_name->sym_string, &DB,
2003-08-30 04:02:36 +02:00
dpb_length, dpb))
DDL_error_abort(gds_status, 29, dbb->dbb_name->sym_string, NULL,
2001-05-23 15:26:42 +02:00
NULL, NULL, NULL); /* msg 29: Couldn't attach database */
if (dudleyGlob.DDL_version) {
2003-08-30 04:02:36 +02:00
DDL_msg_put(30, dbb->dbb_name->sym_string, NULL, NULL, NULL, NULL);
2003-09-10 19:52:12 +02:00
/* msg 30: Version(s) for database \"%s\" */
2003-11-08 00:27:24 +01:00
isc_version(&DB, NULL, NULL);
2001-05-23 15:26:42 +02:00
}
START_TRANSACTION;
2004-03-07 08:58:55 +01:00
const SLONG ods_version = EXE_check_db_version(dbb);
2001-05-23 15:26:42 +02:00
if (ods_version < DB_VERSION_DDL6)
DDL_error_abort(NULL, 32, NULL, NULL, NULL, NULL, NULL);
// msg 32: database version is too old to modify: use GBAK first */
2001-05-23 15:26:42 +02:00
/* Don't allow cache and WAL configurations for pre-ODS8 databases */
/*
2001-05-23 15:26:42 +02:00
if (ods_version < DB_VERSION_DDL8) {
if ((dbb->dbb_flags & DBB_log_default) ||
(dbb->dbb_logfiles) ||
(dbb->dbb_flags && DBB_drop_log) ||
(dbb->dbb_cache_file) || (dbb->dbb_flags & DBB_drop_cache))
2004-03-07 08:58:55 +01:00
{
DDL_error_abort(NULL, 32, NULL, NULL, NULL, NULL, NULL);
// msg 32: database version is too old to modify: use GBAK first
2004-03-07 08:58:55 +01:00
}
2001-05-23 15:26:42 +02:00
}
*/
2001-05-23 15:26:42 +02:00
2004-05-03 01:06:37 +02:00
dbb->dbb_handle = DB;
dbb->dbb_transaction = gds_trans;
2001-05-23 15:26:42 +02:00
/* erase log files and commit transaction */
/*
2001-05-23 15:26:42 +02:00
if (dbb->dbb_flags & DBB_drop_log) {
2004-03-07 08:58:55 +01:00
SCHAR db_info_buffer[512];
2003-11-08 00:27:24 +01:00
if (isc_database_info(gds_status, &DB, sizeof(db_info), db_info,
2003-08-30 04:02:36 +02:00
sizeof(db_info_buffer), db_info_buffer))
DDL_error_abort(gds_status, 327, NULL, NULL, NULL, NULL, NULL);
// msg 327: error in getting write ahead log information
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
FIL log_files = NULL;
SLONG log = 0, part_offset;
SCHAR cur_log[512];
wal_info((const UCHAR*) db_info_buffer, &log, cur_log, &part_offset);
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
// There seems to be missing code here to chain files in "log_files"
// before they are deleted from the system table. Otherwise, the loop
// below doesn't make sense because "log_files" is always NULL.
2001-05-23 15:26:42 +02:00
FOR X IN RDB$LOG_FILES ERASE X;
END_FOR;
2003-08-30 04:02:36 +02:00
COMMIT ON_ERROR DDL_db_error(gds_status, 321, NULL, NULL, NULL, NULL, NULL);
// msg 321: error commiting new write ahead log declarations
2001-05-23 15:26:42 +02:00
ROLLBACK;
END_ERROR;
START_TRANSACTION;
2004-03-07 08:58:55 +01:00
for (FIL file = log_files; file; file = file->fil_next)
2001-05-23 15:26:42 +02:00
if (unlink(file->fil_name->sym_name))
DDL_error_abort(NULL, 28, file->fil_name->sym_name, NULL,
NULL, NULL, NULL);
// msg 28: Could not delete file %s
2001-05-23 15:26:42 +02:00
}
if (dbb->dbb_flags & DBB_drop_cache)
drop_cache(dbb);
*/
2001-05-23 15:26:42 +02:00
/* adding new files */
if (dbb->dbb_files)
add_files(dbb, dbb->dbb_files);
/*
2001-05-23 15:26:42 +02:00
if (dbb->dbb_cache_file)
add_cache(dbb);
if ((dbb->dbb_flags & DBB_log_default) || (dbb->dbb_logfiles)) {
// check if log files exist
2001-05-23 15:26:42 +02:00
FOR X IN RDB$LOG_FILES
DDL_error_abort(NULL, 333, NULL, NULL, NULL, NULL, NULL);
// msg 333: Cannot modify log file specification. Drop and redefine log files
2001-05-23 15:26:42 +02:00
END_FOR;
// add the new log files.
2001-05-23 15:26:42 +02:00
add_log_files(dbb);
// commit log file changes
2001-05-23 15:26:42 +02:00
2003-08-30 04:02:36 +02:00
COMMIT ON_ERROR DDL_db_error(gds_status, 321, NULL, NULL, NULL, NULL, NULL);
// msg 321: error commiting new write ahead log declarations
2001-05-23 15:26:42 +02:00
ROLLBACK;
END_ERROR;
START_TRANSACTION;
}
*/
2001-05-23 15:26:42 +02:00
/* If there is a description of the database, modify it now */
FOR D IN RDB$DATABASE
MODIFY D USING
if (dbb->dbb_flags & DBB_null_security_class)
2003-09-10 19:52:12 +02:00
D.RDB$SECURITY_CLASS.NULL = TRUE;
if (dbb->dbb_flags & DBB_null_description)
D.RDB$DESCRIPTION.NULL = TRUE;
if (dbb->dbb_description) {
store_text(dbb->dbb_description, &D.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
D.RDB$DESCRIPTION.NULL = FALSE;
}
if (dbb->dbb_security_class) {
MOVE_SYMBOL(dbb->dbb_security_class, D.RDB$SECURITY_CLASS);
D.RDB$SECURITY_CLASS.NULL = FALSE;
}
END_MODIFY;
2001-05-23 15:26:42 +02:00
END_FOR;
get_global_fields();
get_relations(dbb);
get_udfs(dbb);
get_triggers(dbb);
}
2003-09-10 19:52:12 +02:00
bool EXE_relation( DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* E X E _ r e l a t i o n
*
**************************************
*
* Functional description
* Lookup a relation. On the way by,
* fix up the field position in the
* relation block;
*
**************************************/
2003-09-10 19:52:12 +02:00
bool result = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
SYM symbol = relation->rel_name;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ symbol->sym_string
2003-09-10 19:52:12 +02:00
result = true;
2001-05-23 15:26:42 +02:00
END_FOR;
FOR X IN RDB$RELATION_FIELDS WITH X.RDB$RELATION_NAME EQ symbol->sym_string
2003-09-10 19:52:12 +02:00
if (X.RDB$FIELD_POSITION > relation->rel_field_position)
relation->rel_field_position = X.RDB$FIELD_POSITION;
2001-05-23 15:26:42 +02:00
END_FOR;
return result;
}
/*
2001-05-23 15:26:42 +02:00
static void add_cache( DBB dbb)
{
// **************************************
// *
// * a d d _ c a c h e
// *
// **************************************
// *
// * Functional description
// * Add a shared cache file to database.
// *
// **************************************
2003-09-10 19:52:12 +02:00
bool result = false;
2001-05-23 15:26:42 +02:00
FOR FIL IN RDB$FILES WITH FIL.RDB$FILE_FLAGS EQ FILE_cache
2003-09-10 19:52:12 +02:00
result = true;
DDL_err(323, FIL.RDB$FILE_NAME, NULL, NULL, NULL, NULL);
// msg 323: a shared cache file %s already exists
2001-05-23 15:26:42 +02:00
END_FOR;
if (result)
return;
2004-03-07 08:58:55 +01:00
FIL file = dbb->dbb_cache_file;
2001-05-23 15:26:42 +02:00
STORE FIL IN RDB$FILES
2003-09-10 19:52:12 +02:00
MOVE_SYMBOL(file->fil_name, FIL.RDB$FILE_NAME);
FIL.RDB$FILE_START = 0;
FIL.RDB$FILE_LENGTH = file->fil_length;
FIL.RDB$FILE_FLAGS = FILE_cache;
END_STORE;
2001-05-23 15:26:42 +02:00
// Unless there are errors, commit the new shared cache immediately!
2001-05-23 15:26:42 +02:00
if (!dudleyGlob.DDL_errors) {
2003-08-30 04:02:36 +02:00
COMMIT ON_ERROR DDL_db_error(gds_status, 324, NULL, NULL, NULL, NULL, NULL);
// msg 324: error commiting new shared cache declaration
2001-05-23 15:26:42 +02:00
ROLLBACK;
END_ERROR;
START_TRANSACTION;
}
}
*/
2001-05-23 15:26:42 +02:00
static void add_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* a d d _ f i e l d
*
**************************************
*
* Functional description
* Add a field to a relation.
*
**************************************/
2004-03-07 08:58:55 +01:00
DUDLEY_REL relation = field->fld_relation;
SYM source = field->fld_source;
if (!source)
2001-05-23 15:26:42 +02:00
source = field->fld_name;
if (check_field(relation->rel_name, field->fld_name)) {
DDL_err(37, field->fld_name->sym_string,
relation->rel_name->sym_string, NULL, NULL, NULL);
/* msg 37: field %s already exists in relation %s */
return;
}
STORE X IN RDB$RELATION_FIELDS
MOVE_SYMBOL(relation->rel_name, X.RDB$RELATION_NAME);
MOVE_SYMBOL(field->fld_name, X.RDB$FIELD_NAME);
MOVE_SYMBOL(source, X.RDB$FIELD_SOURCE);
X.RDB$SECURITY_CLASS.NULL = TRUE;
X.RDB$FIELD_POSITION.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$QUERY_HEADER.NULL = TRUE;
X.RDB$EDIT_STRING.NULL = TRUE;
if (field->fld_security_class) {
X.RDB$SECURITY_CLASS.NULL = FALSE;
MOVE_SYMBOL(field->fld_security_class, X.RDB$SECURITY_CLASS);
}
if (field->fld_flags & fld_explicit_position) {
X.RDB$FIELD_POSITION.NULL = FALSE;
X.RDB$FIELD_POSITION = field->fld_position;
}
if (field->fld_query_name) {
MOVE_SYMBOL(field->fld_query_name, X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
}
if (field->fld_description) {
store_text(field->fld_description, &X.RDB$DESCRIPTION);
2001-05-23 15:26:42 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
if (field->fld_edit_string) {
X.RDB$EDIT_STRING.NULL = FALSE;
MOVE_SYMBOL(field->fld_edit_string, X.RDB$EDIT_STRING);
}
if (field->fld_query_header) {
X.RDB$QUERY_HEADER.NULL = FALSE;
store_query_header(field->fld_query_header, &X.RDB$QUERY_HEADER);
2001-05-23 15:26:42 +02:00
}
if (field->fld_system)
X.RDB$SYSTEM_FLAG = field->fld_system;
else
X.RDB$SYSTEM_FLAG = relation->rel_system;
END_STORE;
}
static void add_files( DBB dbb, FIL files)
{
/**************************************
*
* a d d _ f i l e s
*
**************************************
*
* Functional description
* Add a file to an existing database.
*
**************************************/
SLONG length, start;
FIL file, next;
TEXT s[128];
SSHORT shadow_number;
/* Reverse the order of files (parser left them backwards) */
for (file = files, files = NULL; file; file = next) {
next = file->fil_next;
file->fil_next = files;
files = file;
}
/* To assign page ranges, we need a place to start. Get
current allocation of database, then check the allocation
against the user given maximum length (if given). */
if (dbb) {
2003-11-08 00:27:24 +01:00
if (isc_database_info(gds_status, &DB, sizeof(alloc_info), alloc_info,
sizeof(s), s) || s[0] != isc_info_allocation)
{
2003-08-30 04:02:36 +02:00
DDL_err(38, NULL, NULL, NULL, NULL, NULL);
2003-11-08 00:27:24 +01:00
/* msg 38: isc_database_info failed */
}
2001-05-23 15:26:42 +02:00
length = gds__vax_integer(reinterpret_cast<const UCHAR*>(s + 1), 2);
start = gds__vax_integer(reinterpret_cast<const UCHAR*>(s + 3), length);
2001-05-23 15:26:42 +02:00
length = (dbb->dbb_length) ? dbb->dbb_length + 1 : 0;
start = MAX(start, length);
}
else {
length = 0;
start = 0;
}
2001-05-23 15:26:42 +02:00
shadow_number = 0;
for (file = files; file; file = file->fil_next) {
if (file->fil_shadow_number != shadow_number) {
start = 0;
shadow_number = file->fil_shadow_number;
}
else if (!length && !file->fil_start)
DDL_err(39, file->fil_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 39: Preceding file did not specify length, so %s must include starting page number */
start = MAX(start, file->fil_start);
STORE X IN RDB$FILES MOVE_SYMBOL(file->fil_name, X.RDB$FILE_NAME);
X.RDB$FILE_START = start;
X.RDB$FILE_LENGTH = file->fil_length;
X.RDB$SHADOW_NUMBER = file->fil_shadow_number;
X.RDB$FILE_FLAGS = 0;
if (file->fil_manual)
X.RDB$FILE_FLAGS = FILE_manual;
if (file->fil_conditional)
X.RDB$FILE_FLAGS |= FILE_conditional;
END_STORE;
length = file->fil_length;
start += length;
}
/* Unless there are errors floating around, commit the new file immediately! */
if (!dudleyGlob.DDL_errors) {
2003-08-30 04:02:36 +02:00
COMMIT ON_ERROR DDL_db_error(gds_status, 40, NULL, NULL, NULL, NULL, NULL);
/* msg 40: error commiting new file declarations */
2001-05-23 15:26:42 +02:00
ROLLBACK;
END_ERROR;
START_TRANSACTION;
}
}
static void add_filter( FILTER filter)
{
/**************************************
*
* a d d _ f i l t e r
*
**************************************
*
* Functional description
* Add a new filter.
*
**************************************/
STORE X IN RDB$FILTERS USING X.RDB$MODULE_NAME.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
MOVE_SYMBOL(filter->filter_name, X.RDB$FUNCTION_NAME);
X.RDB$INPUT_SUB_TYPE = filter->filter_input_sub_type;
X.RDB$OUTPUT_SUB_TYPE = filter->filter_output_sub_type;
if (filter->filter_module_name) {
X.RDB$MODULE_NAME.NULL = FALSE;
MOVE_SYMBOL(filter->filter_module_name, X.RDB$MODULE_NAME);
}
MOVE_SYMBOL(filter->filter_entry_point, X.RDB$ENTRYPOINT);
if (filter->filter_description) {
store_text(filter->filter_description, &X.RDB$DESCRIPTION);
2001-05-23 15:26:42 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
END_STORE;
}
static void add_function( FUNC function)
{
/**************************************
*
* a d d _ f u n c t i o n
*
**************************************
*
* Functional description
* Add a new function.
*
**************************************/
if (check_function(function->func_name)) {
2003-08-30 04:02:36 +02:00
DDL_err(41, function->func_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 41: function %s already exists */
2001-05-23 15:26:42 +02:00
return;
}
STORE X IN RDB$FUNCTIONS USING X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$MODULE_NAME.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
MOVE_SYMBOL(function->func_name, X.RDB$FUNCTION_NAME);
if (function->func_query_name) {
X.RDB$QUERY_NAME.NULL = FALSE;
MOVE_SYMBOL(function->func_query_name, X.RDB$QUERY_NAME);
}
if (function->func_module_name) {
X.RDB$MODULE_NAME.NULL = FALSE;
MOVE_SYMBOL(function->func_module_name, X.RDB$MODULE_NAME);
}
MOVE_SYMBOL(function->func_entry_point, X.RDB$ENTRYPOINT);
if (function->func_description) {
store_text(function->func_description, &X.RDB$DESCRIPTION);
2001-05-23 15:26:42 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
X.RDB$RETURN_ARGUMENT = function->func_return_arg;
END_STORE;
}
static void add_function_arg( FUNCARG func_arg)
{
/**************************************
*
* a d d _ f u n c t i o n _ a r g
*
**************************************
*
* Functional description
* Add a new function argument.
*
**************************************/
STORE X IN RDB$FUNCTION_ARGUMENTS
MOVE_SYMBOL(func_arg->funcarg_funcname, X.RDB$FUNCTION_NAME);
X.RDB$ARGUMENT_POSITION = func_arg->funcarg_position;
X.RDB$MECHANISM = func_arg->funcarg_mechanism;
X.RDB$FIELD_TYPE = func_arg->funcarg_dtype;
if (func_arg->funcarg_has_sub_type) {
X.RDB$FIELD_SUB_TYPE = func_arg->funcarg_sub_type;
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
}
else
X.RDB$FIELD_SUB_TYPE.NULL = TRUE;
X.RDB$FIELD_SCALE = func_arg->funcarg_scale;
X.RDB$FIELD_LENGTH = func_arg->funcarg_length;
END_STORE;
}
static void add_generator( SYM symbol)
{
/**************************************
*
* a d d _ g e n e r a t o r
*
**************************************
*
* Functional description
* Add a new generator.
*
**************************************/
STORE X IN RDB$GENERATORS MOVE_SYMBOL(symbol, X.RDB$GENERATOR_NAME);
END_STORE;
}
static void add_global_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* a d d _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
* Add a field to a relation.
*
**************************************/
DSC desc;
2004-03-07 08:58:55 +01:00
SYM name = field->fld_name;
2001-05-23 15:26:42 +02:00
STORE X IN RDB$FIELDS X.RDB$SEGMENT_LENGTH.NULL = TRUE;
X.RDB$COMPUTED_BLR.NULL = TRUE;
X.RDB$COMPUTED_SOURCE.NULL = TRUE;
X.RDB$VALIDATION_BLR.NULL = TRUE;
X.RDB$VALIDATION_SOURCE.NULL = TRUE;
X.RDB$MISSING_VALUE.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$QUERY_HEADER.NULL = TRUE;
X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$EDIT_STRING.NULL = TRUE;
X.RDB$DIMENSIONS.NULL = TRUE;
X.RDB$DEFAULT_VALUE.NULL = TRUE;
if (field->fld_computed) {
store_blr(field->fld_computed, &X.RDB$COMPUTED_BLR, NULL);
store_text(field->fld_compute_src, &X.RDB$COMPUTED_SOURCE);
2001-05-23 15:26:42 +02:00
X.RDB$COMPUTED_BLR.NULL = FALSE;
X.RDB$COMPUTED_SOURCE.NULL = FALSE;
if (!field->fld_dtype) {
make_desc(field->fld_computed, &desc);
field->fld_dtype = desc.dsc_dtype;
field->fld_length = desc.dsc_length;
if (DTYPE_IS_TEXT(make_dtype(desc.dsc_dtype))) {
2001-05-23 15:26:42 +02:00
field->fld_scale = 0;
field->fld_sub_type = desc.dsc_ttype();
2001-05-23 15:26:42 +02:00
field->fld_has_sub_type = TRUE;
}
else {
field->fld_sub_type = 0;
field->fld_scale = desc.dsc_scale;
}
}
}
if (field->fld_default) {
store_blr(field->fld_default, &X.RDB$DEFAULT_VALUE, NULL);
2001-05-23 15:26:42 +02:00
X.RDB$DEFAULT_VALUE.NULL = FALSE;
}
MOVE_SYMBOL(name, X.RDB$FIELD_NAME);
X.RDB$FIELD_TYPE = (int) field->fld_dtype;
X.RDB$FIELD_LENGTH = field->fld_length;
X.RDB$FIELD_SCALE = field->fld_scale;
X.RDB$SYSTEM_FLAG = field->fld_system;
X.RDB$FIELD_SUB_TYPE = field->fld_sub_type;
if (field->fld_segment_length && (X.RDB$FIELD_TYPE == blr_blob)) {
X.RDB$SEGMENT_LENGTH = field->fld_segment_length;
X.RDB$SEGMENT_LENGTH.NULL = FALSE;
}
if (field->fld_missing) {
store_blr(field->fld_missing, &X.RDB$MISSING_VALUE, NULL);
2001-05-23 15:26:42 +02:00
X.RDB$MISSING_VALUE.NULL = FALSE;
}
if (field->fld_validation) {
store_blr(field->fld_validation, &X.RDB$VALIDATION_BLR, NULL);
store_text(field->fld_valid_src, &X.RDB$VALIDATION_SOURCE);
2001-05-23 15:26:42 +02:00
X.RDB$VALIDATION_BLR.NULL = FALSE;
X.RDB$VALIDATION_SOURCE.NULL = FALSE;
}
if (field->fld_description) {
store_text(field->fld_description, &X.RDB$DESCRIPTION);
2001-05-23 15:26:42 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
if (field->fld_query_name) {
MOVE_SYMBOL(field->fld_query_name, X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
}
if (field->fld_edit_string) {
X.RDB$EDIT_STRING.NULL = FALSE;
MOVE_SYMBOL(field->fld_edit_string, X.RDB$EDIT_STRING);
}
if (field->fld_query_header) {
X.RDB$QUERY_HEADER.NULL = FALSE;
store_query_header(field->fld_query_header, &X.RDB$QUERY_HEADER);
2001-05-23 15:26:42 +02:00
}
if (field->fld_dimension) {
X.RDB$DIMENSIONS.NULL = FALSE;
X.RDB$DIMENSIONS = field->fld_dimension;
store_range(field);
}
END_STORE;
}
static void add_index( DUDLEY_IDX index)
{
/**************************************
*
* a d d _ i n d e x
*
**************************************
*
* Functional description
* Add an index to a database.
*
**************************************/
2003-09-10 19:52:12 +02:00
USHORT i;
bool error = false;
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$RELATIONS WITH
X.RDB$RELATION_NAME = index->idx_relation->sym_string
if (!X.RDB$VIEW_BLR.NULL) {
2003-09-10 19:52:12 +02:00
DDL_err(42, index->idx_relation->sym_string, NULL, NULL, NULL, NULL);
// msg 42: %s is a view and can not be indexed
error = true;
}
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (error)
return;
if (!if_any) {
2003-08-30 04:02:36 +02:00
DDL_err(43, index->idx_relation->sym_string, NULL, NULL, NULL, NULL);
// msg 43: relation %s doesn't exist
2001-05-23 15:26:42 +02:00
return;
}
2004-03-07 08:58:55 +01:00
USHORT size = 0;
for (int pos = 0; pos < index->idx_count ; pos++)
{
SYM symbol = index->idx_field[pos];
DUDLEY_FLD field = check_field(index->idx_relation, symbol);
if (!field) {
DDL_err(44, index->idx_name->sym_string, symbol->sym_string,
index->idx_relation->sym_string, NULL, NULL);
// msg 44: index %s: field %s doesn't exist in relation %s
2001-05-23 15:26:42 +02:00
return;
}
if (field->fld_computed) {
DDL_err(45, index->idx_name->sym_string, symbol->sym_string,
index->idx_relation->sym_string, NULL, NULL);
// msg 45: index %s: field %s in %s is computed and can not be a key
2001-05-23 15:26:42 +02:00
return;
}
size += field->fld_length;
}
if ((index->idx_count == 1) && size > 254) {
2004-03-14 06:51:54 +01:00
DDL_err(46, (TEXT *)(IPTR) size, index->idx_name->sym_string, NULL, NULL,
2001-05-23 15:26:42 +02:00
NULL);
/* msg 46: combined key length (%d) for index %s is > 254 bytes */
return;
}
else if ((index->idx_count > 1) && size > 202) {
2004-03-14 06:51:54 +01:00
DDL_err(312, (TEXT *)(IPTR) size, index->idx_name->sym_string, NULL, NULL,
2001-05-23 15:26:42 +02:00
NULL);
/* msg 312: key length (%d) for compound index %s exceeds 202 */
return;
}
STORE X IN RDB$INDICES MOVE_SYMBOL(index->idx_name, X.RDB$INDEX_NAME);
MOVE_SYMBOL(index->idx_relation, X.RDB$RELATION_NAME);
X.RDB$SEGMENT_COUNT = index->idx_count;
2003-09-10 19:52:12 +02:00
X.RDB$UNIQUE_FLAG = (index->idx_unique) ? TRUE : FALSE;
2001-05-23 15:26:42 +02:00
X.RDB$INDEX_INACTIVE = (index->idx_inactive) ? TRUE : FALSE;
2003-09-15 04:15:27 +02:00
if (index->idx_type) {
2003-09-12 18:32:19 +02:00
X.RDB$INDEX_TYPE = index->idx_type;
2001-05-23 15:26:42 +02:00
X.RDB$INDEX_TYPE.NULL = FALSE;
}
else
X.RDB$INDEX_TYPE.NULL = TRUE;
if (index->idx_description) {
store_text(index->idx_description, &X.RDB$DESCRIPTION);
2001-05-23 15:26:42 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
else
X.RDB$DESCRIPTION.NULL = TRUE;
2004-03-07 08:58:55 +01:00
END_STORE
ON_ERROR
if (gds_status[1] == isc_no_dup) {
DDL_err(47, index->idx_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 47: index %s already exists */
return;
}
2001-05-23 15:26:42 +02:00
DDL_db_error(gds_status, 48, index->idx_name->sym_string, NULL, NULL,
2001-05-23 15:26:42 +02:00
NULL, NULL);
2003-09-10 19:52:12 +02:00
// msg 48: error creating index %s
2001-05-23 15:26:42 +02:00
return;
END_ERROR;
/* if there wasn't an index record, clean up any orphan index segments */
FOR X IN RDB$INDEX_SEGMENTS
WITH X.RDB$INDEX_NAME = index->idx_name->sym_string
2003-09-10 19:52:12 +02:00
ERASE X;
2001-05-23 15:26:42 +02:00
END_FOR;
for (i = 0; i < index->idx_count; i++) {
STORE X IN RDB$INDEX_SEGMENTS
MOVE_SYMBOL(index->idx_name, X.RDB$INDEX_NAME);
2003-09-10 19:52:12 +02:00
MOVE_SYMBOL(index->idx_field[i], X.RDB$FIELD_NAME);
X.RDB$FIELD_POSITION = i;
END_STORE;
}
2001-05-23 15:26:42 +02:00
}
/*
2001-05-23 15:26:42 +02:00
static void add_log_files( DBB dbb)
{
// **************************************
// *
// * a d d _ l o g _ f i l e s
// *
// **************************************
// *
// * Functional description
// * Add log files to a database.
// *
// **************************************
2001-05-23 15:26:42 +02:00
FIL file, next;
// Reverse the order of files (parser left them backwards)
2001-05-23 15:26:42 +02:00
for (file = dbb->dbb_logfiles, dbb->dbb_logfiles = NULL; file;
2004-03-07 08:58:55 +01:00
file = next)
{
2001-05-23 15:26:42 +02:00
next = file->fil_next;
file->fil_next = dbb->dbb_logfiles;
dbb->dbb_logfiles = file;
}
2004-03-07 08:58:55 +01:00
SSHORT number = 0;
2001-05-23 15:26:42 +02:00
// Add default values for file size
2001-05-23 15:26:42 +02:00
if (dbb->dbb_flags & DBB_log_default) {
STORE X IN RDB$LOG_FILES MOVE_SYMBOL(dbb->dbb_name, X.RDB$FILE_NAME);
X.RDB$FILE_LENGTH = 0L;
X.RDB$FILE_SEQUENCE = number++;
X.RDB$FILE_PARTITIONS = 0;
X.RDB$FILE_FLAGS = LOG_serial | LOG_default;
END_STORE;
}
for (file = dbb->dbb_logfiles; file; file = file->fil_next) {
STORE X IN RDB$LOG_FILES MOVE_SYMBOL(file->fil_name, X.RDB$FILE_NAME);
X.RDB$FILE_LENGTH = file->fil_length;
X.RDB$FILE_SEQUENCE = number++;
X.RDB$FILE_PARTITIONS = file->fil_partitions;
X.RDB$FILE_FLAGS = file->fil_raw;
if (dbb->dbb_flags & DBB_log_serial)
X.RDB$FILE_FLAGS |= LOG_serial;
END_STORE;
}
if (file = dbb->dbb_overflow) {
STORE X IN RDB$LOG_FILES MOVE_SYMBOL(file->fil_name, X.RDB$FILE_NAME);
X.RDB$FILE_LENGTH = file->fil_length;
X.RDB$FILE_SEQUENCE = number++;
X.RDB$FILE_PARTITIONS = file->fil_partitions;
X.RDB$FILE_FLAGS = LOG_serial | LOG_overflow;
END_STORE;
}
// Unless there were errors , commit immediately!
2001-05-23 15:26:42 +02:00
if (!dudleyGlob.DDL_errors) {
2003-08-30 04:02:36 +02:00
COMMIT ON_ERROR DDL_db_error(gds_status, 321, NULL, NULL, NULL, NULL, NULL);
2003-09-10 19:52:12 +02:00
// msg 321: error commiting new write ahead log declarations
2001-05-23 15:26:42 +02:00
ROLLBACK;
END_ERROR;
START_TRANSACTION;
}
}
*/
2001-05-23 15:26:42 +02:00
static void add_relation( DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* a d d _ r e l a t i o n
*
**************************************
*
* Functional description
* Add a new relation.
*
**************************************/
if (relation->rel_rse) {
add_view(relation);
return;
}
if (check_relation(relation->rel_name)) {
2003-08-30 04:02:36 +02:00
DDL_err(49, relation->rel_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 49: relation %s already exists */
2001-05-23 15:26:42 +02:00
return;
}
STORE X IN RDB$RELATIONS X.RDB$SECURITY_CLASS.NULL = TRUE;
X.RDB$EXTERNAL_FILE.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
if (relation->rel_security_class) {
X.RDB$SECURITY_CLASS.NULL = FALSE;
MOVE_SYMBOL(relation->rel_security_class, X.RDB$SECURITY_CLASS);
}
if (relation->rel_filename) {
X.RDB$EXTERNAL_FILE.NULL = FALSE;
MOVE_SYMBOL(relation->rel_filename, X.RDB$EXTERNAL_FILE);
}
MOVE_SYMBOL(relation->rel_name, X.RDB$RELATION_NAME);
if (relation->rel_description) {
store_text(relation->rel_description, &X.RDB$DESCRIPTION);
2001-05-23 15:26:42 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
X.RDB$SYSTEM_FLAG = relation->rel_system;
END_STORE;
}
static void add_security_class( SCL sec_class)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* a d d _ s e c u r i t y _ c l a s s
*
**************************************
*
* Functional description
* Add a new security class.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
SYM name = sec_class->scl_name;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$SECURITY_CLASSES WITH X.RDB$SECURITY_CLASS EQ name->sym_string
2003-09-10 19:52:12 +02:00
if_any = true;
DDL_err(50, name->sym_string, NULL, NULL, NULL, NULL);
2003-08-30 04:02:36 +02:00
/* msg 50: security class %s already exists */
2001-05-23 15:26:42 +02:00
END_FOR;
if (if_any)
return;
STORE X IN RDB$SECURITY_CLASSES
2003-09-10 19:52:12 +02:00
MOVE_SYMBOL(name, X.RDB$SECURITY_CLASS);
if (sec_class->scl_description) {
store_text(sec_class->scl_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
else
X.RDB$DESCRIPTION.NULL = TRUE;
store_acl(sec_class, &X.RDB$ACL);
2001-05-23 15:26:42 +02:00
END_STORE;
}
static void add_trigger( DUDLEY_TRG trigger)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* a d d _ t r i g g e r
*
**************************************
*
* Functional description
* add a trigger for a relation in rdb$triggers.
*
**************************************/
2004-03-07 08:58:55 +01:00
DUDLEY_REL relation = trigger->trg_relation;
2001-05-23 15:26:42 +02:00
FOR F IN RDB$RELATION_FIELDS CROSS V IN RDB$VIEW_RELATIONS WITH
F.RDB$RELATION_NAME = V.RDB$VIEW_NAME AND
F.RDB$RELATION_NAME = relation->rel_name->sym_string
MODIFY F USING
2003-09-10 19:52:12 +02:00
F.RDB$UPDATE_FLAG = TRUE;
END_MODIFY;
2001-05-23 15:26:42 +02:00
END_FOR;
STORE X IN RDB$TRIGGERS
2003-09-10 19:52:12 +02:00
X.RDB$TRIGGER_SOURCE.NULL = TRUE;
X.RDB$TRIGGER_BLR.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
MOVE_SYMBOL(trigger->trg_name, X.RDB$TRIGGER_NAME);
MOVE_SYMBOL(relation->rel_name, X.RDB$RELATION_NAME);
X.RDB$TRIGGER_SEQUENCE = trigger->trg_sequence;
X.RDB$TRIGGER_TYPE = (SSHORT) trigger->trg_type;
X.RDB$TRIGGER_INACTIVE = trigger->trg_inactive;
if (trigger->trg_source) {
X.RDB$TRIGGER_SOURCE.NULL = FALSE;
store_text(trigger->trg_source, &X.RDB$TRIGGER_SOURCE);
2003-09-10 19:52:12 +02:00
}
if (trigger->trg_statement) {
X.RDB$TRIGGER_BLR.NULL = FALSE;
store_blr(trigger->trg_statement, &X.RDB$TRIGGER_BLR, NULL);
2003-09-10 19:52:12 +02:00
}
if (trigger->trg_description) {
X.RDB$DESCRIPTION.NULL = FALSE;
store_text(trigger->trg_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
}
2001-05-23 15:26:42 +02:00
END_STORE;
}
static void add_trigger_msg( TRGMSG trigmsg)
{
/**************************************
*
* a d d _ t r i g g e r _ m s g
*
**************************************
*
* Functional description
* Add a new trigger message.
*
**************************************/
STORE X IN RDB$TRIGGER_MESSAGES
MOVE_SYMBOL(trigmsg->trgmsg_trg_name, X.RDB$TRIGGER_NAME);
2003-09-10 19:52:12 +02:00
X.RDB$MESSAGE_NUMBER = trigmsg->trgmsg_number;
MOVE_SYMBOL(trigmsg->trgmsg_text, X.RDB$MESSAGE);
2001-05-23 15:26:42 +02:00
END_STORE;
}
static void add_type( TYP fldtype)
{
/**************************************
*
* a d d _ t y p e
*
**************************************
*
* Functional description
* Add all new type values for a given field.
*
**************************************/
STORE X IN RDB$TYPES
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = TRUE;
MOVE_SYMBOL(fldtype->typ_field_name, X.RDB$FIELD_NAME);
MOVE_SYMBOL(fldtype->typ_name, X.RDB$TYPE_NAME);
X.RDB$TYPE = fldtype->typ_type;
if (fldtype->typ_description) {
X.RDB$DESCRIPTION.NULL = FALSE;
store_text(fldtype->typ_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
}
2001-05-23 15:26:42 +02:00
END_STORE;
}
static void add_user_privilege( USERPRIV upriv)
{
/**************************************
*
* a d d _ u s e r _ p r i v i l e g e
*
**************************************
*
* Functional description
* Add as many rdb$user_privilege entries as needed
* for the GRANT statement.
*
**************************************/
TEXT grantor[32], priv[7];
2003-09-10 19:52:12 +02:00
bool if_any = false;
USHORT privflag;
2001-05-23 15:26:42 +02:00
USRE usr; /* user entry */
UPFE upf; /* user privilege field entry */
/* rdb$owner_name doesn't get filled in until we store the relation */
FOR X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ upriv->userpriv_relation->sym_string
2003-09-10 19:52:12 +02:00
strcpy(grantor, X.RDB$OWNER_NAME);
if_any = true;
END_FOR;
2001-05-23 15:26:42 +02:00
if (!if_any) {
DDL_err(54, upriv->userpriv_relation->sym_string, NULL, NULL, NULL,
NULL);
/* msg 54: relation %s doesn't exist */
return;
}
/* we need one rdb$user_privileges entry per each user/privilege/field
combination so start by looping through each user in user list, then
loop for each privilege, and if update privilege, loop for each field */
for (usr = upriv->userpriv_userlist; usr; usr = usr->usre_next) {
/* start with a fresh copy of privflag and erase each
privilege as we take care of it */
privflag = upriv->userpriv_flags & ~USERPRIV_grant;
while (privflag) {
upf = NULL;
if (privflag & USERPRIV_select) {
strcpy(priv, UPRIV_SELECT);
privflag ^= USERPRIV_select;
}
else if (privflag & USERPRIV_delete) {
strcpy(priv, UPRIV_DELETE);
privflag ^= USERPRIV_delete;
}
else if (privflag & USERPRIV_insert) {
strcpy(priv, UPRIV_INSERT);
privflag ^= USERPRIV_insert;
}
else if (privflag & USERPRIV_update) {
strcpy(priv, UPRIV_UPDATE);
privflag ^= USERPRIV_update;
/* no field list implies all fields */
if (!upriv->userpriv_upflist)
store_userpriv(upriv, grantor, priv, usr, upf);
else
/* update is the only privilege with a possible field list */
for (upf = upriv->userpriv_upflist; upf;
upf =
upf->upfe_next) store_userpriv(upriv, grantor, priv,
usr, upf);
continue;
}
store_userpriv(upriv, grantor, priv, usr, upf);
} /* while (privflag) */
} /* for */
}
static void add_view( DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* a d d _ v i e w
*
**************************************
*
* Functional description
* Add a new view relation.
*
**************************************/
DUDLEY_FLD field;
DUDLEY_REL target;
2004-03-07 08:58:55 +01:00
DUDLEY_NOD contexts;
DUDLEY_CTX context;
2001-05-23 15:26:42 +02:00
USHORT i;
if (check_relation(relation->rel_name)) {
2003-08-30 04:02:36 +02:00
DDL_err(55, relation->rel_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 55: relation %s already exists */
2001-05-23 15:26:42 +02:00
return;
}
2004-03-07 08:58:55 +01:00
DUDLEY_NOD rse = relation->rel_rse;
2001-05-23 15:26:42 +02:00
// Store the relation record proper
2001-05-23 15:26:42 +02:00
STORE X IN RDB$RELATIONS
MOVE_SYMBOL(relation->rel_name, X.RDB$RELATION_NAME);
store_blr(rse, &X.RDB$VIEW_BLR, relation);
store_text(relation->rel_view_source, &X.RDB$VIEW_SOURCE);
2003-09-10 19:52:12 +02:00
if (relation->rel_security_class) {
X.RDB$SECURITY_CLASS.NULL = FALSE;
MOVE_SYMBOL(relation->rel_security_class, X.RDB$SECURITY_CLASS);
}
else
X.RDB$SECURITY_CLASS.NULL = TRUE;
if (relation->rel_description) {
store_text(relation->rel_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
else
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$SYSTEM_FLAG = relation->rel_system;
2001-05-23 15:26:42 +02:00
END_STORE
// Store VIEW_RELATIONS for each relation in view
contexts = rse->nod_arg[s_rse_contexts];
for (i = 0; i < contexts->nod_count; i++) {
2001-05-23 15:26:42 +02:00
STORE X IN RDB$VIEW_RELATIONS
context = (DUDLEY_CTX) contexts->nod_arg[i]->nod_arg[0];
2003-09-10 19:52:12 +02:00
target = context->ctx_relation;
MOVE_SYMBOL(relation->rel_name, X.RDB$VIEW_NAME);
MOVE_SYMBOL(target->rel_name, X.RDB$RELATION_NAME);
MOVE_SYMBOL(context->ctx_name, X.RDB$CONTEXT_NAME);
X.RDB$VIEW_CONTEXT = context->ctx_context_id;
END_STORE;
}
2001-05-23 15:26:42 +02:00
// Store the various fields
2001-05-23 15:26:42 +02:00
for (field = relation->rel_fields; field; field = field->fld_next) {
if (check_field(relation->rel_name, field->fld_name))
DDL_err(56, field->fld_name->sym_string,
relation->rel_name->sym_string, NULL, NULL, NULL);
/* msg 56: field %s already exists in relation %s */
STORE X IN RDB$RELATION_FIELDS
2003-09-10 19:52:12 +02:00
X.RDB$SECURITY_CLASS.NULL = TRUE;
X.RDB$FIELD_POSITION.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$QUERY_HEADER.NULL = TRUE;
X.RDB$EDIT_STRING.NULL = TRUE;
MOVE_SYMBOL(relation->rel_name, X.RDB$RELATION_NAME);
MOVE_SYMBOL(field->fld_name, X.RDB$FIELD_NAME);
if (field->fld_computed) {
MOVE_SYMBOL(field->fld_source, X.RDB$FIELD_SOURCE);
X.RDB$BASE_FIELD.NULL = TRUE;
X.RDB$VIEW_CONTEXT = 0;
}
else {
X.RDB$BASE_FIELD.NULL = FALSE;
MOVE_SYMBOL(field->fld_base, X.RDB$BASE_FIELD);
context = field->fld_context;
target = context->ctx_relation;
if (!check_field(target->rel_name, field->fld_base))
DDL_err(57,
field->fld_base->sym_string,
target->rel_name->sym_string,
field->fld_name->sym_string, NULL, NULL);
/* msg 57: field %s doesn't exist in relation %s as referenced in view field %s */
X.RDB$VIEW_CONTEXT = context->ctx_context_id;
FOR RFR IN RDB$RELATION_FIELDS WITH
RFR.RDB$RELATION_NAME EQ target->rel_name->sym_string AND
RFR.RDB$FIELD_NAME EQ field->fld_base->sym_string
gds__vtov(RFR.RDB$FIELD_SOURCE,
X.RDB$FIELD_SOURCE, sizeof(X.RDB$FIELD_SOURCE));
END_FOR;
}
if (field->fld_security_class) {
X.RDB$SECURITY_CLASS.NULL = FALSE;
MOVE_SYMBOL(field->fld_security_class, X.RDB$SECURITY_CLASS);
}
if (field->fld_flags & fld_explicit_position) {
X.RDB$FIELD_POSITION.NULL = FALSE;
X.RDB$FIELD_POSITION = field->fld_position;
}
if (field->fld_query_name) {
MOVE_SYMBOL(field->fld_query_name, X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
}
if (field->fld_description) {
store_text(field->fld_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
if (field->fld_edit_string) {
X.RDB$EDIT_STRING.NULL = FALSE;
MOVE_SYMBOL(field->fld_edit_string, X.RDB$EDIT_STRING);
}
if (field->fld_query_header) {
X.RDB$QUERY_HEADER.NULL = FALSE;
store_query_header(field->fld_query_header, &X.RDB$QUERY_HEADER);
2003-09-10 19:52:12 +02:00
}
if (field->fld_system)
X.RDB$SYSTEM_FLAG = field->fld_system;
else
X.RDB$SYSTEM_FLAG = relation->rel_system;
2001-05-23 15:26:42 +02:00
END_STORE;
}
}
static void alloc_file_name( FIL * start_file, UCHAR * file_name)
{
/**************************************
*
* a l l o c _ f i l e _ n a m e
*
**************************************
*
* Functional description
* Add a file name only once. No duplicates.
*
**************************************/
2004-03-07 08:58:55 +01:00
for (FIL temp = *start_file; temp; temp = temp->fil_next)
if (!strcmp(temp->fil_name->sym_name, (char*) file_name))
2001-05-23 15:26:42 +02:00
return;
2004-03-07 08:58:55 +01:00
FIL file = (FIL) DDL_alloc(sizeof(fil));
2001-05-23 15:26:42 +02:00
file->fil_next = *start_file;
*start_file = file;
2004-03-07 08:58:55 +01:00
SYM string = (SYM) DDL_alloc(SYM_LEN + strlen((char*) file_name));
strcpy(string->sym_name, (char*) file_name);
2001-05-23 15:26:42 +02:00
file->fil_name = string;
}
static DUDLEY_FLD check_field( SYM relation, SYM field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c h e c k _ f i e l d
*
**************************************
*
* Functional description
* Check to see if a field already exists in RFR.
*
**************************************/
FOR X IN RDB$RELATION_FIELDS WITH
X.RDB$RELATION_NAME EQ relation->sym_string AND
X.RDB$FIELD_NAME EQ field->sym_string
2003-09-10 19:52:12 +02:00
{
2004-03-07 08:58:55 +01:00
SYM symbol = HSH_typed_lookup(X.RDB$FIELD_SOURCE, (USHORT) 0, SYM_global);
if (symbol)
2003-09-10 19:52:12 +02:00
return (DUDLEY_FLD) symbol->sym_object;
}
END_FOR;
2001-05-23 15:26:42 +02:00
return NULL;
}
2003-09-04 15:45:44 +02:00
static bool check_function( SYM name)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c h e c k _ f u n c t i o n
*
**************************************
*
* Functional description
* Check function for existence.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$FUNCTIONS WITH X.RDB$FUNCTION_NAME EQ name->sym_string
2003-09-04 15:45:44 +02:00
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
return if_any;
}
2003-09-04 15:45:44 +02:00
static bool check_range(DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c h e c k _ r a n g e
*
**************************************
*
* Functional description
* Don't let the poor user modify the
* datatype of an array unless he has
* specifed the indices correctly. Ahy
* deviation in the ranges is assumed
* to be an illconsidered modification.
*
**************************************/
BASED ON RDB$FIELD_DIMENSIONS.RDB$FIELD_NAME name;
2003-09-04 15:45:44 +02:00
bool if_any = false;
bool match = false;
2001-05-23 15:26:42 +02:00
MOVE_SYMBOL(field->fld_name, name);
2004-03-07 08:58:55 +01:00
const USHORT dims = field->fld_dimension;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
// existance: if neither is an array, life is good
// else if there are dimensions they'd better match
2001-05-23 15:26:42 +02:00
FOR X IN RDB$FIELDS WITH X.RDB$FIELD_NAME EQ name
2003-09-10 19:52:12 +02:00
if (!dims) {
if (!X.RDB$DIMENSIONS.NULL)
DDL_err(302, name, NULL, NULL, NULL, NULL);
// msg 302: Include complete field specification to change datatype of array %s
else
match = true;
}
else if (dims == X.RDB$DIMENSIONS)
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (match)
return match;
if (!dims)
2003-09-04 15:45:44 +02:00
return false;
2001-05-23 15:26:42 +02:00
if (if_any) {
2004-03-07 08:58:55 +01:00
const SLONG* range = field->fld_ranges;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$FIELD_DIMENSIONS WITH X.RDB$FIELD_NAME EQ name
SORTED BY ASCENDING X.RDB$DIMENSION
2003-09-04 15:45:44 +02:00
if ((*range++ != X.RDB$LOWER_BOUND) || (*range++ != X.RDB$UPPER_BOUND))
if_any = false;
2001-05-23 15:26:42 +02:00
END_FOR;
}
if (!if_any)
DDL_err(301, NULL, NULL, NULL, NULL, NULL);
return if_any;
}
2003-09-04 15:45:44 +02:00
static bool check_relation( SYM name)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c h e c k _ r e l a t i o n
*
**************************************
*
* Functional description
* Check relation for existence.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ name->sym_string
2003-09-04 15:45:44 +02:00
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
return if_any;
}
2004-05-03 01:06:37 +02:00
static void close_blob(FB_API_HANDLE blob)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c l o s e _ b l o b
*
**************************************
*
* Functional description
* Close a blob.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2003-09-10 19:52:12 +02:00
2003-11-08 00:27:24 +01:00
if (isc_close_blob(status_vector, &blob))
2003-08-30 04:02:36 +02:00
DDL_db_error(status_vector, 58, NULL, NULL, NULL, NULL, NULL);
2003-11-08 00:27:24 +01:00
/* msg 58: isc_close_blob failed */
2001-05-23 15:26:42 +02:00
}
2004-05-03 01:06:37 +02:00
static FB_API_HANDLE create_blob( ISC_QUAD* blob_id, USHORT bpb_length, const UCHAR* bpb)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c r e a t e _ b l o b
*
**************************************
*
* Functional description
* Create a new blob.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2004-05-03 01:06:37 +02:00
FB_API_HANDLE blob = 0;
2003-09-10 19:52:12 +02:00
2003-11-08 00:27:24 +01:00
if (isc_create_blob2(status_vector, &DB, &gds_trans, &blob,
blob_id, bpb_length,
reinterpret_cast<const SCHAR*>(bpb)))
{
2003-08-30 04:02:36 +02:00
DDL_db_error(status_vector, 59, NULL, NULL, NULL, NULL, NULL);
2003-11-08 00:27:24 +01:00
/* msg 59: isc_create_blob failed */
2004-05-03 01:06:37 +02:00
return 0;
2001-05-23 15:26:42 +02:00
}
return blob;
}
/*
2001-05-23 15:26:42 +02:00
static void drop_cache( DBB dbb)
{
// **************************************
// *
// * d r o p _ c a c h e
// *
// **************************************
// *
// * Functional description
// * Get rid of shared cache file in the database.
// *
// **************************************
2003-09-10 19:52:12 +02:00
bool found = false;
2001-05-23 15:26:42 +02:00
FOR FIL IN RDB$FILES WITH FIL.RDB$FILE_FLAGS EQ FILE_cache
2003-09-10 19:52:12 +02:00
ERASE FIL;
found = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!found)
2003-08-30 04:02:36 +02:00
DDL_err(325, NULL, NULL, NULL, NULL, NULL);
// msg 325: no shared cache file exists to drop
2001-05-23 15:26:42 +02:00
if (!dudleyGlob.DDL_errors) {
2001-05-23 15:26:42 +02:00
COMMIT
2003-09-10 19:52:12 +02:00
ON_ERROR
DDL_db_error(gds_status, 326, NULL, NULL, NULL, NULL, NULL);
// msg 326: error commiting deletion of shared cache file
ROLLBACK;
2001-05-23 15:26:42 +02:00
END_ERROR;
START_TRANSACTION;
}
}
*/
2001-05-23 15:26:42 +02:00
static void drop_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* d r o p _ f i e l d
*
**************************************
*
* Functional description
* Drop a field from a relation. First
* check that it's not referenced in a
* view (other that the current one, if the
* current relation happens to be a view).
* If the field is computed, and
* the current reference is not a view,
* erase the artificially named source field.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool error = false;
bool if_any = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
DUDLEY_REL relation = field->fld_relation;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$RELATION_FIELDS CROSS Y IN RDB$RELATION_FIELDS CROSS
Z IN RDB$VIEW_RELATIONS WITH
X.RDB$RELATION_NAME EQ relation->rel_name->sym_string AND
X.RDB$FIELD_NAME EQ field->fld_name->sym_string AND
X.RDB$FIELD_NAME = Y.RDB$BASE_FIELD AND
X.RDB$FIELD_SOURCE = Y.RDB$FIELD_SOURCE AND
Y.RDB$RELATION_NAME EQ Z.RDB$VIEW_NAME AND
X.RDB$RELATION_NAME EQ Z.RDB$RELATION_NAME AND
Y.RDB$VIEW_CONTEXT EQ Z.RDB$VIEW_CONTEXT
2003-09-10 19:52:12 +02:00
DDL_err(60, field->fld_name->sym_string,
relation->rel_name->sym_string,
Y.RDB$RELATION_NAME,
NULL, NULL);
// msg 60: field %s from relation %s is referenced in view %s
error = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (error)
return;
FOR FIRST 1 X IN RDB$RELATION_FIELDS WITH
X.RDB$RELATION_NAME EQ relation->rel_name->sym_string AND
X.RDB$FIELD_NAME EQ field->fld_name->sym_string
FOR Y IN RDB$RELATION_FIELDS WITH
2003-09-12 11:00:40 +02:00
Y.RDB$FIELD_NAME = X.RDB$BASE_FIELD
if_any = true;
2003-09-10 19:52:12 +02:00
END_FOR
if (!if_any) {
FOR Z IN RDB$FIELDS WITH
Z.RDB$FIELD_NAME = X.RDB$FIELD_SOURCE
AND NOT(Z.RDB$COMPUTED_BLR MISSING)
ERASE Z;
END_FOR;
}
ERASE X;
if_any = true;
END_FOR;
2001-05-23 15:26:42 +02:00
if (!if_any)
2003-09-10 19:52:12 +02:00
DDL_err(61, field->fld_name->sym_string,
2001-05-23 15:26:42 +02:00
relation->rel_name->sym_string, NULL, NULL, NULL);
/* msg 61: field %s doesn't exists in relation %s */
}
static void drop_filter( FILTER filter)
{
/**************************************
*
* d r o p _ f i l t e r
*
**************************************
*
* Functional description
* Get rid of a filter.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR F IN RDB$FILTERS WITH F.RDB$FUNCTION_NAME EQ filter->filter_name->sym_string
2003-09-10 19:52:12 +02:00
ERASE F;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(62, filter->filter_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 62: filter %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void drop_function( FUNC function)
{
/**************************************
*
* d r o p _ f u n c t i o n
*
**************************************
*
* Functional description
* Get rid of a function and its arguments.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
TEXT* name = function->func_name->sym_string;
2001-05-23 15:26:42 +02:00
/* Clean out function argument first. */
FOR FUNCARG IN RDB$FUNCTION_ARGUMENTS WITH FUNCARG.
RDB$FUNCTION_NAME EQ name ERASE FUNCARG;
END_FOR;
FOR FUNC IN RDB$FUNCTIONS WITH FUNC.RDB$FUNCTION_NAME EQ name
2003-09-10 19:52:12 +02:00
ERASE FUNC;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(63, name, NULL, NULL, NULL, NULL);
/* msg 63: function %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void drop_global_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* d r o p _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
* Drop a field from a relation.
*
**************************************/
SCHAR *p;
2003-09-10 19:52:12 +02:00
bool if_any = false;
bool error = false;
2001-05-23 15:26:42 +02:00
FOR Y IN RDB$RELATION_FIELDS WITH
Y.RDB$FIELD_SOURCE EQ field->fld_name->sym_string
for (p = Y.RDB$FIELD_SOURCE; *p && *p != ' '; p++);
2003-09-10 19:52:12 +02:00
*p = 0;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
for (p = Y.RDB$RELATION_NAME; *p && *p != ' '; p++);
*p = 0;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
for (p = Y.RDB$FIELD_NAME; *p && *p != ' '; p++);
*p = 0;
2001-05-23 15:26:42 +02:00
2003-09-10 19:52:12 +02:00
DDL_err(64, Y.RDB$FIELD_SOURCE,
Y.RDB$RELATION_NAME, Y.RDB$FIELD_NAME, NULL, NULL);
// msg 64: field %s is used in relation %s (local name %s) and can not be dropped
error = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (error)
return;
FOR X IN RDB$TYPES WITH
X.RDB$FIELD_NAME EQ field->fld_name->sym_string
2003-09-10 19:52:12 +02:00
ERASE X;
2001-05-23 15:26:42 +02:00
END_FOR;
FOR X IN RDB$FIELD_DIMENSIONS WITH
X.RDB$FIELD_NAME EQ field->fld_name->sym_string
2003-09-10 19:52:12 +02:00
ERASE X;
2001-05-23 15:26:42 +02:00
END_FOR;
FOR X IN RDB$FIELDS WITH
X.RDB$FIELD_NAME EQ field->fld_name->sym_string
2003-09-10 19:52:12 +02:00
ERASE X;
if_any = true;
END_FOR
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(65, field->fld_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 65: field %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void drop_index( DUDLEY_IDX index)
{
/**************************************
*
* d r o p _ i n d e x
*
**************************************
*
* Functional description
* Get rid of an index.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
TEXT* name = index->idx_name->sym_string;
2001-05-23 15:26:42 +02:00
/* Clean out index segments first. */
FOR SEG IN RDB$INDEX_SEGMENTS WITH SEG.RDB$INDEX_NAME EQ name
2003-09-10 19:52:12 +02:00
ERASE SEG;
2001-05-23 15:26:42 +02:00
END_FOR;
FOR IDX IN RDB$INDICES WITH IDX.RDB$INDEX_NAME EQ name
2003-09-10 19:52:12 +02:00
ERASE IDX;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(66, name, NULL, NULL, NULL, NULL);
/* msg 66: index %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void drop_relation( DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* d r o p _ r e l a t i o n
*
**************************************
*
* Functional description
* Drop a relation, friends, and relatives.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
TEXT* name = relation->rel_name->sym_string;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$VIEW_RELATIONS WITH X.RDB$RELATION_NAME EQ name
2003-08-30 04:02:36 +02:00
DDL_err(67, name, X.RDB$VIEW_NAME, NULL, NULL, NULL);
/* msg 67: %s referenced by view %s */
2001-05-23 15:26:42 +02:00
return;
END_FOR;
/* check that the relation exists and can be deleted */
FOR X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ name
if (X.RDB$SYSTEM_FLAG == 1) {
2003-09-10 19:52:12 +02:00
DDL_err(68, name, NULL, NULL, NULL, NULL);
// msg 68: can't drop system relation %s
return;
}
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any) {
2003-08-30 04:02:36 +02:00
DDL_err(69, name, NULL, NULL, NULL, NULL);
/* msg 69: relation %s doesn't exist */
2001-05-23 15:26:42 +02:00
return;
}
/* First, get rid of the relation itself. This will speed things later on. */
FOR X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ name
2003-09-10 19:52:12 +02:00
ERASE X;
2001-05-23 15:26:42 +02:00
END_FOR;
/* Clean out RDB$INDICES, RDB$VIEW_RELATIONS and RDB$RELATION_FIELDS */
FOR IDX IN RDB$INDICES WITH IDX.RDB$RELATION_NAME EQ name
FOR SEG IN RDB$INDEX_SEGMENTS WITH
2003-09-10 19:52:12 +02:00
SEG.RDB$INDEX_NAME EQ IDX.RDB$INDEX_NAME
ERASE SEG;
END_FOR;
ERASE IDX;
2001-05-23 15:26:42 +02:00
END_FOR;
FOR X IN RDB$VIEW_RELATIONS WITH X.RDB$VIEW_NAME EQ name
2003-09-10 19:52:12 +02:00
ERASE X;
2001-05-23 15:26:42 +02:00
END_FOR;
FOR X IN RDB$RELATION_FIELDS WITH X.RDB$RELATION_NAME EQ name
2003-09-10 19:52:12 +02:00
ERASE X;
2001-05-23 15:26:42 +02:00
END_FOR;
/* Finally, get rid of any user privileges */
FOR PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$RELATION_NAME EQ name AND
PRIV.RDB$OBJECT_TYPE = obj_relation
2003-09-10 19:52:12 +02:00
ERASE PRIV;
2001-05-23 15:26:42 +02:00
END_FOR
2003-09-10 19:52:12 +02:00
ON_ERROR
END_ERROR;
2001-05-23 15:26:42 +02:00
}
static void drop_security_class( SCL scl_class)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* d r o p _ s e c u r i t y _ c l a s s
*
**************************************
*
* Functional description
* Drop an existing security class name.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
SYM name = scl_class->scl_name;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$SECURITY_CLASSES WITH X.RDB$SECURITY_CLASS EQ name->sym_string
2003-09-10 19:52:12 +02:00
ERASE X;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(70, name->sym_string, NULL, NULL, NULL, NULL);
/* msg 70: security class %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void drop_shadow( SLONG shadow_number)
{
/**************************************
*
* d r o p _ s h a d o w
*
**************************************
*
* Functional description
* Get rid of all files in the database
* with the given shadow number.
*
**************************************/
2004-02-02 12:02:12 +01:00
dudley_lls* files = NULL;
dudley_lls* first_file = NULL;
2001-05-23 15:26:42 +02:00
FOR FIL IN RDB$FILES WITH
FIL.RDB$SHADOW_NUMBER EQ shadow_number
2003-09-10 19:52:12 +02:00
ERASE FIL;
2004-03-07 08:58:55 +01:00
SYM string = (SYM) DDL_alloc(SYM_LEN + strlen(FIL.RDB$FILE_NAME));
2003-09-10 19:52:12 +02:00
strcpy(string->sym_name, FIL.RDB$FILE_NAME);
DDL_push((DUDLEY_NOD) string, &files);
if (!first_file)
first_file = files;
END_FOR;
2001-05-23 15:26:42 +02:00
if (!files)
2004-03-14 06:51:54 +01:00
DDL_err(71, (TEXT *)(IPTR) shadow_number, NULL, NULL, NULL, NULL);
2003-08-30 04:02:36 +02:00
/* msg 71: shadow %ld doesn't exist */
2001-05-23 15:26:42 +02:00
if (!dudleyGlob.DDL_errors) {
2001-05-23 15:26:42 +02:00
COMMIT
2003-09-10 19:52:12 +02:00
ON_ERROR
DDL_db_error(gds_status, 72, NULL, NULL, NULL, NULL, NULL);
2003-08-30 04:02:36 +02:00
/* msg 72: error commiting deletion of shadow */
2003-09-10 19:52:12 +02:00
ROLLBACK;
2001-05-23 15:26:42 +02:00
END_ERROR;
START_TRANSACTION;
first_file->lls_next = files_to_delete;
files_to_delete = files;
}
}
static void drop_trigger( DUDLEY_TRG trigger)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* d r o p _ t r i g g e r
*
**************************************
*
* Functional description
* drop a trigger in rdb$triggers.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
bool others = false;
2001-05-23 15:26:42 +02:00
BASED_ON RDB$TRIGGERS.RDB$RELATION_NAME relation_name;
2004-03-07 08:58:55 +01:00
TEXT* name = trigger->trg_name->sym_string;
2001-05-23 15:26:42 +02:00
/* Clean out possible trigger messages first. */
FOR TM IN RDB$TRIGGER_MESSAGES WITH TM.RDB$TRIGGER_NAME EQ name
2003-09-10 19:52:12 +02:00
ERASE TM;
2001-05-23 15:26:42 +02:00
END_FOR;
FOR X IN RDB$TRIGGERS WITH X.RDB$TRIGGER_NAME EQ name
gds__vtov(X.RDB$RELATION_NAME, relation_name, sizeof(relation_name));
2003-09-10 19:52:12 +02:00
ERASE X;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
DDL_err(73, name, NULL, NULL, NULL, NULL); /* msg 73: Trigger %s doesn't exist */
/* clear the update flags on the fields if this is the last remaining trigger that changes a view */
FOR V IN RDB$VIEW_RELATIONS
WITH V.RDB$VIEW_NAME = relation_name
FOR F IN RDB$RELATION_FIELDS CROSS T IN RDB$TRIGGERS OVER
2003-09-10 19:52:12 +02:00
RDB$RELATION_NAME WITH
F.RDB$RELATION_NAME = V.RDB$VIEW_NAME
others = true;
END_FOR;
if (!others) {
FOR F IN RDB$RELATION_FIELDS
WITH F.RDB$RELATION_NAME = V.RDB$VIEW_NAME
MODIFY F USING
F.RDB$UPDATE_FLAG = FALSE;
END_MODIFY;
END_FOR;
}
2001-05-23 15:26:42 +02:00
END_FOR;
}
static void drop_trigger_msg( TRGMSG trigmsg)
{
/**************************************
*
* d r o p _ t r i g g e r _ m s g
*
**************************************
*
* Functional description
* Drop a trigger message.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR FIRST 1 X IN RDB$TRIGGER_MESSAGES WITH
X.RDB$TRIGGER_NAME EQ trigmsg->trgmsg_trg_name->sym_string AND
X.RDB$MESSAGE_NUMBER = trigmsg->trgmsg_number;
2003-09-10 19:52:12 +02:00
ERASE X;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
2004-03-14 06:51:54 +01:00
DDL_err(74, (TEXT *)(IPTR) trigmsg->trgmsg_number,
2001-05-23 15:26:42 +02:00
trigmsg->trgmsg_trg_name->sym_string, NULL, NULL, NULL);
/* msg 74: Trigger message number %d for trigger %s doesn't exist */
}
static void drop_type( TYP fldtype)
{
/**************************************
*
* d r o p _ t y p e
*
**************************************
*
* Functional description
* Drop a list of types or all types of an existing field.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
if (fldtype->typ_name->sym_length == 3 &&
!strncmp(fldtype->typ_name->sym_string, "ALL", 3)) {
FOR X IN RDB$TYPES WITH
X.RDB$FIELD_NAME EQ fldtype->typ_field_name->sym_string
2003-09-10 19:52:12 +02:00
ERASE X;
2001-05-23 15:26:42 +02:00
END_FOR;
return;
}
FOR X IN RDB$TYPES WITH
X.RDB$FIELD_NAME EQ fldtype->typ_field_name->sym_string AND
X.RDB$TYPE_NAME EQ fldtype->typ_name->sym_string
2003-09-10 19:52:12 +02:00
ERASE X;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
DDL_err(75,
fldtype->typ_name->sym_string,
fldtype->typ_field_name->sym_string, NULL, NULL, NULL);
/* msg 75: Type %s for field %s doesn't exist */
}
static void drop_user_privilege( USERPRIV upriv)
{
/**************************************
*
* d r o p _ u s e r _ p r i v i l e g e
*
**************************************
*
* Functional description
* Find and delete as many rdb$user_privilege entries
* as needed for the REVOKE statement.
*
**************************************/
USHORT privflag;
TEXT priv[7];
UPFE upf; /* user privilege field entry */
USRE usr; /* user entry */
/* we have one rdb$user_privileges entry per each user/privilege/field
combination so start by looping through each user in user list, then
loop for each privilege - erase_userpriv takes care of the multiple
field entries */
for (usr = upriv->userpriv_userlist; usr; usr = usr->usre_next) {
/* start with a fresh copy of privflag and erase each
privilege as we take care of it */
privflag = upriv->userpriv_flags & ~USERPRIV_grant;
while (privflag) {
upf = NULL;
if (privflag & USERPRIV_select) {
strcpy(priv, UPRIV_SELECT);
privflag ^= USERPRIV_select;
}
else if (privflag & USERPRIV_delete) {
strcpy(priv, UPRIV_DELETE);
privflag ^= USERPRIV_delete;
}
else if (privflag & USERPRIV_insert) {
strcpy(priv, UPRIV_INSERT);
privflag ^= USERPRIV_insert;
}
else if (privflag & USERPRIV_update) {
strcpy(priv, UPRIV_UPDATE);
privflag ^= USERPRIV_update;
/* no field list implies all fields */
if (!upriv->userpriv_upflist)
erase_userpriv(upriv, priv, usr, upf);
else
/* update is the only privilege with a possible field list */
for (upf = upriv->userpriv_upflist; upf;
upf =
upf->upfe_next) erase_userpriv(upriv, priv, usr,
upf);
}
/* don't call erase_userpriv if we just finished update */
if (strcmp(priv, UPRIV_UPDATE))
erase_userpriv(upriv, priv, usr, upf);
} /* while (privflag) */
} /* for */
}
static void erase_userpriv( USERPRIV upriv, TEXT * priv, USRE usr, UPFE upf)
{
/**************************************
*
* e r a s e _ u s e r p r i v
*
**************************************
*
* Functional description
* Erase a user/privilege/field combination for a REVOKE statement.
*
**************************************/
TEXT *fldname, *relname, *usrname;
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
usrname = usr->usre_name->sym_string;
relname = upriv->userpriv_relation->sym_string;
/* for UPDATE privilege the field is specified */
if (upf) {
fldname = upf->upfe_fldname->sym_string;
FOR X IN RDB$USER_PRIVILEGES WITH
X.RDB$USER EQ usrname AND
X.RDB$USER_TYPE EQ obj_user AND
X.RDB$PRIVILEGE EQ priv AND
X.RDB$FIELD_NAME EQ fldname AND
X.RDB$RELATION_NAME EQ relname AND
X.RDB$OBJECT_TYPE EQ obj_relation
2003-09-10 19:52:12 +02:00
ERASE X;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
DDL_err(76, priv, fldname, relname, usrname, NULL);
/* msg 76: User privilege %s on field %s in relation %s for user %s doesn't exist */
}
else {
FOR X IN RDB$USER_PRIVILEGES WITH
X.RDB$USER EQ usrname AND
X.RDB$USER_TYPE EQ obj_user AND
X.RDB$PRIVILEGE EQ priv AND
X.RDB$RELATION_NAME EQ relname AND
X.RDB$OBJECT_TYPE EQ obj_relation
2003-09-10 19:52:12 +02:00
ERASE X;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
DDL_err(77, priv, relname, usrname, NULL, NULL);
/* msg 77: User privilege %s on relation %s for user %s doesn't exist */
}
}
static void get_field_desc( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ f i e l d _ d e s c
*
**************************************
*
* Functional description
* Get description for existing field.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR DUDLEY_FLD IN RDB$RELATION_FIELDS CROSS SRC IN RDB$FIELDS
WITH DUDLEY_FLD.RDB$FIELD_NAME = field->fld_name->sym_string
AND DUDLEY_FLD.RDB$RELATION_NAME = field->fld_relation->rel_name->sym_string
AND DUDLEY_FLD.RDB$FIELD_SOURCE = SRC.RDB$FIELD_NAME
2001-05-23 15:26:42 +02:00
field->fld_dtype = SRC.RDB$FIELD_TYPE;
2003-09-10 19:52:12 +02:00
field->fld_length = SRC.RDB$FIELD_LENGTH;
field->fld_scale = SRC.RDB$FIELD_SCALE;
field->fld_segment_length = SRC.RDB$SEGMENT_LENGTH;
field->fld_sub_type = SRC.RDB$FIELD_SUB_TYPE;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
DDL_err(78,
field->fld_name->sym_string,
field->fld_relation->rel_name->sym_string, NULL, NULL, NULL);
/* msg 78: field %s is unknown in relation %s */
}
static void get_global_fields(void)
{
/**************************************
*
* g e t _ g l o b a l _ f i e l d s
*
**************************************
*
* Functional description
* Get global fields for database.
*
**************************************/
2004-03-07 08:58:55 +01:00
FOR X IN RDB$FIELDS
DUDLEY_FLD field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
SYM symbol = get_symbol(SYM_global, X.RDB$FIELD_NAME, (DUDLEY_CTX) field);
field->fld_name = symbol;
2003-09-10 19:52:12 +02:00
HSH_insert(symbol);
field->fld_dtype = X.RDB$FIELD_TYPE;
field->fld_length = X.RDB$FIELD_LENGTH;
field->fld_scale = X.RDB$FIELD_SCALE;
field->fld_segment_length = X.RDB$SEGMENT_LENGTH;
field->fld_sub_type = X.RDB$FIELD_SUB_TYPE;
END_FOR;
2001-05-23 15:26:42 +02:00
}
2004-05-12 21:39:17 +02:00
static void get_relations( DBB databaseL)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ r e l a t i o n s
*
**************************************
*
* Functional description
* Get information on existing relations
* and their fields.
*
**************************************/
DUDLEY_REL relation;
DUDLEY_FLD field;
2001-05-23 15:26:42 +02:00
SYM symbol;
FOR R IN RDB$RELATIONS
2003-09-30 12:39:11 +02:00
relation = (DUDLEY_REL) DDL_alloc(sizeof(dudley_rel));
2003-09-10 19:52:12 +02:00
relation->rel_name = symbol =
get_symbol(SYM_relation, R.RDB$RELATION_NAME, (DUDLEY_CTX) relation);
HSH_insert(symbol);
2004-05-12 21:39:17 +02:00
relation->rel_database = databaseL;
relation->rel_next = dudleyGlob.database->dbb_relations;
dudleyGlob.database->dbb_relations = relation;
2003-09-10 19:52:12 +02:00
relation->rel_system = R.RDB$SYSTEM_FLAG;
FOR RFR IN RDB$RELATION_FIELDS WITH
RFR.RDB$RELATION_NAME = R.RDB$RELATION_NAME
2003-09-30 12:39:11 +02:00
field = (DUDLEY_FLD) DDL_alloc(sizeof(dudley_fld));
2003-09-10 19:52:12 +02:00
field->fld_name = get_symbol(SYM_field, RFR.RDB$FIELD_NAME, (DUDLEY_CTX) field);
HSH_insert(field->fld_name);
field->fld_relation = relation;
field->fld_next = relation->rel_fields;
relation->rel_fields = field;
field->fld_position = RFR.RDB$FIELD_POSITION;
relation->rel_field_position =
MAX(RFR.RDB$FIELD_POSITION, relation->rel_field_position);
field->fld_source =
HSH_typed_lookup(RFR.RDB$FIELD_SOURCE, (USHORT) 0, SYM_global);
END_FOR;
END_FOR;
2001-05-23 15:26:42 +02:00
}
static USHORT get_prot_mask( TEXT * relation, TEXT * field)
{
/**************************************
*
* g e t _ p r o t _ m a s k
*
**************************************
*
* Functional description
* returns the protection mask for a relation
* or field (if the field is an empty string it
* gets the mask for the relation).
*
**************************************/
static const SCHAR blr[] = {
2001-05-23 15:26:42 +02:00
blr_version4,
blr_begin,
blr_message, 1, 1, 0,
blr_short, 0,
blr_message, 0, 2, 0,
blr_cstring, 32, 0,
blr_cstring, 32, 0,
blr_receive, 0,
blr_begin,
blr_send, 1,
blr_begin,
blr_assignment,
blr_prot_mask,
blr_parameter, 0, 0, 0,
blr_parameter, 0, 1, 0,
blr_parameter, 1, 0, 0,
blr_end,
blr_end,
blr_end,
blr_eoc
};
2004-05-03 01:06:37 +02:00
static FB_API_HANDLE req_handle;
2001-05-23 15:26:42 +02:00
struct {
SCHAR relation_name[32];
SCHAR field_name[32];
} msg;
struct {
SSHORT prot_mask;
} output;
strcpy(msg.relation_name, relation);
if (field)
strcpy(msg.field_name, field);
else
strcpy(msg.field_name, "");
if (!req_handle)
isc_compile_request2(NULL, &DB, &req_handle, sizeof(blr), blr);
isc_start_request(NULL, &req_handle, &gds_trans, 0);
isc_start_and_send(NULL, &req_handle, &gds_trans, 0, sizeof(msg), &msg, 0);
isc_receive(NULL, &req_handle, 1, sizeof(output), &output, 0);
2001-05-23 15:26:42 +02:00
return output.prot_mask;
}
static SYM get_symbol( enum sym_t type, TEXT * string, DUDLEY_CTX object)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ s y m b o l
*
**************************************
*
* Functional description
* Allocate and format symbol block for null or blank terminated string.
*
**************************************/
TEXT *p;
USHORT l;
SYM symbol;
for (p = string; *p && *p != ' '; p++);
l = p - string;
symbol = (SYM) DDL_alloc(SYM_LEN + l);
symbol->sym_object = object;
symbol->sym_type = type;
symbol->sym_string = p = symbol->sym_name;
if (symbol->sym_length = l)
2004-03-07 08:58:55 +01:00
do {
2001-05-23 15:26:42 +02:00
*p++ = *string++;
2004-03-07 08:58:55 +01:00
} while (--l);
2001-05-23 15:26:42 +02:00
return symbol;
}
2004-05-12 21:39:17 +02:00
static void get_triggers( DBB databaseL)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ t r i g g e r s
*
**************************************
*
* Functional description
* Get information on existing relations
* and their fields.
*
**************************************/
DUDLEY_TRG trigger;
2001-05-23 15:26:42 +02:00
SYM symbol, rel_name;
FOR T IN RDB$TRIGGERS WITH T.RDB$SYSTEM_FLAG MISSING OR
2003-09-10 19:52:12 +02:00
T.RDB$SYSTEM_FLAG = 0
2003-09-30 12:39:11 +02:00
trigger = (DUDLEY_TRG) DDL_alloc(sizeof(dudley_trg));
2003-09-10 19:52:12 +02:00
trigger->trg_name = symbol =
get_symbol(SYM_trigger, T.RDB$TRIGGER_NAME, (DUDLEY_CTX) trigger);
HSH_insert(symbol);
rel_name =
HSH_typed_lookup(T.RDB$RELATION_NAME, (USHORT) 0, SYM_relation);
if (rel_name && rel_name->sym_object)
trigger->trg_relation = (DUDLEY_REL) rel_name->sym_object;
else
trigger->trg_relation =
(DUDLEY_REL) get_symbol(SYM_relation, T.RDB$RELATION_NAME, NULL);
trigger->trg_type = (TRG_T) T.RDB$TRIGGER_TYPE;
trigger->trg_inactive = T.RDB$TRIGGER_INACTIVE;
trigger->trg_sequence = T.RDB$TRIGGER_SEQUENCE;
2001-05-23 15:26:42 +02:00
END_FOR;
}
static void get_udfs( DBB dbb)
{
/**************************************
*
* g e t _ u d f s
*
**************************************
*
* Functional description
* Pickup any user defined functions.
*
**************************************/
FOR FUN IN RDB$FUNCTIONS CROSS ARG IN RDB$FUNCTION_ARGUMENTS WITH
FUN.RDB$FUNCTION_NAME EQ ARG.RDB$FUNCTION_NAME AND
FUN.RDB$RETURN_ARGUMENT EQ ARG.RDB$ARGUMENT_POSITION
2004-03-07 08:58:55 +01:00
FUNC function = (FUNC) DDL_alloc(sizeof(func));
2003-09-10 19:52:12 +02:00
function->func_database = dbb;
2004-03-07 08:58:55 +01:00
SYM symbol =
2003-09-10 19:52:12 +02:00
get_symbol(SYM_function, FUN.RDB$FUNCTION_NAME, (DUDLEY_CTX) function);
2004-03-07 08:58:55 +01:00
function->func_name = symbol;
2003-09-10 19:52:12 +02:00
HSH_insert(symbol);
2004-03-07 08:58:55 +01:00
FUNCARG arg = (FUNCARG) DDL_alloc(sizeof(funcarg));
function->func_return = arg;
2003-09-10 19:52:12 +02:00
arg->funcarg_dtype = ARG.RDB$FIELD_TYPE;
arg->funcarg_scale = ARG.RDB$FIELD_SCALE;
arg->funcarg_length = ARG.RDB$FIELD_LENGTH;
arg->funcarg_sub_type = ARG.RDB$FIELD_SUB_TYPE;
arg->funcarg_has_sub_type = !(ARG.RDB$FIELD_SUB_TYPE.NULL);
END_FOR
ON_ERROR
END_ERROR;
2001-05-23 15:26:42 +02:00
}
static void make_desc( DUDLEY_NOD node, DSC * desc)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m a k e _ d e s c
*
**************************************
*
* Functional description
* Invent a descriptor based on expression tree.
*
**************************************/
DUDLEY_FLD field;
2001-05-23 15:26:42 +02:00
DSC desc1, desc2;
CON constant;
FUNC function;
USHORT dtype;
FUNCARG arg;
switch (node->nod_type) {
case nod_max:
case nod_min:
case nod_from:
make_desc(node->nod_arg[s_stt_value], desc);
return;
case nod_total:
make_desc(node->nod_arg[s_stt_value], &desc1);
dtype = make_dtype(desc1.dsc_dtype);
switch (dtype) {
case dtype_short:
case dtype_long:
desc->dsc_dtype = blr_long;
desc->dsc_length = sizeof(SLONG);
desc->dsc_scale = desc1.dsc_scale;
desc->dsc_sub_type = 0;
return;
case dtype_timestamp:
case dtype_sql_date:
case dtype_sql_time:
2003-08-30 04:02:36 +02:00
DDL_msg_put(80, NULL, NULL, NULL, NULL, NULL);
/* msg 80: TOTAL of date not supported */
2001-05-23 15:26:42 +02:00
return;
default:
desc->dsc_dtype = blr_double;
desc->dsc_length = sizeof(double);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
return;
}
break;
case nod_average:
case nod_divide:
desc->dsc_dtype = blr_double;
desc->dsc_length = sizeof(double);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
return;
case nod_count:
desc->dsc_dtype = blr_long;
desc->dsc_length = sizeof(SLONG);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
return;
case nod_add:
case nod_subtract:
make_desc(node->nod_arg[0], &desc1);
make_desc(node->nod_arg[1], &desc2);
dtype = MAX(make_dtype(desc1.dsc_dtype), make_dtype(desc2.dsc_dtype));
switch (dtype) {
case dtype_short:
case dtype_long:
desc->dsc_dtype = blr_long;
desc->dsc_length = sizeof(SLONG);
desc->dsc_scale = MIN(C_NUMERIC_SCALE(desc1),
C_NUMERIC_SCALE(desc2));
2001-05-23 15:26:42 +02:00
desc->dsc_sub_type = 0;
return;
case dtype_timestamp:
if (node->nod_type == nod_add) {
desc->dsc_dtype = blr_timestamp;
desc->dsc_length = 8;
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
return;
}
break;
case dtype_sql_date:
if (node->nod_type == nod_add) {
desc->dsc_dtype = blr_sql_date;
desc->dsc_length = 4;
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
return;
}
break;
case dtype_sql_time:
if (node->nod_type == nod_add) {
desc->dsc_dtype = blr_sql_time;
desc->dsc_length = 4;
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
return;
}
break;
}
desc->dsc_dtype = blr_double;
desc->dsc_length = sizeof(double);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
return;
case nod_multiply:
make_desc(node->nod_arg[0], &desc1);
make_desc(node->nod_arg[1], &desc2);
dtype = MAX(make_dtype(desc1.dsc_dtype), make_dtype(desc2.dsc_dtype));
if (dtype == dtype_short || dtype == dtype_long) {
desc->dsc_dtype = blr_long;
desc->dsc_length = sizeof(SLONG);
desc->dsc_sub_type = 0;
desc->dsc_scale = C_NUMERIC_SCALE(desc1) +
C_NUMERIC_SCALE(desc2);
2001-05-23 15:26:42 +02:00
return;
}
desc->dsc_dtype = blr_double;
desc->dsc_length = sizeof(double);
desc->dsc_sub_type = 0;
desc->dsc_scale = 0;
return;
case nod_concatenate:
make_desc(node->nod_arg[0], &desc1);
make_desc(node->nod_arg[1], &desc2);
desc->dsc_dtype = blr_varying;
desc->dsc_sub_type = 0;
desc->dsc_scale = 0;
dtype = make_dtype(desc1.dsc_dtype);
if (dtype > dtype_any_text) {
desc1.dsc_length = string_length(dtype);
desc->dsc_ttype() = ttype_ascii;
2001-05-23 15:26:42 +02:00
}
else
desc->dsc_ttype() = desc1.dsc_ttype();
2001-05-23 15:26:42 +02:00
dtype = make_dtype(desc2.dsc_dtype);
if (dtype > dtype_any_text)
desc2.dsc_length = string_length(dtype);
desc->dsc_length = desc1.dsc_length + desc2.dsc_length;
return;
case nod_field:
field = (DUDLEY_FLD) node->nod_arg[s_fld_field];
2001-05-23 15:26:42 +02:00
if (!field->fld_dtype)
get_field_desc(field);
desc->dsc_dtype = field->fld_dtype;
desc->dsc_length = field->fld_length;
desc->dsc_scale = field->fld_scale;
desc->dsc_sub_type = 0;
if (DTYPE_IS_TEXT(make_dtype(desc->dsc_dtype)))
desc->dsc_ttype() = field->fld_sub_type;
2001-05-23 15:26:42 +02:00
return;
case nod_literal:
constant = (CON) node->nod_arg[0];
desc->dsc_length = constant->con_desc.dsc_length;
desc->dsc_scale = constant->con_desc.dsc_scale;
desc->dsc_sub_type = 0;
/* Note: GDEF doesn't have any knowledge of alternate character
sets (GDML is frozen) - so literal constants appearing
in GDEF must be ttype_ascii. Note they are not ttype_dynamic
as we are defining data objects, which cannot be "typed"
at runtime
*/
dtype = constant->con_desc.dsc_dtype;
switch (dtype) {
case dtype_short:
desc->dsc_dtype = blr_short;
break;
case dtype_long:
desc->dsc_dtype = blr_long;
break;
case dtype_quad:
desc->dsc_dtype = blr_quad;
break;
case dtype_real:
desc->dsc_dtype = blr_float;
break;
case dtype_double:
desc->dsc_dtype = blr_double;
break;
case dtype_text:
desc->dsc_dtype = blr_text;
desc->dsc_sub_type = ttype_ascii;
break;
case dtype_varying:
desc->dsc_dtype = blr_varying;
desc->dsc_sub_type = ttype_ascii;
break;
case dtype_cstring:
desc->dsc_dtype = blr_cstring;
desc->dsc_sub_type = ttype_ascii;
break;
case dtype_timestamp:
desc->dsc_dtype = blr_timestamp;
break;
case dtype_sql_date:
desc->dsc_dtype = blr_sql_date;
break;
case dtype_sql_time:
desc->dsc_dtype = blr_sql_time;
break;
case dtype_int64:
desc->dsc_dtype = blr_int64;
break;
case dtype_blob:
2002-04-04 07:36:37 +02:00
desc->dsc_dtype = (UCHAR) blr_blob;
2001-05-23 15:26:42 +02:00
break;
default:
desc->dsc_dtype = blr_double;
break;
}
return;
case nod_function:
function = (FUNC) node->nod_arg[2];
arg = function->func_return;
desc->dsc_dtype = arg->funcarg_dtype;
desc->dsc_length = arg->funcarg_length;
desc->dsc_scale = arg->funcarg_scale;
desc->dsc_sub_type = 0;
if (DTYPE_IS_TEXT(make_dtype(desc->dsc_dtype)))
desc->dsc_ttype() = arg->funcarg_sub_type;
2001-05-23 15:26:42 +02:00
return;
case nod_fid:
2003-08-30 04:02:36 +02:00
DDL_err(287, NULL, NULL, NULL, NULL, NULL);
/* msg 287: Inappropriate self reference */
2001-05-23 15:26:42 +02:00
return;
default:
2003-08-30 04:02:36 +02:00
DDL_err(81, NULL, NULL, NULL, NULL, NULL);
/* msg 81: (EXE) make_desc: don't understand node type */
2001-05-23 15:26:42 +02:00
return;
}
}
static int make_dtype( USHORT blr_type)
{
/**************************************
*
* m a k e _ d t y p e
*
**************************************
*
* Functional description
* Translate from blr to internal data types.
*
**************************************/
switch (blr_type) {
case blr_short:
return dtype_short;
case blr_long:
return dtype_long;
case blr_quad:
return dtype_quad;
case blr_float:
return dtype_real;
case blr_double:
return dtype_double;
case blr_text:
return dtype_text;
case blr_cstring:
return dtype_cstring;
case blr_varying:
return dtype_varying;
case blr_timestamp:
return dtype_timestamp;
case blr_sql_date:
return dtype_sql_date;
case blr_sql_time:
return dtype_sql_time;
case blr_int64:
return dtype_int64;
}
if (blr_type == blr_blob)
return dtype_blob;
return dtype_double;
}
static void modify_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m o d i f y _ f i e l d
*
**************************************
*
* Functional description
* Change attributes of a local field.
* The first group of attributes are ones
* that should never be false. The second
* set also manipulate the missing flag so
* if they came in null and weren't changed
* they'll still be null
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
DUDLEY_REL relation;
2001-05-23 15:26:42 +02:00
relation = field->fld_relation;
2004-03-07 08:58:55 +01:00
SYM name = field->fld_name;
2001-05-23 15:26:42 +02:00
FOR FIRST 1 X IN RDB$RELATION_FIELDS WITH
2003-09-10 19:52:12 +02:00
X.RDB$FIELD_NAME EQ name->sym_string AND
X.RDB$RELATION_NAME EQ relation->rel_name->sym_string
MODIFY X USING
if (field->fld_flags & fld_null_description)
X.RDB$DESCRIPTION.NULL = TRUE;
if (field->fld_flags & fld_null_security_class)
X.RDB$SECURITY_CLASS.NULL = TRUE;
if (field->fld_flags & fld_null_edit_string)
X.RDB$EDIT_STRING.NULL = TRUE;
if (field->fld_flags & fld_null_query_name)
X.RDB$QUERY_NAME.NULL = TRUE;
if (field->fld_flags & fld_null_query_header)
X.RDB$QUERY_HEADER.NULL = TRUE;
if (field->fld_flags & fld_explicit_system)
X.RDB$SYSTEM_FLAG = field->fld_system;
if (field->fld_source)
MOVE_SYMBOL(field->fld_source, X.RDB$FIELD_SOURCE);
if (field->fld_security_class) {
MOVE_SYMBOL(field->fld_security_class, X.RDB$SECURITY_CLASS);
X.RDB$SECURITY_CLASS.NULL = FALSE;
}
if ((field->fld_flags & fld_explicit_position) || field->fld_position) {
X.RDB$FIELD_POSITION = field->fld_position;
X.RDB$FIELD_POSITION.NULL = FALSE;
}
if (field->fld_description) {
store_text(field->fld_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
if (field->fld_query_name) {
MOVE_SYMBOL(field->fld_query_name, X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
}
if (field->fld_edit_string) {
MOVE_SYMBOL(field->fld_edit_string, X.RDB$EDIT_STRING);
X.RDB$EDIT_STRING.NULL = FALSE;
}
if (field->fld_query_header) {
store_query_header(field->fld_query_header, &X.RDB$QUERY_HEADER);
2003-09-10 19:52:12 +02:00
X.RDB$QUERY_HEADER.NULL = FALSE;
}
END_MODIFY
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR
2003-09-10 19:52:12 +02:00
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(82, name->sym_string, NULL, NULL, NULL, NULL);
/* msg 82: field %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void modify_global_field( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m o d i f y _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
* Change attributes of a global field.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
SYM name = field->fld_name;
2001-05-23 15:26:42 +02:00
FOR FIRST 1 X IN RDB$FIELDS WITH X.RDB$FIELD_NAME EQ name->sym_string
MODIFY X USING
2003-09-10 19:52:12 +02:00
if (field->fld_dtype) {
if ((X.RDB$FIELD_TYPE != blr_blob) && (field->fld_dtype != blr_blob)) {
if ((check_range(field))) {
X.RDB$FIELD_TYPE = (int) field->fld_dtype;
X.RDB$FIELD_LENGTH = field->fld_length;
X.RDB$FIELD_SCALE = field->fld_scale;
}
}
else if (field->fld_dtype != X.RDB$FIELD_TYPE)
DDL_err(83, name->sym_name, NULL, NULL, NULL, NULL);
/* msg 83: Unauthorized attempt to change field %s to or from blob */
}
if (field->fld_flags & fld_explicit_system)
X.RDB$SYSTEM_FLAG = field->fld_system;
if (field->fld_flags & fld_null_description)
X.RDB$DESCRIPTION.NULL = TRUE;
if (field->fld_flags & fld_null_missing_value)
X.RDB$MISSING_VALUE.NULL = TRUE;
if (field->fld_flags & fld_null_query_name)
X.RDB$QUERY_NAME.NULL = TRUE;
if (field->fld_flags & fld_null_query_header)
X.RDB$QUERY_HEADER.NULL = TRUE;
if (field->fld_flags & fld_null_edit_string)
X.RDB$EDIT_STRING.NULL = TRUE;
if (field->fld_flags & fld_null_validation) {
X.RDB$VALIDATION_BLR.NULL = TRUE;
X.RDB$VALIDATION_SOURCE.NULL = TRUE;
}
if (field->fld_segment_length) {
X.RDB$SEGMENT_LENGTH = field->fld_segment_length;
X.RDB$SEGMENT_LENGTH.NULL = FALSE;
}
if (field->fld_has_sub_type) {
X.RDB$FIELD_SUB_TYPE = field->fld_sub_type;
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
}
if (field->fld_missing) {
store_blr(field->fld_missing, &X.RDB$MISSING_VALUE, NULL);
2003-09-10 19:52:12 +02:00
X.RDB$MISSING_VALUE.NULL = FALSE;
}
if (field->fld_validation) {
store_blr(field->fld_validation, &X.RDB$VALIDATION_BLR, NULL);
store_text(field->fld_valid_src, &X.RDB$VALIDATION_SOURCE);
2003-09-10 19:52:12 +02:00
X.RDB$VALIDATION_BLR.NULL = FALSE;
X.RDB$VALIDATION_SOURCE.NULL = FALSE;
}
if (field->fld_description) {
store_text(field->fld_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
if (field->fld_query_name) {
MOVE_SYMBOL(field->fld_query_name, X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
}
if (field->fld_edit_string) {
MOVE_SYMBOL(field->fld_edit_string, X.RDB$EDIT_STRING);
X.RDB$EDIT_STRING.NULL = FALSE;
}
if (field->fld_query_header) {
store_query_header(field->fld_query_header, &X.RDB$QUERY_HEADER);
2003-09-10 19:52:12 +02:00
X.RDB$QUERY_HEADER.NULL = FALSE;
}
END_MODIFY
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR
2003-09-10 19:52:12 +02:00
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(84, name->sym_string, NULL, NULL, NULL, NULL);
/* msg 84: field %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void modify_index( DUDLEY_IDX index)
{
/**************************************
*
* m o d i f y _ i n d e x
*
**************************************
*
* Functional description
* Modify an index.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$INDICES WITH X.RDB$INDEX_NAME = index->idx_name->sym_string
MODIFY X USING
2003-09-10 19:52:12 +02:00
if (index->idx_flags & IDX_active_flag) {
X.RDB$INDEX_INACTIVE = (index->idx_inactive) ? TRUE : FALSE;
if (index->idx_flags & IDX_unique_flag)
X.RDB$UNIQUE_FLAG = (index->idx_unique) ? TRUE : FALSE;
2003-09-15 04:15:27 +02:00
if (index->idx_flags & IDX_type_flag) {
2003-09-12 18:32:19 +02:00
X.RDB$INDEX_TYPE = index->idx_type;
2003-09-10 19:52:12 +02:00
X.RDB$INDEX_TYPE.NULL = FALSE;
}
if (index->idx_flags & IDX_null_description)
X.RDB$DESCRIPTION.NULL = TRUE;
if (index->idx_description) {
store_text(index->idx_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
if (index->idx_flags & IDX_statistics_flag)
X.RDB$STATISTICS = -1.0;
}
END_MODIFY;
if_any = true;
END_FOR;
2001-05-23 15:26:42 +02:00
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(85, index->idx_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 85: index %s does not exist */
2001-05-23 15:26:42 +02:00
}
static void modify_relation( DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m o d i f y _ r e l a t i o n
*
**************************************
*
* Functional description
* Change the volitile attributes of a relation -
* to wit, the description, security class, and
* system flag.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
if (!(relation->rel_flags & rel_marked_for_modify)) {
2001-05-23 15:26:42 +02:00
return;
}
2004-03-07 08:58:55 +01:00
SYM name = relation->rel_name;
2001-05-23 15:26:42 +02:00
FOR FIRST 1 X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ name->sym_string
2003-09-10 19:52:12 +02:00
MODIFY X USING
if (relation->rel_flags & rel_null_security_class)
X.RDB$SECURITY_CLASS.NULL = TRUE;
if (relation->rel_security_class) {
MOVE_SYMBOL(relation->rel_security_class, X.RDB$SECURITY_CLASS);
X.RDB$SECURITY_CLASS.NULL = FALSE;
}
if (relation->rel_flags & rel_null_description)
X.RDB$DESCRIPTION.NULL = TRUE;
if (relation->rel_description) {
store_text(relation->rel_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
X.RDB$DESCRIPTION.NULL = FALSE;
}
if (relation->rel_flags & rel_explicit_system)
X.RDB$SYSTEM_FLAG = relation->rel_system;
if (relation->rel_filename) {
if (X.RDB$EXTERNAL_FILE.NULL)
DDL_err(86, name->sym_string, NULL, NULL, NULL, NULL);
2003-08-30 04:02:36 +02:00
/* msg 86: relation %s is not external */
2003-09-10 19:52:12 +02:00
MOVE_SYMBOL(relation->rel_filename, X.RDB$EXTERNAL_FILE);
}
END_MODIFY
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR
2003-09-10 19:52:12 +02:00
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(87, name->sym_string, NULL, NULL, NULL, NULL);
/* msg 87: relation %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void modify_trigger( DUDLEY_TRG trigger)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m o d i f y _ t r i g g e r
*
**************************************
*
* Functional description
* modify a trigger in rdb$triggers.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
DUDLEY_REL relation;
2001-05-23 15:26:42 +02:00
TEXT buffer[32], *p, *q;
FOR FIRST 1 X IN RDB$TRIGGERS WITH
X.RDB$TRIGGER_NAME EQ trigger->trg_name->sym_string
MODIFY X USING
2003-09-10 19:52:12 +02:00
if (relation = trigger->trg_relation) {
for (p = buffer, q = X.RDB$RELATION_NAME; *q && *q != ' ';)
*p++ = *q++;
*p = 0;
if (strcmp(relation->rel_name->sym_string, buffer))
DDL_err(88, trigger->trg_name->sym_string, NULL, NULL, NULL,
NULL);
/* msg 88: Invalid attempt to assign trigger %s to a new relation */
}
if (trigger->trg_mflag & trg_mflag_onoff)
X.RDB$TRIGGER_INACTIVE = trigger->trg_inactive;
if (trigger->trg_mflag & trg_mflag_type)
X.RDB$TRIGGER_TYPE = (SSHORT) trigger->trg_type;
if (trigger->trg_mflag & trg_mflag_seqnum)
X.RDB$TRIGGER_SEQUENCE = trigger->trg_sequence;
if (trigger->trg_source) {
X.RDB$TRIGGER_SOURCE.NULL = FALSE;
store_text(trigger->trg_source, &X.RDB$TRIGGER_SOURCE);
2003-09-10 19:52:12 +02:00
}
if (trigger->trg_statement) {
X.RDB$TRIGGER_BLR.NULL = FALSE;
store_blr(trigger->trg_statement, &X.RDB$TRIGGER_BLR, NULL);
2003-09-10 19:52:12 +02:00
}
if (trigger->trg_description) {
X.RDB$DESCRIPTION.NULL = FALSE;
store_text(trigger->trg_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
}
END_MODIFY;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
2003-08-30 04:02:36 +02:00
DDL_err(89, trigger->trg_name->sym_string, NULL, NULL, NULL, NULL);
/* msg 89: Trigger %s doesn't exist */
2001-05-23 15:26:42 +02:00
}
static void modify_trigger_msg( TRGMSG trigmsg)
{
/**************************************
*
* m o d i f y _ t r i g g e r _ m s g
*
**************************************
*
* Functional description
* Modify a trigger message.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR FIRST 1 X IN RDB$TRIGGER_MESSAGES WITH
X.RDB$TRIGGER_NAME EQ trigmsg->trgmsg_trg_name->sym_string AND
X.RDB$MESSAGE_NUMBER = trigmsg->trgmsg_number;
2003-09-10 19:52:12 +02:00
MODIFY X USING
MOVE_SYMBOL(trigmsg->trgmsg_text, X.RDB$MESSAGE);
END_MODIFY;
if_any = true;
2001-05-23 15:26:42 +02:00
END_FOR;
if (!if_any)
add_trigger_msg(trigmsg);
}
static void modify_type( TYP fldtype)
{
/**************************************
*
* m o d i f y _ t y p e
*
**************************************
*
* Functional description
* Modify type value or description of a type for a field.
*
**************************************/
2003-09-10 19:52:12 +02:00
bool if_any = false;
2001-05-23 15:26:42 +02:00
FOR FIRST 1 X IN RDB$TYPES WITH
X.RDB$FIELD_NAME EQ fldtype->typ_field_name->sym_string AND
X.RDB$TYPE_NAME EQ fldtype->typ_name->sym_string;
2003-09-10 19:52:12 +02:00
MODIFY X USING
X.RDB$TYPE = fldtype->typ_type;
if (fldtype->typ_description) {
X.RDB$DESCRIPTION.NULL = FALSE;
store_text(fldtype->typ_description, &X.RDB$DESCRIPTION);
2003-09-10 19:52:12 +02:00
}
END_MODIFY;
if_any = true;
END_FOR;
2001-05-23 15:26:42 +02:00
if (!if_any)
DDL_err(90, fldtype->typ_name->sym_string,
fldtype->typ_field_name->sym_string, NULL, NULL, NULL);
/* msg 90: Type %s for field %s doesn't exist */
}
static void move_symbol( SYM symbol, SCHAR * field, SSHORT length)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m o v e _ s y m b o l
*
**************************************
*
* Functional description
* Move a string from a symbol to a field.
*
**************************************/
SCHAR *p;
SSHORT l;
2001-05-23 15:26:42 +02:00
if (symbol) {
if ((l = symbol->sym_length) > length) {
2004-03-14 06:51:54 +01:00
DDL_err(296, symbol->sym_string, (TEXT *)(IPTR) length, NULL, NULL,
2001-05-23 15:26:42 +02:00
NULL);
/*msg 296: symbol %s is too long, truncating it to %ld characters */
dudleyGlob.DDL_errors--;
2001-05-23 15:26:42 +02:00
l = length;
}
p = symbol->sym_string;
while (l--)
*field++ = *p++;
}
*field = 0;
}
static void set_generator( DUDLEY_NOD node)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s e t _ g e n e r a t o r
*
**************************************
*
* Functional description
* if the user has write privs for
* rdb$generators, get current value,
* figure out the difference, and use
* that as the increment for set. give
* it half a dozen tries in case someone
* else is interfering.
*
**************************************/
2004-05-03 01:06:37 +02:00
FB_API_HANDLE req_handle1, req_handle2;
2001-05-23 15:26:42 +02:00
USHORT prot_mask, i;
SLONG *number;
SLONG new_val;
2001-05-23 15:26:42 +02:00
SSHORT l;
2003-09-30 12:39:11 +02:00
str current_blr, new_blr;
UCHAR *blr;
2001-05-23 15:26:42 +02:00
SLONG gen_value;
CON constant;
prot_mask = get_prot_mask("RDB$GENERATORS", NULL);
if (!(prot_mask & SCL_write)) {
2003-08-30 04:02:36 +02:00
DDL_err(311, NULL, NULL, NULL, NULL, NULL);
/* msg 311: Set generator requires write privilege for RDB$GENERATORS. */
2001-05-23 15:26:42 +02:00
return;
}
/* set up node to get the current value of the generator */
constant = (CON) node->nod_arg[0]->nod_arg[0];
number = (SLONG *) constant->con_data;
new_val = *number;
2001-05-23 15:26:42 +02:00
*number = 0;
current_blr.str_current = current_blr.str_start =
reinterpret_cast<UCHAR *>(gds__alloc(1028));
if (!current_blr.str_current) {
DDL_error_abort(NULL, 14, 0, 0, 0, 0, 0); /* msg 14: memory exhausted */
}
2001-05-23 15:26:42 +02:00
current_blr.str_length = 1028;
#ifdef DEBUG_GDS_ALLOC
/* For V4.0 we don't care about Gdef specific memory leaks */
gds_alloc_flag_unfreed(current_blr.str_start);
#endif
GENERATE_blr(&current_blr, node);
l = current_blr.str_current - current_blr.str_start;
req_handle1 = 0;
blr = current_blr.str_start;
isc_compile_request2(NULL, &DB, &req_handle1, l,
reinterpret_cast<const SCHAR*>(blr));
isc_start_request(NULL, &req_handle1, &gds_trans, 0);
isc_receive(NULL, &req_handle1, 0, sizeof(gen_value), &gen_value, 0);
isc_release_request(NULL, &req_handle1);
2001-05-23 15:26:42 +02:00
/* the difference between output.current and new is the amount we
want to change the generator by */
*number = new_val - gen_value;
2001-05-23 15:26:42 +02:00
new_blr.str_current = new_blr.str_start =
reinterpret_cast<UCHAR*>(gds__alloc(1028));
if (!new_blr.str_current) {
DDL_error_abort(NULL, 14, 0, 0, 0, 0, 0); /* msg 14: memory exhausted */
}
2001-05-23 15:26:42 +02:00
new_blr.str_length = 1028;
#ifdef DEBUG_GDS_ALLOC
/* For V4.0 we don't care about Gdef specific memory leaks */
gds_alloc_flag_unfreed(new_blr.str_start);
#endif
GENERATE_blr(&new_blr, node);
l = new_blr.str_current - new_blr.str_start;
req_handle2 = 0;
blr = new_blr.str_start;
isc_compile_request2(NULL, &DB, &req_handle2, l,
reinterpret_cast<const SCHAR*>(blr));
isc_start_request(NULL, &req_handle2, &gds_trans, 0);
isc_receive(NULL, &req_handle2, 0, sizeof(gen_value), &gen_value, 0);
isc_release_request(NULL, &req_handle2);
2001-05-23 15:26:42 +02:00
for (i = 5; (gen_value != new_val) && --i;) {
*number = new_val - gen_value;
2001-05-23 15:26:42 +02:00
new_blr.str_current = new_blr.str_start;
new_blr.str_length = 1028;
GENERATE_blr(&new_blr, node);
l = new_blr.str_current - new_blr.str_start;
req_handle2 = 0;
blr = new_blr.str_start;
isc_compile_request2(NULL, &DB, &req_handle2, l,
reinterpret_cast<const SCHAR*>(blr));
isc_start_request(NULL, &req_handle2, &gds_trans, 0);
isc_receive(NULL, &req_handle2, 0, sizeof(gen_value), &gen_value, 0);
isc_release_request(NULL, &req_handle2);
2001-05-23 15:26:42 +02:00
}
gds__free(current_blr.str_start);
gds__free(new_blr.str_start);
}
static void store_acl( SCL scl_class, ISC_QUAD* blob_id)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s t o r e _ a c l
*
**************************************
*
* Functional description
* Generate and store an access control list.
*
**************************************/
TEXT buffer[4096];
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
/* Generate access control list */
2004-03-07 08:58:55 +01:00
const USHORT length = GENERATE_acl(scl_class, (UCHAR*) buffer);
2001-05-23 15:26:42 +02:00
2004-05-03 01:06:37 +02:00
FB_API_HANDLE blob = create_blob(blob_id, 0, NULL);
2001-05-23 15:26:42 +02:00
2003-11-08 00:27:24 +01:00
if (isc_put_segment(status_vector, &blob, length, buffer)) {
2003-08-30 04:02:36 +02:00
DDL_db_error(status_vector, 92, NULL, NULL, NULL, NULL, NULL);
2003-11-08 00:27:24 +01:00
/* msg 92: isc_put_segment failed */
2001-05-23 15:26:42 +02:00
return;
}
close_blob(blob);
}
static void store_blr( DUDLEY_NOD node, ISC_QUAD* blob_id, DUDLEY_REL relation)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s t o r e _ b l r
*
**************************************
*
* Functional description
* Generate blr for an expression and store result in
* a blob.
*
**************************************/
2003-09-30 12:39:11 +02:00
str blr;
USHORT length;
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2004-05-03 01:06:37 +02:00
FB_API_HANDLE handle;
2001-05-23 15:26:42 +02:00
blr.str_current = blr.str_start =
reinterpret_cast<UCHAR*>(gds__alloc(4096));
if (!blr.str_current)
DDL_error_abort(NULL, 14, 0, 0, 0, 0, 0); /* msg 14: memory exhausted */
2001-05-23 15:26:42 +02:00
blr.str_length = 4096;
#ifdef DEBUG_GDS_ALLOC
/* For V4.0 we don't care about Gdef specific memory leaks */
gds_alloc_flag_unfreed(blr.str_start);
#endif
GENERATE_blr(&blr, node);
#ifdef DEBUG
2003-12-22 11:00:59 +01:00
gds__print_blr((const UCHAR*)blr.str_start, 0, 0, 0);
2001-05-23 15:26:42 +02:00
#endif
handle = create_blob(blob_id, 0, NULL);
2001-05-23 15:26:42 +02:00
length = blr.str_current - blr.str_start;
2003-11-08 00:27:24 +01:00
if (isc_put_segment(status_vector, &handle, length,
reinterpret_cast<const SCHAR*>(blr.str_start)))
{
2003-08-30 04:02:36 +02:00
DDL_db_error(status_vector, 93, NULL, NULL, NULL, NULL, NULL);
2003-11-08 00:27:24 +01:00
/* msg 93: isc_put_segment failed */
2001-05-23 15:26:42 +02:00
return;
}
close_blob(handle);
}
static void store_query_header( DUDLEY_NOD node, ISC_QUAD* blob_id)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s t o r e _ q u e r y _ h e a d e r
*
**************************************
*
* Functional description
* Store a query header.
*
**************************************/
2003-04-16 12:18:51 +02:00
ISC_STATUS_ARRAY status_vector;
2001-05-23 15:26:42 +02:00
USHORT bpb_length;
UCHAR bpb[20];
2001-05-23 15:26:42 +02:00
bpb_length = 0;
2004-05-03 01:06:37 +02:00
FB_API_HANDLE blob = create_blob(blob_id, bpb_length, bpb);
2001-05-23 15:26:42 +02:00
for (int pos = 0; pos < node->nod_count; pos++) {
const sym* symbol = (SYM) node->nod_arg[pos];
2003-11-08 00:27:24 +01:00
if (isc_put_segment(status_vector, &blob, symbol->sym_length,
symbol->sym_string))
{
2003-08-30 04:02:36 +02:00
DDL_db_error(status_vector, 93, NULL, NULL, NULL, NULL, NULL);
2003-11-08 00:27:24 +01:00
// msg 93: isc_put_segment failed
2001-05-23 15:26:42 +02:00
return;
}
}
close_blob(blob);
}
static void store_range( DUDLEY_FLD field)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s t o r e _ r a n g e
*
**************************************
*
* Functional description
* Store the range in a blob. Range was
* already generated into a storable format
* during parse.
*
**************************************/
SLONG *range;
USHORT n;
BASED ON RDB$FIELD_DIMENSIONS.RDB$FIELD_NAME name;
MOVE_SYMBOL(field->fld_name, name);
FOR X IN RDB$FIELD_DIMENSIONS WITH X.RDB$FIELD_NAME EQ name ERASE X;
END_FOR;
for (range = field->fld_ranges, n = 0; n < field->fld_dimension;
2004-03-07 08:58:55 +01:00
range += 2, ++n)
{
2001-05-23 15:26:42 +02:00
STORE X IN RDB$FIELD_DIMENSIONS
2003-09-10 19:52:12 +02:00
strcpy(X.RDB$FIELD_NAME, name);
X.RDB$DIMENSION = n;
X.RDB$LOWER_BOUND = range[0];
X.RDB$UPPER_BOUND = range[1];
END_STORE;
}
2001-05-23 15:26:42 +02:00
}
static void store_text( TXT text, ISC_QUAD* blob_id)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* s t o r e _ t e x t
*
**************************************
*
* Functional description
* store the text of a description or
* BLR expression in a blob.
*
**************************************/
UCHAR bpb[20];
2001-05-23 15:26:42 +02:00
USHORT bpb_length = 0;
2001-05-23 15:26:42 +02:00
2004-05-03 01:06:37 +02:00
FB_API_HANDLE blob = create_blob(blob_id, bpb_length, bpb);
2001-05-23 15:26:42 +02:00
LEX_put_text(blob, text);
close_blob(blob);
}
static void store_userpriv(USERPRIV upriv,
TEXT * grantor, TEXT * priv, USRE usr, UPFE upf)
{
/**************************************
*
* s t o r e _ u s e r p r i v
*
**************************************
*
* Functional description
* store one of possibly many entries for
* a single GRANT statement.
*
**************************************/
STORE X IN RDB$USER_PRIVILEGES USING
2003-09-10 19:52:12 +02:00
X.RDB$FIELD_NAME.NULL = TRUE;
MOVE_SYMBOL(usr->usre_name, X.RDB$USER);
strcpy(X.RDB$GRANTOR, grantor);
strcpy(X.RDB$PRIVILEGE, priv);
X.RDB$GRANT_OPTION =
(upriv->userpriv_flags & USERPRIV_grant) ? TRUE : FALSE;
MOVE_SYMBOL(upriv->userpriv_relation, X.RDB$RELATION_NAME);
X.RDB$USER_TYPE = obj_user;
X.RDB$OBJECT_TYPE = obj_relation;
if (upf) {
MOVE_SYMBOL(upf->upfe_fldname, X.RDB$FIELD_NAME);
X.RDB$FIELD_NAME.NULL = FALSE;
}
2001-05-23 15:26:42 +02:00
END_STORE;
}
static int string_length( SCHAR dtype)
{
/**************************************
*
* s t r i n g _ l e n g t h
*
**************************************
*
* Functional description
* Take a guess at how long a number
* or date will be as a string
*
**************************************/
switch (dtype) {
case dtype_short:
return 6;
case dtype_long:
return 10;
case dtype_quad:
return 19;
case dtype_real:
return 10;
case dtype_double:
return 19;
case dtype_timestamp:
2003-08-30 04:02:36 +02:00
return 10;
/* really 24, kept at 10 for old apps */
2001-05-23 15:26:42 +02:00
case dtype_sql_date:
case dtype_sql_time:
case dtype_int64:
case dtype_blob:
default:
2003-08-30 04:02:36 +02:00
DDL_msg_put(94, NULL, NULL, NULL, NULL, NULL);
/* msg 94: (EXE) string_length: No defined length for blobs */
2001-05-23 15:26:42 +02:00
return 0;
}
}
/*
static void wal_info(const UCHAR* db_info_buffer,
2001-05-23 15:26:42 +02:00
SLONG * log, SCHAR * cur_log, SLONG * part_offset)
{
// **************************************
// *
// * w a l _ i n f o
// *
// **************************************
// *
// * Functional description
// * Extract wal name and offset from wal_info string.
// *
// **************************************
2001-05-23 15:26:42 +02:00
UCHAR item;
const UCHAR* p = db_info_buffer;
2001-05-23 15:26:42 +02:00
2003-11-08 00:27:24 +01:00
while ((item = *p++) != isc_info_end) {
const SLONG length = gds__vax_integer(p, 2);
2001-05-23 15:26:42 +02:00
p += 2;
switch (item) {
2003-11-08 00:27:24 +01:00
case isc_info_logfile:
*log = gds__vax_integer(p, length);
2001-05-23 15:26:42 +02:00
p += length;
break;
2003-11-08 00:27:24 +01:00
case isc_info_cur_logfile_name:
{
const UCHAR* d = p;
p += length;
const SLONG length2 = *d++;
memcpy(cur_log, d, length2);
cur_log[length2] = 0;
break;
}
2001-05-23 15:26:42 +02:00
2003-11-08 00:27:24 +01:00
case isc_info_cur_log_part_offset:
*part_offset = gds__vax_integer(p, length);
2001-05-23 15:26:42 +02:00
p += length;
break;
default:
;
}
}
}
*/