8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 18:03:04 +01:00
firebird-mirror/src/jrd/dyn_mod.epp

3075 lines
80 KiB
Plaintext
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Data Definition Utility
* MODULE: dyn_modify.e
* DESCRIPTION: Dynamic data definition - DYN_modify_<x>
*
* 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): ______________________________________.
* 2001.5.20: Claudio Valderrama: when changing a domain's name,
2002-06-30 10:46:51 +02:00
* if it has dimensions, rdb$field_dimensions should be updated, too.
* 2001.5.23: Claudio Valderrama: Forbid zero length identifiers,
* they are not ANSI SQL compliant.
* 2001.5.27 Claudio Valderrama: Prevent rdb$field_length from going
* out of sync when toggling between char and varchar data types.
* This caused check_update_fld_type() to lose ability to detect potentially
* dangerous changes. For example, you could alter a field or a domain and
* be able to change char(10) to varchar(8).
* Unfortunately, Borland chose to have DYN_modify_global_field() and add to the
* party DYN_modify_sql_field(); therefore bug fixes should be done twice.
* 2001.10.08 Claudio Valderrama: put a comment with suggested code to hide
* special non-system triggers from user manipulation.
* 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY)
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/ib_stdio.h"
#include <string.h>
#include "../jrd/common.h"
#include <stdarg.h>
#include "../jrd/jrd.h"
#include "../jrd/tra.h"
#include "../jrd/scl.h"
#include "../jrd/drq.h"
#include "../jrd/flags.h"
#include "../jrd/gds.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/lls.h"
#include "../jrd/all.h"
#include "../jrd/met.h"
#include "../jrd/btr.h"
#include "../jrd/intl.h"
#include "../jrd/dyn.h"
#include "../jrd/all_proto.h"
#include "../jrd/blb_proto.h"
#include "../jrd/cmp_proto.h"
#include "../jrd/dyn_proto.h"
#include "../jrd/dyn_df_proto.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/dyn_md_proto.h"
#include "../jrd/dyn_ut_proto.h"
#include "../jrd/err_proto.h"
#include "../jrd/exe_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/inf_proto.h"
#include "../jrd/intl_proto.h"
#include "../jrd/isc_f_proto.h"
#include "../jrd/met_proto.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/thd_proto.h"
#include "../jrd/vio_proto.h"
#include "../jrd/dsc_proto.h"
#include "../jrd/ail.h"
#ifdef SUPERSERVER
#define V4_THREADING
#endif
#include "../jrd/nlm_thd.h"
DATABASE DB = STATIC "yachts.gdb";
#define MAX_CHARS_SHORT 6 /* 2**16 = 5 chars + sign */
#define MAX_CHARS_LONG 11 /* 2**32 = 10 chars + sign */
#define MAX_CHARS_INT64 20 /* 2**64 = 19 chars + sign */
#define MAX_CHARS_DOUBLE 22 /* 15 digits + 2 signs + E + decimal + 3 digit exp */
#define MAX_CHARS_FLOAT 13 /* 7 digits + 2 signs + E + decimal + 2 digit exp */
static UCHAR alloc_info[] = { gds_info_allocation, gds_info_end };
2001-05-23 15:26:42 +02:00
static void drop_cache(GBL);
static void drop_log(GBL);
// Function not defined in this file MOD 04-July-2002
// static void modify_lfield_type(GBL, UCHAR **, TEXT *, TEXT *);
2001-05-23 15:26:42 +02:00
static void modify_lfield_position(TDBB, DBB, GBL, TEXT *, TEXT *, USHORT,
USHORT);
static BOOLEAN check_view_dependency(TDBB, DBB, GBL, TEXT *, TEXT *);
static BOOLEAN check_sptrig_dependency(TDBB, DBB, GBL, TEXT *, TEXT *);
static void modify_lfield_index(TDBB, DBB, GBL, TEXT *, TEXT *, TEXT *);
static BOOLEAN field_exists(TDBB, DBB, GBL, TEXT *, TEXT *);
static BOOLEAN domain_exists(TDBB, DBB, GBL, TEXT *);
static void get_domain_type(TDBB, DBB, GBL, DYN_FLD);
static ULONG check_update_fld_type(DYN_FLD, DYN_FLD);
static void modify_err_punt(TDBB, ULONG, DYN_FLD, DYN_FLD);
void DYN_modify_database( GBL gbl, UCHAR ** ptr)
{
/**************************************
*
* D Y N _ m o d i f y _ d a t a b a s e
*
**************************************
*
* Functional description
* Modify a database.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
SSHORT length;
SLONG start;
UCHAR verb, s[128];
SSHORT num_log_buffers = 0;
USHORT log_buffer_size = 0;
SLONG check_point_len = 0, group_commit_wait = -1;
SSHORT log_params_defined = FALSE;
#ifdef SUPERSERVER
USHORT first_log_file = TRUE;
#endif
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = NULL;
2001-12-24 03:51:06 +01:00
try {
INF_database_info((SCHAR*)alloc_info, sizeof(alloc_info), (SCHAR*)s, sizeof(s));
2001-05-23 15:26:42 +02:00
if (s[0] != gds_info_allocation) {
2001-12-24 03:51:06 +01:00
goto dyn_punt_84;
2001-05-23 15:26:42 +02:00
}
request = (BLK) CMP_find_request(tdbb, drq_m_database, DYN_REQUESTS);
length = gds__vax_integer(s + 1, 2);
start = gds__vax_integer(s + 3, length);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
DBB IN RDB$DATABASE
if (!DYN_REQUEST(drq_m_database))
DYN_REQUEST(drq_m_database) = request;
MODIFY DBB USING
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_security_class:
2001-05-23 15:26:42 +02:00
if (GET_STRING(ptr, DBB.RDB$SECURITY_CLASS))
DBB.RDB$SECURITY_CLASS.NULL = FALSE;
else
DBB.RDB$SECURITY_CLASS.NULL = TRUE;
break;
case gds_dyn_description:
2001-05-23 15:26:42 +02:00
if (DYN_put_text_blob(gbl, ptr, &DBB.RDB$DESCRIPTION))
DBB.RDB$DESCRIPTION.NULL = FALSE;
else
DBB.RDB$DESCRIPTION.NULL = TRUE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_description2:
2001-05-23 15:26:42 +02:00
if (DYN_put_text_blob2(gbl, ptr, &DBB.RDB$DESCRIPTION))
DBB.RDB$DESCRIPTION.NULL = FALSE;
else
DBB.RDB$DESCRIPTION.NULL = TRUE;
break;
#endif
case gds_dyn_def_file:
2001-05-23 15:26:42 +02:00
DYN_define_file(gbl, ptr, (SLONG) 0, &start, 158);
break;
#ifdef SUPERSERVER
case gds_dyn_def_default_log:
2001-05-23 15:26:42 +02:00
DYN_define_log_file(gbl, ptr, first_log_file, TRUE);
break;
case gds_dyn_def_log_file:
2001-05-23 15:26:42 +02:00
DYN_define_log_file(gbl, ptr, first_log_file, FALSE);
first_log_file = FALSE;
break;
#endif
case gds_dyn_def_cache_file:
2001-05-23 15:26:42 +02:00
DYN_define_cache(gbl, ptr);
break;
case gds_dyn_log_group_commit_wait:
2001-05-23 15:26:42 +02:00
group_commit_wait = DYN_get_number(ptr);
log_params_defined = TRUE;
break;
case gds_dyn_log_buffer_size:
2001-05-23 15:26:42 +02:00
log_buffer_size = DYN_get_number(ptr);
log_params_defined = TRUE;
break;
case gds_dyn_log_check_point_length:
2001-05-23 15:26:42 +02:00
check_point_len = DYN_get_number(ptr);
log_params_defined = TRUE;
break;
case gds_dyn_log_num_of_buffers:
2001-05-23 15:26:42 +02:00
num_log_buffers = DYN_get_number(ptr);
log_params_defined = TRUE;
break;
case gds_dyn_drop_cache:
2001-05-23 15:26:42 +02:00
drop_cache(gbl);
break;
case gds_dyn_drop_log:
2001-05-23 15:26:42 +02:00
drop_log(gbl);
break;
case gds_dyn_fld_character_set_name:
2001-05-23 15:26:42 +02:00
if (GET_STRING(ptr, DBB.RDB$CHARACTER_SET_NAME))
DBB.RDB$CHARACTER_SET_NAME.NULL = FALSE;
else
DBB.RDB$CHARACTER_SET_NAME.NULL = TRUE;
break;
default:
--(*ptr);
DYN_execute(gbl, ptr, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR,
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
2001-05-23 15:26:42 +02:00
}
END_MODIFY;
END_FOR;
if (log_params_defined)
AIL_set_log_options(check_point_len, num_log_buffers, log_buffer_size,
group_commit_wait);
if (!DYN_REQUEST(drq_m_database))
DYN_REQUEST(drq_m_database) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 84, NULL, NULL, NULL, NULL, NULL);
/* msg 84: "MODIFY DATABASE failed" */
}
return;
dyn_punt_84:
DYN_error_punt(TRUE, 84, NULL, NULL, NULL, NULL, NULL);
/* msg 84: "MODIFY DATABASE failed" */
2001-05-23 15:26:42 +02:00
}
void DYN_modify_exception( GBL gbl, UCHAR ** ptr)
{
/**************************************
*
* D Y N _ m o d i f y _ e x c e p t i o n
*
**************************************
*
* Functional description
* Modify an exception.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
USHORT found;
UCHAR verb;
TEXT t[32];
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = (BLK) CMP_find_request(tdbb, drq_m_xcp, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, t);
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$EXCEPTIONS
WITH X.RDB$EXCEPTION_NAME EQ t
if (!DYN_REQUEST(drq_m_xcp)) DYN_REQUEST(drq_m_xcp) = request;
found = TRUE;
MODIFY X
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_xcp_msg:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, X.RDB$MESSAGE);
X.RDB$MESSAGE.NULL = FALSE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_xcp_msg2:
2001-05-23 15:26:42 +02:00
DYN_get_string2(ptr, X.RDB$MESSAGE,
sizeof(X.RDB$MESSAGE));
X.RDB$MESSAGE.NULL = FALSE;
break;
#endif
default:
DYN_unsupported_verb();
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_xcp))
DYN_REQUEST(drq_m_xcp) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 145, NULL, NULL, NULL, NULL, NULL);
/* msg 145: "MODIFY EXCEPTION failed" */
}
2001-05-23 15:26:42 +02:00
if (!found)
2001-12-24 03:51:06 +01:00
{
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 144, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 144: "Exception not found" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_global_field(
GBL gbl,
UCHAR ** ptr,
TEXT * relation_name, TEXT * field_name)
{
/**************************************
*
* D Y N _ m o d i f y _ g l o b a l _ f i e l d
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement.
* Note: a global field here is a SQL domain.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request, old_request;
USHORT found, single_validate = FALSE;
UCHAR verb;
DYN_FLD orig_dom, new_dom;
BOOLEAN dtype, scale, prec, subtype, charlen, collation, fldlen, nullflg,
charset;
2001-12-24 03:51:06 +01:00
TEXT *qryname, *qryhdr, *edtstr, *missingval,
*fldvald, *fldvaldsrc, *desc,
*flddftval, *flddfltsrc;
#if (defined JPN_SJIS || defined JPN_EUC)
TEXT* edtstr2;
TEXT* qryhdr2;
TEXT* desc2;
TEXT* fldvaldsrc2;
#endif
2001-05-23 15:26:42 +02:00
BOOLEAN bqryname, bqryhdr, bqryhdr2, bedtstr, bedtstr2, bmissingval,
bsingvald, bfldvald, bfldvaldsrc, bfldvaldsrc2, bdesc, bdesc2,
bdelvald, bdeldflt, bflddftval, bflddfltsrc;
BOOLEAN has_dimensions = FALSE;
2002-06-30 10:46:51 +02:00
SSHORT field_adjusted_count = 0;
TEXT *err_one_type_change_only = "Only one data type change to the domain allowed at a time";
2001-05-23 15:26:42 +02:00
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
dtype = scale = prec = subtype = charlen = collation = fldlen = nullflg =
charset = FALSE;
bqryname = bqryhdr = bqryhdr2 = bedtstr = bedtstr2 = bmissingval =
bsingvald = FALSE;
bfldvald = bfldvaldsrc = bfldvaldsrc2 = bdesc = bdesc2 = bdelvald =
bdeldflt = bflddftval = bflddfltsrc = FALSE;
request = (BLK) CMP_find_request(tdbb, drq_m_gfield, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
/* Allocate the field structures */
orig_dom = (DYN_FLD) gds__alloc(sizeof(struct dyn_fld));
2001-12-24 03:51:06 +01:00
if (!orig_dom) {
2001-05-23 15:26:42 +02:00
DYN_error_punt(TRUE, 211, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
MOVE_CLEAR(orig_dom, sizeof(struct dyn_fld));
new_dom = (DYN_FLD) gds__alloc(sizeof(struct dyn_fld));
2001-12-24 03:51:06 +01:00
if (!new_dom) {
2001-05-23 15:26:42 +02:00
DYN_error_punt(TRUE, 211, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
MOVE_CLEAR(new_dom, sizeof(struct dyn_fld));
GET_STRING(ptr, orig_dom->dyn_fld_name);
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ orig_dom->dyn_fld_name
if (!DYN_REQUEST(drq_m_gfield))
DYN_REQUEST(drq_m_gfield) = request;
found = TRUE;
DSC_make_descriptor(&orig_dom->dyn_dsc,
FLD.RDB$FIELD_TYPE,
FLD.RDB$FIELD_SCALE,
FLD.RDB$FIELD_LENGTH,
FLD.RDB$FIELD_SUB_TYPE,
FLD.RDB$CHARACTER_SET_ID, FLD.RDB$COLLATION_ID);
2002-06-30 10:46:51 +02:00
orig_dom->dyn_charbytelen = FLD.RDB$FIELD_LENGTH;
2001-05-23 15:26:42 +02:00
orig_dom->dyn_dtype = FLD.RDB$FIELD_TYPE;
orig_dom->dyn_precision = FLD.RDB$FIELD_PRECISION;
orig_dom->dyn_charlen = FLD.RDB$CHARACTER_LENGTH;
orig_dom->dyn_collation = FLD.RDB$COLLATION_ID;
orig_dom->dyn_null_flag = FLD.RDB$NULL_FLAG;
/* If the original field type is an array, force its blr type to blr_blob */
if (FLD.RDB$DIMENSIONS != 0)
{
orig_dom->dyn_dtype = blr_blob;
has_dimensions = TRUE;
}
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
{
switch (verb)
{
case gds_dyn_fld_name:
2001-05-23 15:26:42 +02:00
{
char newfld[32];
if (GET_STRING(ptr, newfld))
{
if (!domain_exists(tdbb, dbb, gbl, newfld))
{
MODIFY FLD USING
strcpy(FLD.RDB$FIELD_NAME, newfld);
FLD.RDB$FIELD_NAME.NULL = FALSE;
old_request = request;
request = NULL;
/* CVC: Let's update the dimensions, too. */
if (has_dimensions)
{
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
DIM_DOM IN RDB$FIELD_DIMENSIONS
WITH DIM_DOM.RDB$FIELD_NAME EQ orig_dom->dyn_fld_name
MODIFY DIM_DOM USING
strcpy (DIM_DOM.RDB$FIELD_NAME, newfld);
DIM_DOM.RDB$FIELD_NAME.NULL = FALSE;
END_MODIFY;
END_FOR;
CMP_release (tdbb, (REQ) request);
2001-05-23 15:26:42 +02:00
request = NULL;
}
/* CVC: End modification. */
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
DOM IN RDB$RELATION_FIELDS
WITH DOM.RDB$FIELD_SOURCE EQ orig_dom->dyn_fld_name
MODIFY DOM USING
strcpy(DOM.RDB$FIELD_SOURCE, newfld);
DOM.RDB$FIELD_SOURCE.NULL = FALSE;
END_MODIFY;
modify_lfield_index(tdbb, dbb, gbl,
DOM.RDB$RELATION_NAME,
DOM.RDB$FIELD_NAME,
DOM.RDB$FIELD_NAME);
END_FOR;
CMP_release(tdbb, (REQ)request);
request = old_request;
END_MODIFY;
}
else
{
DYN_error_punt(FALSE, 204, orig_dom->dyn_fld_name,
newfld, NULL, NULL, NULL);
/* msg 204: Cannot rename domain %s to %s. A domain with that name already exists. */
}
}
2002-06-30 10:46:51 +02:00
else
{
DYN_error_punt(FALSE, 212, NULL, NULL, NULL, NULL, NULL);
/* msg 212: "Zero length identifiers not allowed" */
}
2001-05-23 15:26:42 +02:00
break;
}
case gds_dyn_rel_name:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, new_dom->dyn_rel_name);
break;
2002-06-30 10:46:51 +02:00
/* CVC: The syntax for DDL alter domain was accepting multiple
changes in one command even to the same features, IE two length alterations.
This repetitive type change will cause havoc so it should be stopped in the future. */
case gds_dyn_fld_length:
2001-05-23 15:26:42 +02:00
fldlen = TRUE;
new_dom->dyn_dsc.dsc_length = DYN_get_number(ptr);
2002-06-30 10:46:51 +02:00
if (++field_adjusted_count > 2)
{
EXE_unwind(tdbb, (REQ)request);
2002-06-30 10:46:51 +02:00
DYN_error_punt(FALSE, 5, err_one_type_change_only, NULL, NULL, NULL, NULL);
}
switch (new_dom->dyn_dtype) {
case blr_text:
case blr_text2:
case blr_varying:
case blr_varying2:
case blr_cstring:
case blr_cstring2:
new_dom->dyn_charbytelen = new_dom->dyn_dsc.dsc_length;
break;
default:
new_dom->dyn_charbytelen = 0; /* It won't be used, anyway. */
break;
}
2001-05-23 15:26:42 +02:00
break;
case gds_dyn_fld_type:
2001-05-23 15:26:42 +02:00
dtype = TRUE;
new_dom->dyn_dtype = DYN_get_number(ptr);
2002-06-30 10:46:51 +02:00
if (++field_adjusted_count > 2)
{
EXE_unwind(tdbb, (REQ)request);
2002-06-30 10:46:51 +02:00
DYN_error_punt(FALSE, 5, err_one_type_change_only, NULL, NULL, NULL, NULL);
}
2001-05-23 15:26:42 +02:00
switch (new_dom->dyn_dtype) {
case blr_text:
case blr_text2:
case blr_varying:
case blr_varying2:
case blr_cstring:
case blr_cstring2:
2002-06-30 10:46:51 +02:00
if (new_dom->dyn_dsc.dsc_length && !new_dom->dyn_charbytelen)
new_dom->dyn_charbytelen = new_dom->dyn_dsc.dsc_length;
new_dom->dyn_dsc.dsc_length = DSC_string_length(&new_dom->dyn_dsc);
2001-05-23 15:26:42 +02:00
break;
case blr_short:
new_dom->dyn_dsc.dsc_length = 2;
break;
case blr_long:
case blr_float:
new_dom->dyn_dsc.dsc_length = 4;
break;
case blr_int64:
case blr_sql_time:
case blr_sql_date:
case blr_timestamp:
case blr_double:
case blr_d_float:
new_dom->dyn_dsc.dsc_length = 8;
break;
default:
break;
}
break;
case gds_dyn_fld_scale:
2001-05-23 15:26:42 +02:00
scale = TRUE;
new_dom->dyn_dsc.dsc_scale = DYN_get_number(ptr);
break;
case isc_dyn_fld_precision:
prec = TRUE;
new_dom->dyn_precision = DYN_get_number(ptr);
break;
case gds_dyn_fld_sub_type:
2001-05-23 15:26:42 +02:00
subtype = TRUE;
new_dom->dyn_dsc.dsc_sub_type = DYN_get_number(ptr);
break;
case gds_dyn_fld_char_length:
2001-05-23 15:26:42 +02:00
charlen = TRUE;
new_dom->dyn_charlen = DYN_get_number(ptr);
break;
case gds_dyn_fld_collation:
2001-05-23 15:26:42 +02:00
collation = TRUE;
new_dom->dyn_collation = DYN_get_number(ptr);
break;
case gds_dyn_fld_character_set:
2001-05-23 15:26:42 +02:00
charset = TRUE;
new_dom->dyn_charset = DYN_get_number(ptr);
break;
case gds_dyn_fld_not_null:
2001-05-23 15:26:42 +02:00
nullflg = TRUE;
new_dom->dyn_null_flag = TRUE;
break;
case gds_dyn_fld_query_name:
2001-05-23 15:26:42 +02:00
qryname = (TEXT *) * ptr;
bqryname = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_fld_query_header:
2001-05-23 15:26:42 +02:00
qryhdr = (TEXT *) * ptr;
bqryhdr = TRUE;
DYN_skip_attribute(ptr);
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_fld_query_header2:
2001-05-23 15:26:42 +02:00
qryhdr2 = (TEXT *) * ptr;
bqryhdr2 = TRUE;
DYN_skip_attribute2(ptr);
break;
#endif
case gds_dyn_fld_edit_string:
2001-05-23 15:26:42 +02:00
edtstr = (TEXT *) * ptr;
bedtstr = TRUE;
DYN_skip_attribute(ptr);
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_fld_edit_string2:
2001-05-23 15:26:42 +02:00
edtstr2 = (TEXT *) * ptr;
bedtstr2 = TRUE;
DYN_skip_attribute2(ptr);
break;
#endif
case gds_dyn_fld_missing_value:
2001-05-23 15:26:42 +02:00
missingval = (TEXT *) * ptr;
bmissingval = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_single_validation:
2001-05-23 15:26:42 +02:00
if (single_validate) {
EXE_unwind(tdbb, (REQ)request);
DYN_error_punt(FALSE, 160, NULL, NULL, NULL, NULL, NULL);
/* msg 160: "Only one constraint allowed for a domain" */
break;
}
else
single_validate = TRUE;
break;
case gds_dyn_fld_validation_blr:
2001-05-23 15:26:42 +02:00
if (single_validate && (!FLD.RDB$VALIDATION_BLR.NULL)) {
EXE_unwind(tdbb, (REQ)request);
DYN_error_punt(FALSE, 160, NULL, NULL, NULL, NULL, NULL);
/* msg 160: "Only one constraint allowed for a domain" */
break;
}
else
single_validate = TRUE;
fldvald = (TEXT *) * ptr;
bfldvald = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_fld_validation_source:
2001-05-23 15:26:42 +02:00
fldvaldsrc = (TEXT *) * ptr;
bfldvaldsrc = TRUE;
DYN_skip_attribute(ptr);
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_fld_validation_source2:
2001-05-23 15:26:42 +02:00
fldvaldsrc2 = (TEXT *) * ptr;
bfldvaldsrc2 = TRUE;
DYN_skip_attribute2(ptr);
break;
#endif
case gds_dyn_description:
2001-05-23 15:26:42 +02:00
desc = (TEXT *) * ptr;
bdesc = TRUE;
DYN_skip_attribute(ptr);
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_description2:
2001-05-23 15:26:42 +02:00
desc2 = (TEXT *) * ptr;
bdesc2 = TRUE;
DYN_skip_attribute2(ptr);
break;
#endif
case gds_dyn_del_validation:
2001-05-23 15:26:42 +02:00
bdelvald = TRUE;
break;
case gds_dyn_del_default:
2001-05-23 15:26:42 +02:00
bdeldflt = TRUE;
break;
case gds_dyn_fld_default_value:
2001-05-23 15:26:42 +02:00
flddftval = (TEXT *) * ptr;
bflddftval = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_fld_default_source:
2001-05-23 15:26:42 +02:00
flddfltsrc = (TEXT *) * ptr;
bflddfltsrc = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_fld_dimensions:
2001-05-23 15:26:42 +02:00
new_dom->dyn_dtype = blr_blob;
break;
/* These should only be defined for BLOB types and should not come through with
* any other types. Do nothing with them.
*/
case gds_dyn_fld_segment_length:
2001-05-23 15:26:42 +02:00
DYN_get_number(ptr);
break;
default:
--(*ptr);
DYN_execute(gbl, ptr, relation_name, field_name,
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
2001-05-23 15:26:42 +02:00
}
}
2002-06-30 10:46:51 +02:00
/* Now that we have all of the information needed, let's check to see if the field type can be modifed.
* Only do this, however, if we are actually modifying the datatype of the domain.
2001-05-23 15:26:42 +02:00
*/
if (dtype) {
ULONG retval;
DSC_make_descriptor(&new_dom->dyn_dsc,
new_dom->dyn_dtype,
new_dom->dyn_dsc.dsc_scale,
new_dom->dyn_dsc.dsc_length,
new_dom->dyn_dsc.dsc_sub_type,
new_dom->dyn_charset, new_dom->dyn_collation);
if ((retval = check_update_fld_type(orig_dom, new_dom)) !=
SUCCESS) modify_err_punt(tdbb, retval, orig_dom, new_dom);
}
MODIFY FLD USING
if (dtype) {
FLD.RDB$FIELD_TYPE = new_dom->dyn_dtype;
FLD.RDB$FIELD_TYPE.NULL = FALSE;
/* If the datatype was changed, update any indexes that involved the domain */
old_request = request;
request = NULL;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
DOM IN RDB$RELATION_FIELDS
WITH DOM.RDB$FIELD_SOURCE EQ orig_dom->dyn_fld_name
modify_lfield_index(tdbb, dbb, gbl,
DOM.
RDB$RELATION_NAME,
DOM.RDB$FIELD_NAME,
DOM.RDB$FIELD_NAME);
END_FOR;
CMP_release(tdbb, (REQ)request);
request = old_request;
}
if (scale) {
FLD.RDB$FIELD_SCALE = new_dom->dyn_dsc.dsc_scale;
FLD.RDB$FIELD_SCALE.NULL = FALSE;
}
if (prec) {
FLD.RDB$FIELD_PRECISION = new_dom->dyn_precision;
FLD.RDB$FIELD_PRECISION.NULL = FALSE;
}
if (subtype) {
FLD.RDB$FIELD_SUB_TYPE = new_dom->dyn_dsc.dsc_sub_type;
FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
}
if (charlen) {
FLD.RDB$CHARACTER_LENGTH = new_dom->dyn_charlen;
FLD.RDB$CHARACTER_LENGTH.NULL = FALSE;
}
if (fldlen) {
2002-06-30 10:46:51 +02:00
/* CVC: Rescue from the wrong field_length with a helper. */
if (new_dom->dyn_dsc.dsc_dtype <= dtype_varying && new_dom->dyn_charbytelen)
FLD.RDB$FIELD_LENGTH = new_dom->dyn_charbytelen;
else
FLD.RDB$FIELD_LENGTH = new_dom->dyn_dsc.dsc_length;
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_LENGTH.NULL = FALSE;
}
if (bqryname) {
if (GET_STRING(&qryname, FLD.RDB$QUERY_NAME))
FLD.RDB$QUERY_NAME.NULL = FALSE;
else
FLD.RDB$QUERY_NAME.NULL = TRUE;
}
if (bqryhdr) {
if (DYN_put_blr_blob(gbl, (UCHAR**)&qryhdr, &FLD.RDB$QUERY_HEADER))
2001-05-23 15:26:42 +02:00
FLD.RDB$QUERY_HEADER.NULL = FALSE;
else
FLD.RDB$QUERY_HEADER.NULL = TRUE;
}
#if (defined JPN_SJIS || defined JPN_EUC)
if (bqryhdr2) {
if (DYN_put_blr_blob2(gbl, (UCHAR**)&qryhdr2, &FLD.RDB$QUERY_HEADER))
2001-05-23 15:26:42 +02:00
FLD.RDB$QUERY_HEADER.NULL = FALSE;
else
FLD.RDB$QUERY_HEADER.NULL = TRUE;
}
#endif
if (bedtstr) {
if (GET_STRING(&edtstr, FLD.RDB$EDIT_STRING))
FLD.RDB$EDIT_STRING.NULL = FALSE;
else
FLD.RDB$EDIT_STRING.NULL = TRUE;
}
#if (defined JPN_SJIS || defined JPN_EUC)
if (bedtstr2) {
if (DYN_get_string2
(&edtstr2, FLD.RDB$EDIT_STRING,
sizeof(FLD.RDB$EDIT_STRING))) FLD.RDB$EDIT_STRING.NULL =
FALSE;
else
FLD.RDB$EDIT_STRING.NULL = TRUE;
}
#endif
if (bmissingval) {
if (DYN_put_blr_blob
(gbl, (UCHAR**)&missingval,
2001-05-23 15:26:42 +02:00
&FLD.RDB$MISSING_VALUE)) FLD.RDB$MISSING_VALUE.NULL =
FALSE;
else
FLD.RDB$MISSING_VALUE.NULL = TRUE;
}
if (bfldvald) {
if (DYN_put_blr_blob(gbl, (UCHAR**)&fldvald, &FLD.RDB$VALIDATION_BLR))
2001-05-23 15:26:42 +02:00
FLD.RDB$VALIDATION_BLR.NULL = FALSE;
else
FLD.RDB$VALIDATION_BLR.NULL = TRUE;
}
if (bfldvaldsrc) {
if (DYN_put_text_blob
(gbl, (UCHAR**)&fldvaldsrc,
2001-05-23 15:26:42 +02:00
&FLD.RDB$VALIDATION_SOURCE)) FLD.RDB$VALIDATION_SOURCE.
NULL = FALSE;
else
FLD.RDB$VALIDATION_SOURCE.NULL = TRUE;
}
#if (defined JPN_SJIS || defined JPN_EUC)
if (bfldvaldsrc2) {
if (DYN_put_text_blob2
(gbl, (UCHAR**)&fldvaldsrc2,
2001-05-23 15:26:42 +02:00
&FLD.RDB$VALIDATION_SOURCE)) FLD.RDB$VALIDATION_SOURCE.
NULL = FALSE;
else
FLD.RDB$VALIDATION_SOURCE.NULL = TRUE;
}
#endif
if (bdesc) {
if (DYN_put_text_blob(gbl, (UCHAR**)&desc, &FLD.RDB$DESCRIPTION))
2001-05-23 15:26:42 +02:00
FLD.RDB$DESCRIPTION.NULL = FALSE;
else
FLD.RDB$DESCRIPTION.NULL = TRUE;
}
#if (defined JPN_SJIS || defined JPN_EUC)
if (bdesc2) {
if (DYN_put_text_blob2(gbl, (UCHAR**)&desc2, &FLD.RDB$DESCRIPTION))
2001-05-23 15:26:42 +02:00
FLD.RDB$DESCRIPTION.NULL = FALSE;
else
FLD.RDB$DESCRIPTION.NULL = TRUE;
}
#endif
if (bdelvald) {
FLD.RDB$VALIDATION_BLR.NULL = TRUE;
FLD.RDB$VALIDATION_SOURCE.NULL = TRUE;
}
if (bdeldflt) {
FLD.RDB$DEFAULT_VALUE.NULL = TRUE;
FLD.RDB$DEFAULT_SOURCE.NULL = TRUE;
}
if (bflddftval) {
FLD.RDB$DEFAULT_VALUE.NULL = FALSE;
DYN_put_blr_blob(gbl, (UCHAR**)&flddftval, &FLD.RDB$DEFAULT_VALUE);
2001-05-23 15:26:42 +02:00
}
if (bflddfltsrc) {
FLD.RDB$DEFAULT_SOURCE.NULL = FALSE;
DYN_put_text_blob(gbl, (UCHAR**)&flddfltsrc, &FLD.RDB$DEFAULT_SOURCE);
2001-05-23 15:26:42 +02:00
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_gfield))
DYN_REQUEST(drq_m_gfield) = request;
if (orig_dom)
gds__free((SLONG *) orig_dom);
if (new_dom)
gds__free((SLONG *) new_dom);
2001-12-24 03:51:06 +01:00
}
catch (...) {
if (orig_dom) {
gds__free((SLONG *) orig_dom);
}
if (new_dom) {
gds__free((SLONG *) new_dom);
}
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 87, NULL, NULL, NULL, NULL, NULL);
/* msg 87: "MODIFY RDB$FIELDS failed" */
}
2001-05-23 15:26:42 +02:00
if (!found)
2001-12-24 03:51:06 +01:00
{
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 89, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 89: "Global field not found" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_index( GBL gbl, UCHAR ** ptr)
{
/**************************************
*
* D Y N _ m o d i f y _ i n d e x
*
**************************************
*
* Functional description
* Modify an existing index
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
USHORT found;
UCHAR verb;
TEXT name[32];
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = (BLK) CMP_find_request(tdbb, drq_m_index, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, name);
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
IDX IN RDB$INDICES WITH IDX.RDB$INDEX_NAME EQ name
if (!DYN_REQUEST(drq_m_index)) DYN_REQUEST(drq_m_index) = request;
found = TRUE;
MODIFY IDX USING
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_idx_unique:
2001-05-23 15:26:42 +02:00
IDX.RDB$UNIQUE_FLAG = DYN_get_number(ptr);
IDX.RDB$UNIQUE_FLAG.NULL = FALSE;
break;
case gds_dyn_idx_inactive:
2001-05-23 15:26:42 +02:00
IDX.RDB$INDEX_INACTIVE = DYN_get_number(ptr);
IDX.RDB$INDEX_INACTIVE.NULL = FALSE;
break;
case gds_dyn_description:
2001-05-23 15:26:42 +02:00
if (DYN_put_text_blob(gbl, ptr, &IDX.RDB$DESCRIPTION))
IDX.RDB$DESCRIPTION.NULL = FALSE;
else
IDX.RDB$DESCRIPTION.NULL = TRUE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_description2:
2001-05-23 15:26:42 +02:00
if (DYN_put_text_blob2(gbl, ptr, &IDX.RDB$DESCRIPTION))
IDX.RDB$DESCRIPTION.NULL = FALSE;
else
IDX.RDB$DESCRIPTION.NULL = TRUE;
break;
#endif
/* For V4 index selectivity can be set only to -1 */
case gds_dyn_idx_statistic:
2001-05-23 15:26:42 +02:00
IDX.RDB$STATISTICS = -1.0;
IDX.RDB$STATISTICS.NULL = FALSE;
break;
default:
DYN_unsupported_verb();
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_index))
DYN_REQUEST(drq_m_index) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 91, NULL, NULL, NULL, NULL, NULL);
/* msg 91: "MODIFY RDB$INDICES failed" */
}
2001-05-23 15:26:42 +02:00
if (!found)
2001-12-24 03:51:06 +01:00
{
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 93, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 93: "Index field not found" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_local_field(
GBL gbl,
UCHAR ** ptr,
TEXT * relation_name, TEXT * field_name)
{
/**************************************
*
* D Y N _ m o d i f y _ l o c a l _ f i e l d
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
USHORT found, position, existing_position;
USHORT sfflag, qnflag, qhflag, esflag, dflag, system_flag, scflag, nnflag,
ntflag, npflag;
UCHAR verb;
TEXT f[32], r[32], *query_name, *query_header, *edit_string, *description,
*security_class, *new_name;
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
GET_STRING(ptr, f);
r[0] = 0;
sfflag = qnflag = qhflag = esflag = dflag = scflag = npflag = nnflag =
ntflag = FALSE;
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_rel_name:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, r);
break;
case gds_dyn_system_flag:
2001-05-23 15:26:42 +02:00
system_flag = DYN_get_number(ptr);
sfflag = TRUE;
break;
case gds_dyn_fld_position:
2001-05-23 15:26:42 +02:00
position = DYN_get_number(ptr);
npflag = TRUE;
break;
case isc_dyn_new_fld_name:
new_name = (TEXT *) * ptr;
nnflag = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_fld_query_name:
2001-05-23 15:26:42 +02:00
query_name = (TEXT *) * ptr;
qnflag = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_fld_query_header:
2001-05-23 15:26:42 +02:00
query_header = (TEXT *) * ptr;
qhflag = TRUE;
DYN_skip_attribute(ptr);
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_fld_query_header2:
2001-05-23 15:26:42 +02:00
query_header = (TEXT *) * ptr;
qhflag = TRUE;
DYN_skip_attribute2(ptr);
break;
#endif
case gds_dyn_fld_edit_string:
2001-05-23 15:26:42 +02:00
edit_string = (TEXT *) * ptr;
esflag = TRUE;
DYN_skip_attribute(ptr);
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_fld_edit_string2:
2001-05-23 15:26:42 +02:00
edit_string = (TEXT *) * ptr;
esflag = TRUE;
DYN_skip_attribute2(ptr);
break;
#endif
case gds_dyn_security_class:
2001-05-23 15:26:42 +02:00
security_class = (TEXT *) * ptr;
scflag = TRUE;
DYN_skip_attribute(ptr);
break;
case gds_dyn_description:
2001-05-23 15:26:42 +02:00
description = (TEXT *) * ptr;
dflag = TRUE;
DYN_skip_attribute(ptr);
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_description2:
2001-05-23 15:26:42 +02:00
description = (TEXT *) * ptr;
dflag = TRUE;
DYN_skip_attribute2(ptr);
break;
#endif
default:
--(*ptr);
DYN_execute(gbl, ptr, relation_name, field_name,
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
2001-05-23 15:26:42 +02:00
}
request = (BLK) CMP_find_request(tdbb, drq_m_lfield, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$RELATION_FIELDS
WITH FLD.RDB$FIELD_NAME EQ f AND FLD.RDB$RELATION_NAME EQ r
if (!DYN_REQUEST(drq_m_lfield))
DYN_REQUEST(drq_m_lfield) = request;
found = TRUE;
MODIFY FLD USING
if (npflag)
existing_position = FLD.RDB$FIELD_POSITION;
if (sfflag) {
FLD.RDB$SYSTEM_FLAG = system_flag;
FLD.RDB$SYSTEM_FLAG.NULL = FALSE;
}
if (qnflag) {
if (GET_STRING(&query_name, FLD.RDB$QUERY_NAME))
FLD.RDB$QUERY_NAME.NULL = FALSE;
else
FLD.RDB$QUERY_NAME.NULL = TRUE;
}
if (nnflag) {
TEXT new_fld[FLD_NAME_LEN];
2002-06-30 10:46:51 +02:00
new_fld[0] = 0;
2001-05-23 15:26:42 +02:00
GET_STRING(&new_name, new_fld);
2002-06-30 10:46:51 +02:00
MET_exact_name(new_fld);
if (!new_fld[0])
DYN_error_punt(FALSE, 212, NULL, NULL, NULL, NULL, NULL);
/* msg 212: "Zero length identifiers not allowed" */
2001-05-23 15:26:42 +02:00
check_view_dependency(tdbb, dbb, gbl, r, f);
check_sptrig_dependency(tdbb, dbb, gbl, r, f);
if (!field_exists(tdbb, dbb, gbl, r, new_fld)) {
strcpy(FLD.RDB$FIELD_NAME, new_fld);
modify_lfield_index(tdbb, dbb, gbl, r, f,
FLD.RDB$FIELD_NAME);
}
else {
DYN_error_punt(FALSE, 205, f, new_fld, r, NULL, NULL);
/* msg 205: Cannot rename field %s to %s. A field with that name already exists in table %s. */
}
}
if (qhflag) {
#if ( !(defined JPN_SJIS || defined JPN_EUC))
if (DYN_put_blr_blob
(gbl, (UCHAR**)&query_header, &FLD.RDB$QUERY_HEADER))
2001-05-23 15:26:42 +02:00
#else
if (DYN_put_blr_blob2
(gbl, (UCHAR**)&query_header, &FLD.RDB$QUERY_HEADER))
2001-05-23 15:26:42 +02:00
#endif
FLD.RDB$QUERY_HEADER.NULL = FALSE;
else
FLD.RDB$QUERY_HEADER.NULL = TRUE;
}
if (esflag) {
#if (! (defined JPN_SJIS || defined JPN_EUC) )
if (GET_STRING(&edit_string, FLD.RDB$EDIT_STRING))
#else
if (DYN_get_string2
(&edit_string, FLD.RDB$EDIT_STRING,
sizeof(FLD.RDB$EDIT_STRING)))
#endif
FLD.RDB$EDIT_STRING.NULL = FALSE;
else
FLD.RDB$EDIT_STRING.NULL = TRUE;
}
if (scflag) {
if (GET_STRING(&security_class, FLD.RDB$SECURITY_CLASS))
FLD.RDB$SECURITY_CLASS.NULL = FALSE;
else
FLD.RDB$SECURITY_CLASS.NULL = TRUE;
}
if (dflag) {
#if (defined JPN_EUC || defined JPN_SJIS)
if (DYN_put_text_blob2
(gbl, (UCHAR**)&description, &FLD.RDB$DESCRIPTION))
2001-05-23 15:26:42 +02:00
#else
if (DYN_put_text_blob
(gbl, (UCHAR**)&description, &FLD.RDB$DESCRIPTION))
2001-05-23 15:26:42 +02:00
#endif /* (defined JPN_EUC || defined JPN_SJIS) */
FLD.RDB$DESCRIPTION.NULL = FALSE;
else
FLD.RDB$DESCRIPTION.NULL = TRUE;
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_lfield))
DYN_REQUEST(drq_m_lfield) = request;
2002-06-30 10:46:51 +02:00
if (npflag && found && position != existing_position)
2001-05-23 15:26:42 +02:00
modify_lfield_position(tdbb, dbb, gbl, r, f, position,
existing_position);
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 95, NULL, NULL, NULL, NULL, NULL);
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
}
2001-05-23 15:26:42 +02:00
if (!found)
2001-12-24 03:51:06 +01:00
{
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 96, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 96: "Local column not found" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_procedure( GBL gbl, UCHAR ** ptr)
{
/**************************************
*
* D Y N _ m o d i f y _ p r o c e d u r e
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
UCHAR verb;
USHORT found;
TEXT procedure_name[PROC_NAME_SIZE];
GET_STRING(ptr, procedure_name);
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = NULL;
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
request = (BLK) CMP_find_request(tdbb, drq_m_prcs, DYN_REQUESTS);
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
P IN RDB$PROCEDURES WITH P.RDB$PROCEDURE_NAME = procedure_name
if (!DYN_REQUEST(drq_m_prcs))
DYN_REQUEST(drq_m_prcs) = request;
found = TRUE;
/* Set NULL flags to TRUE only for fields which must be specified in the DYN string.
Retain existing values on other fields (RDB$DESCRIPTION, RDB$SECURITY_CLASS),
unless explicitly changed in the DYN string */
MODIFY P
P.RDB$SYSTEM_FLAG.NULL = TRUE;
P.RDB$PROCEDURE_BLR.NULL = TRUE;
P.RDB$PROCEDURE_SOURCE.NULL = TRUE;
P.RDB$PROCEDURE_INPUTS.NULL = TRUE;
P.RDB$PROCEDURE_OUTPUTS.NULL = TRUE;
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_system_flag:
2001-05-23 15:26:42 +02:00
P.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
P.RDB$SYSTEM_FLAG.NULL = FALSE;
break;
case gds_dyn_prc_blr:
2001-05-23 15:26:42 +02:00
P.RDB$PROCEDURE_BLR.NULL = FALSE;
DYN_put_blr_blob(gbl, ptr, &P.RDB$PROCEDURE_BLR);
break;
case gds_dyn_description:
2001-05-23 15:26:42 +02:00
DYN_put_text_blob(gbl, ptr, &P.RDB$DESCRIPTION);
P.RDB$DESCRIPTION.NULL = FALSE;
break;
case gds_dyn_prc_source:
2001-05-23 15:26:42 +02:00
DYN_put_text_blob(gbl, ptr, &P.RDB$PROCEDURE_SOURCE);
P.RDB$PROCEDURE_SOURCE.NULL = FALSE;
break;
case gds_dyn_prc_inputs:
2001-05-23 15:26:42 +02:00
P.RDB$PROCEDURE_INPUTS = DYN_get_number(ptr);
P.RDB$PROCEDURE_INPUTS.NULL = FALSE;
break;
case gds_dyn_prc_outputs:
2001-05-23 15:26:42 +02:00
P.RDB$PROCEDURE_OUTPUTS = DYN_get_number(ptr);
P.RDB$PROCEDURE_OUTPUTS.NULL = FALSE;
break;
case gds_dyn_security_class:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, P.RDB$SECURITY_CLASS);
P.RDB$SECURITY_CLASS.NULL = FALSE;
break;
default:
--(*ptr);
DYN_execute(gbl, ptr, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR,
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, procedure_name);
2001-05-23 15:26:42 +02:00
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_prcs))
DYN_REQUEST(drq_m_prcs) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 141, NULL, NULL, NULL, NULL, NULL);
/* msg 141: "MODIFY RDB$PROCEDURES failed" */
}
if (!found) {
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 140, procedure_name, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 140: "Procedure %s not found" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_relation( GBL gbl, UCHAR ** ptr)
{
/**************************************
*
* D Y N _ m o d i f y _ r e l a t i o n
*
**************************************
*
* Functional description
* Modify an existing relation
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
USHORT found;
UCHAR verb;
TEXT name[32], field_name[32];
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
2002-06-30 10:46:51 +02:00
field_name[0] = 0;
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, name);
request = (BLK) CMP_find_request(tdbb, drq_m_relation, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
REL IN RDB$RELATIONS WITH REL.RDB$RELATION_NAME EQ name
if (!DYN_REQUEST(drq_m_relation))
DYN_REQUEST(drq_m_relation) = request;
if (!REL.RDB$VIEW_BLR.NULL)
DYN_error_punt(FALSE, 177, NULL, NULL, NULL, NULL, NULL);
found = TRUE;
MODIFY REL USING
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_system_flag:
2001-05-23 15:26:42 +02:00
REL.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
REL.RDB$SYSTEM_FLAG.NULL = FALSE;
break;
case gds_dyn_security_class:
2001-05-23 15:26:42 +02:00
if (GET_STRING(ptr, REL.RDB$SECURITY_CLASS))
REL.RDB$SECURITY_CLASS.NULL = FALSE;
else
REL.RDB$SECURITY_CLASS.NULL = TRUE;
break;
case gds_dyn_rel_ext_file:
2001-05-23 15:26:42 +02:00
if (REL.RDB$EXTERNAL_FILE.NULL) {
DYN_rundown_request(request, -1);
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 97, NULL, NULL, NULL, NULL,
NULL);
/* msg 97: "add EXTERNAL FILE not allowed" */
}
if (!GET_STRING(ptr, REL.RDB$EXTERNAL_FILE)) {
DYN_rundown_request(request, -1);
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 98, NULL, NULL, NULL, NULL,
NULL);
/* msg 98: "drop EXTERNAL FILE not allowed" */
}
break;
case gds_dyn_description:
2001-05-23 15:26:42 +02:00
if (DYN_put_text_blob(gbl, ptr, &REL.RDB$DESCRIPTION))
REL.RDB$DESCRIPTION.NULL = FALSE;
else
REL.RDB$DESCRIPTION.NULL = TRUE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_description2:
2001-05-23 15:26:42 +02:00
if (DYN_put_text_blob2(gbl, ptr, &REL.RDB$DESCRIPTION))
REL.RDB$DESCRIPTION.NULL = FALSE;
else
REL.RDB$DESCRIPTION.NULL = TRUE;
break;
#endif
default:
--(*ptr);
DYN_execute(gbl, ptr, name, field_name,
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
2001-05-23 15:26:42 +02:00
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_relation))
DYN_REQUEST(drq_m_relation) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 99, NULL, NULL, NULL, NULL, NULL);
/* msg 99: "MODIFY RDB$RELATIONS failed" */
}
2001-05-23 15:26:42 +02:00
if (!found)
2001-12-24 03:51:06 +01:00
{
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 101, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 101: "Relation field not found" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_trigger( GBL gbl, UCHAR ** ptr)
{
/**************************************
*
* D Y N _ m o d i f y _ t r i g g e r
*
**************************************
*
* Functional description
* Modify a trigger for a relation.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
USHORT found;
UCHAR verb, *blr;
TEXT trigger_name[32], *source;
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = (BLK) CMP_find_request(tdbb, drq_m_trigger, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, trigger_name);
source = NULL;
blr = NULL;
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$TRIGGERS WITH X.RDB$TRIGGER_NAME EQ trigger_name
2001-12-24 03:51:06 +01:00
if (!DYN_REQUEST(drq_m_trigger)) {
2001-05-23 15:26:42 +02:00
DYN_REQUEST(drq_m_trigger) = request;
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
2002-06-30 10:46:51 +02:00
/* CVC: I think that we'll do well by hiding our automatic triggers from this function.
Why would a user want to fiddle with triggers that were generated automatically?
if (!X.RDB$SYSTEM_FLAG.NULL)
{
switch (X.RDB$SYSTEM_FLAG)
{
case frb_sysflag_check_constraint:
case frb_sysflag_referential_constraint:
case frb_sysflag_view_check:
continue;
default:
break;
}
}
*/
2001-05-23 15:26:42 +02:00
found = TRUE;
MODIFY X
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_trg_name:
2002-06-30 10:46:51 +02:00
{
TEXT new_trigger_name[32];
new_trigger_name[0] = 0;
/* GET_STRING(ptr, X.RDB$TRIGGER_NAME); */
GET_STRING(ptr, new_trigger_name);
MET_exact_name(new_trigger_name);
if (!new_trigger_name[0])
DYN_error_punt(FALSE, 212, NULL, NULL, NULL, NULL, NULL);
/* msg 212: "Zero length identifiers not allowed" */
strcpy (X.RDB$TRIGGER_NAME, new_trigger_name);
}
2001-05-23 15:26:42 +02:00
break;
case gds_dyn_trg_type:
2001-05-23 15:26:42 +02:00
X.RDB$TRIGGER_TYPE = DYN_get_number(ptr);
X.RDB$TRIGGER_TYPE.NULL = FALSE;
break;
case gds_dyn_trg_sequence:
2001-05-23 15:26:42 +02:00
X.RDB$TRIGGER_SEQUENCE = DYN_get_number(ptr);
X.RDB$TRIGGER_SEQUENCE.NULL = FALSE;
break;
case gds_dyn_trg_inactive:
2001-05-23 15:26:42 +02:00
X.RDB$TRIGGER_INACTIVE = DYN_get_number(ptr);
X.RDB$TRIGGER_INACTIVE.NULL = FALSE;
break;
case gds_dyn_rel_name:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, X.RDB$RELATION_NAME);
X.RDB$RELATION_NAME.NULL = FALSE;
break;
case gds_dyn_trg_blr:
2001-05-23 15:26:42 +02:00
blr = *ptr;
DYN_skip_attribute(ptr);
DYN_put_blr_blob(gbl, &blr, &X.RDB$TRIGGER_BLR);
X.RDB$TRIGGER_BLR.NULL = FALSE;
break;
case gds_dyn_trg_source:
2001-05-23 15:26:42 +02:00
source = (TEXT *) * ptr;
DYN_skip_attribute(ptr);
DYN_put_text_blob(gbl, (UCHAR**)&source, &X.RDB$TRIGGER_SOURCE);
2001-05-23 15:26:42 +02:00
X.RDB$TRIGGER_SOURCE.NULL = FALSE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_trg_source2:
2001-05-23 15:26:42 +02:00
source = (TEXT *) * ptr;
DYN_skip_attribute2(ptr);
DYN_put_text_blob2(gbl, &source, &X.RDB$TRIGGER_SOURCE);
X.RDB$TRIGGER_SOURCE.NULL = FALSE;
break;
#endif
case gds_dyn_description:
2001-05-23 15:26:42 +02:00
DYN_put_text_blob(gbl, ptr, &X.RDB$DESCRIPTION);
X.RDB$DESCRIPTION.NULL = FALSE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_description2:
2001-05-23 15:26:42 +02:00
DYN_put_text_blob2(gbl, ptr, &X.RDB$DESCRIPTION);
X.RDB$DESCRIPTION.NULL = FALSE;
break;
#endif
default:
--(*ptr);
DYN_execute(gbl, ptr, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR,
trigger_name, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
2001-05-23 15:26:42 +02:00
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_trigger))
DYN_REQUEST(drq_m_trigger) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 102, NULL, NULL, NULL, NULL, NULL);
/* msg 102: "MODIFY TRIGGER failed" */
}
if (!found) {
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 147, trigger_name, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 147: "Trigger %s not found" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_trigger_msg( GBL gbl, UCHAR ** ptr, TEXT * trigger_name)
{
/**************************************
*
* D Y N _ m o d i f y _ t r i g g e r _ m s g
*
**************************************
*
* Functional description
* Modify a trigger message.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
int number;
UCHAR verb;
TEXT t[32];
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = (BLK) CMP_find_request(tdbb, drq_m_trg_msg, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
number = DYN_get_number(ptr);
if (trigger_name)
strcpy(t, trigger_name);
else if (*(*ptr)++ == gds_dyn_trg_name)
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, t);
else
DYN_error_punt(FALSE, 103, NULL, NULL, NULL, NULL, NULL);
/* msg 103: "TRIGGER NAME expected" */
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$TRIGGER_MESSAGES
WITH X.RDB$MESSAGE_NUMBER EQ number AND X.RDB$TRIGGER_NAME EQ t
if (!DYN_REQUEST(drq_m_trg_msg))
DYN_REQUEST(drq_m_trg_msg) = request;
MODIFY X
while ((verb = *(*ptr)++) != gds_dyn_end)
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_trg_msg_number:
2001-05-23 15:26:42 +02:00
X.RDB$MESSAGE_NUMBER = DYN_get_number(ptr);
X.RDB$MESSAGE_NUMBER.NULL = FALSE;
break;
case gds_dyn_trg_msg:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, X.RDB$MESSAGE);
X.RDB$MESSAGE.NULL = FALSE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_trg_msg2:
2001-05-23 15:26:42 +02:00
DYN_get_string2(ptr, X.RDB$MESSAGE,
sizeof(X.RDB$MESSAGE));
X.RDB$MESSAGE.NULL = FALSE;
break;
#endif
default:
DYN_unsupported_verb();
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_trg_msg))
DYN_REQUEST(drq_m_trg_msg) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, -1);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 105, NULL, NULL, NULL, NULL, NULL);
/* msg 105: "MODIFY TRIGGER MESSAGE failed" */
}
2001-05-23 15:26:42 +02:00
}
void DYN_modify_view( GBL gbl, UCHAR ** ptr)
{
/**************************************
*
* D Y N _ m o d i f y _ v i e w
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement.
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
UCHAR verb;
USHORT found;
TEXT view_name[32];
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
view_name[0] = 0;
GET_STRING(ptr, view_name);
MET_exact_name(view_name);
if (!view_name[0])
DYN_error_punt(FALSE, 212, NULL, NULL, NULL, NULL, NULL);
/* msg 212: "Zero length identifiers not allowed" */
try {
request = (BLK) CMP_find_request(tdbb, drq_m_relation, DYN_REQUESTS);
found = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
VRL IN RDB$VIEW_RELATIONS CROSS REL IN RDB$RELATIONS
WITH VRL.RDB$VIEW_NAME EQ REL.RDB$RELATION_NAME AND
VRL.RDB$VIEW_NAME EQ view_name
if (!DYN_REQUEST(drq_m_relation))
DYN_REQUEST(drq_m_relation) = request;
found = TRUE;
MODIFY REL
REL.RDB$SYSTEM_FLAG.NULL = TRUE;
REL.RDB$VIEW_BLR.NULL = TRUE;
REL.RDB$VIEW_SOURCE.NULL = TRUE;
REL.RDB$SECURITY_CLASS.NULL = TRUE;
while ((verb = *(*ptr)++) != gds_dyn_end)
switch (verb)
{
case gds_dyn_system_flag:
REL.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
REL.RDB$SYSTEM_FLAG.NULL = FALSE;
break;
case gds_dyn_view_blr:
DYN_put_blr_blob(gbl, ptr, &REL.RDB$VIEW_BLR);
REL.RDB$VIEW_BLR.NULL = FALSE;
break;
case gds_dyn_view_source:
DYN_put_text_blob(gbl, ptr, &REL.RDB$VIEW_SOURCE);
REL.RDB$VIEW_SOURCE.NULL = FALSE;
break;
#if (defined JPN_SJIS || defined JPN_EUC)
case gds_dyn_view_source2:
DYN_put_text_blob2(gbl, ptr, &REL.RDB$VIEW_SOURCE);
REL.RDB$VIEW_SOURCE.NULL = FALSE;
break;
#endif
case gds_dyn_security_class:
GET_STRING(ptr, REL.RDB$SECURITY_CLASS);
REL.RDB$SECURITY_CLASS.NULL = FALSE;
break;
default:
--(*ptr);
DYN_execute(gbl, ptr, REL.RDB$RELATION_NAME, (TEXT*)NULL_PTR,
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
}
END_MODIFY;
END_FOR;
if (!DYN_REQUEST(drq_m_relation))
DYN_REQUEST(drq_m_relation) = request;
}
catch (...) {
DYN_rundown_request(request, -1);
DYN_error_punt(TRUE, 99, NULL, NULL, NULL, NULL, NULL);
/* msg 99: "MODIFY RDB$RELATIONS failed" */
}
if (!found) {
DYN_error_punt(FALSE, 61, NULL, NULL, NULL, NULL, NULL);
/* msg 61: "Relation not found" */
}
}
2001-05-23 15:26:42 +02:00
static void drop_cache( GBL gbl)
{
/**************************************
*
* d r o p _ c a c h e
*
**************************************
*
* Functional description
* Drop the database cache
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
USHORT found = FALSE;
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = (BLK) CMP_find_request(tdbb, drq_d_cache, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FILES WITH X.RDB$FILE_FLAGS EQ FILE_cache
ERASE X;
found = TRUE;
END_FOR;
2001-12-24 03:51:06 +01:00
if (!DYN_REQUEST(drq_d_cache)) {
2001-05-23 15:26:42 +02:00
DYN_REQUEST(drq_d_cache) = request;
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, drq_s_cache);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 63, NULL, NULL, NULL, NULL, NULL);
/* msg 63: ERASE RDB$FILE failed */
}
2001-05-23 15:26:42 +02:00
if (!found)
2001-12-24 03:51:06 +01:00
{
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 149, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 149: "Shared cache file not found" */
}
2001-05-23 15:26:42 +02:00
}
static void drop_log( GBL gbl)
{
/**************************************
*
* d r o p _ l o g
*
**************************************
*
* Functional description
* Delete all log files
*
**************************************/
TDBB tdbb;
DBB dbb;
BLK request;
USHORT found = FALSE;
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
request = (BLK) CMP_find_request(tdbb, drq_d_log, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$LOG_FILES
ERASE X;
found = TRUE;
END_FOR;
if (!DYN_REQUEST(drq_d_log))
DYN_REQUEST(drq_d_log) = request;
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_rundown_request(request, drq_d_log);
2001-12-24 03:51:06 +01:00
DYN_error_punt(TRUE, 153, NULL, NULL, NULL, NULL, NULL);
/* msg 153: ERASE RDB$LOG_FILE failed */
}
2001-05-23 15:26:42 +02:00
if (!found)
2001-12-24 03:51:06 +01:00
{
2001-05-23 15:26:42 +02:00
DYN_error_punt(FALSE, 152, NULL, NULL, NULL, NULL, NULL);
2001-12-24 03:51:06 +01:00
/* msg 152: "Write ahead log not found" */
}
2001-05-23 15:26:42 +02:00
}
static void modify_lfield_position(TDBB tdbb,
DBB dbb,
GBL gbl,
TEXT * relation_name,
TEXT * field_name,
USHORT new_position,
USHORT existing_position)
{
/***********************************************************
*
* m o d i f y _ l f i e l d _ p o s i t i o n
***********************************************************
*
* Functional Description:
* Alters the position of a field with respect to the
* other fields in the relation. This will only affect
* the order in which the fields will be returned when either
* viewing the relation or performing select * from the relation.
*
* The rules of engagement are as follows:
* if new_position > original position
* increase RDB$FIELD_POSITION for all fields with RDB$FIELD_POSITION
* between the new_position and existing position of the field
* then update the position of the field being altered.
* just update the position
*
* if new_position < original position
* decrease RDB$FIELD_POSITION for all fields with RDB$FIELD_POSITION
* between the new_position and existing position of the field
* then update the position of the field being altered.
*
* if new_position == original_position -- no_op
*
***********************************************************/
volatile BLK request = NULL;
2001-05-23 15:26:42 +02:00
USHORT new_pos = 0;
SLONG max_position = -1;
BOOLEAN move_down = FALSE;
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
/* Find the position of the last field in the relation */
DYN_UTIL_generate_field_position(tdbb, gbl, relation_name, &max_position);
/* if the existing position of the field is less than the new position of
* the field, subtract 1 to move the fields to their new positions otherwise,
* increase the value in RDB$FIELD_POSITION by one
*/
if (existing_position < new_position)
move_down = TRUE;
/* Retrieve the records for the fields which have a position between the
* existing field position and the new field position
*/
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$RELATION_FIELDS
WITH FLD.RDB$RELATION_NAME EQ relation_name AND
FLD.RDB$FIELD_POSITION >= MIN(new_position, existing_position) AND
FLD.RDB$FIELD_POSITION <= MAX(new_position, existing_position)
MODIFY FLD USING
/* If the field is the one we want, change the position, otherwise
* increase the value of RDB$FIELD_POSITION
*/
MET_exact_name(FLD.RDB$FIELD_NAME);
if (strcmp(FLD.RDB$FIELD_NAME, field_name) == 0) {
if (new_position > max_position)
/* This prevents gaps in the position sequence of the
* fields */
FLD.RDB$FIELD_POSITION = max_position;
else
FLD.RDB$FIELD_POSITION = new_position;
}
else {
if (move_down)
FLD.RDB$FIELD_POSITION = FLD.RDB$FIELD_POSITION - 1;
else
FLD.RDB$FIELD_POSITION = FLD.RDB$FIELD_POSITION + 1;
}
FLD.RDB$FIELD_POSITION.NULL = FALSE;
END_MODIFY;
END_FOR;
CMP_release(tdbb, (REQ)request);
request = NULL;
/* Once the field position has been changed, make sure that there are no
* duplicate field positions and no gaps in the position sequence (this can
* not be guaranteed by the query above */
new_pos = 0;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$RELATION_FIELDS WITH FLD.RDB$RELATION_NAME EQ relation_name
SORTED BY ASCENDING FLD.RDB$FIELD_POSITION
if (FLD.RDB$FIELD_POSITION != new_pos) {
MODIFY FLD USING
FLD.RDB$FIELD_POSITION = new_pos;
END_MODIFY;
}
new_pos += 1;
END_FOR;
CMP_release(tdbb, (REQ)request);
2001-12-24 03:51:06 +01:00
}
catch (...) {
DYN_error_punt(TRUE, 95, NULL, NULL, NULL, NULL, NULL);
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
}
2001-05-23 15:26:42 +02:00
}
static BOOLEAN check_view_dependency(TDBB tdbb,
DBB dbb,
GBL gbl,
TEXT * relation_name, TEXT * field_name)
{
/***********************************************************
*
* c h e c k _ v i e w _ d e p e n d e n c y
***********************************************************
*
* Functional Description:
* Checks to see if the given field is referenced in a view. If the field
* is referenced in a view, return TRUE, else return FALSE
*
***********************************************************/
BLK request = NULL;
BOOLEAN retval = FALSE;
TEXT *view_name;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIRST 1
X IN RDB$RELATION_FIELDS CROSS Y IN RDB$RELATION_FIELDS CROSS
Z IN RDB$VIEW_RELATIONS WITH
X.RDB$RELATION_NAME EQ relation_name AND
X.RDB$FIELD_NAME EQ field_name AND
X.RDB$FIELD_NAME EQ Y.RDB$BASE_FIELD AND
X.RDB$FIELD_SOURCE EQ 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
retval = TRUE;
view_name = Z.RDB$VIEW_NAME;
END_FOR;
CMP_release(tdbb, (REQ)request);
if (retval)
DYN_error_punt(FALSE, 206, field_name, relation_name, view_name, NULL,
NULL);
/* msg 206: Column %s from table %s is referenced in %s. */
return retval;
}
static BOOLEAN check_sptrig_dependency(TDBB tdbb,
DBB dbb,
GBL gbl,
TEXT * relation_name,
TEXT * field_name)
{
/***********************************************************
*
* c h e c k _ s p t r i g _ d e p e n d e n c y
***********************************************************
*
* Functional Description:
* Checks to see if the given field is referenced in a stored procedure
* or trigger. If the field is refereneced, return TRUE, else return
* FALSE
***********************************************************/
BLK request = NULL;
BOOLEAN retval = FALSE;
TEXT *dep_name;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIRST 1
DEP IN RDB$DEPENDENCIES WITH
DEP.RDB$DEPENDED_ON_NAME EQ relation_name AND
DEP.RDB$FIELD_NAME EQ field_name
retval = TRUE;
dep_name = DEP.RDB$DEPENDENT_NAME;
END_FOR;
CMP_release(tdbb, (REQ)request);
if (retval)
DYN_error_punt(FALSE, 206, field_name, relation_name, dep_name, NULL,
NULL);
/* msg 206: Column %s from table %s is referenced in %s. */
return retval;
}
static void modify_lfield_index(TDBB tdbb,
DBB dbb,
GBL gbl,
TEXT* relation_name,
TEXT* field_name,
TEXT* new_fld_name)
{
/***********************************************************
*
* m o d i f y _ l f i e l d _ i n d e x
***********************************************************
*
* Functional Description:
* Updates the field names in an index and forces the index to be rebuilt
* with the new field names
*
***********************************************************/
BLK request = NULL;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
IDX IN RDB$INDICES CROSS IDXS IN RDB$INDEX_SEGMENTS WITH
IDX.RDB$INDEX_NAME EQ IDXS.RDB$INDEX_NAME AND
IDX.RDB$RELATION_NAME EQ relation_name AND
IDXS.RDB$FIELD_NAME EQ field_name
/* Change the name of the field in the index */
MODIFY IDXS USING
MOVE_FASTER(new_fld_name, IDXS.RDB$FIELD_NAME,
sizeof(IDXS.RDB$FIELD_NAME));
END_MODIFY;
/* Set the index name to itself to tell the index to rebuild */
MODIFY IDX USING
MOVE_FASTER(IDX.RDB$INDEX_NAME, IDX.RDB$INDEX_NAME,
sizeof(IDX.RDB$INDEX_NAME));
END_MODIFY;
END_FOR;
CMP_release(tdbb, (REQ)request);
}
static BOOLEAN field_exists(TDBB tdbb,
DBB dbb,
GBL gbl, TEXT * relation_name, TEXT * field_name)
{
/***********************************************************
*
* f i e l d _ e x i s t s
***********************************************************
*
* Functional Description:
* Checks to see if the given field already exists in a relation
***********************************************************/
BLK request = NULL;
BOOLEAN retval = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$RELATION_FIELDS WITH
FLD.RDB$RELATION_NAME EQ relation_name AND
FLD.RDB$FIELD_NAME EQ field_name
retval = TRUE;
END_FOR;
CMP_release(tdbb, (REQ)request);
return retval;
}
static BOOLEAN domain_exists(TDBB tdbb, DBB dbb, GBL gbl, TEXT * field_name)
{
/***********************************************************
*
* d o m a i n _ e x i s t s
***********************************************************
*
* Functional Description:
* Checks to see if the given field already exists in a relation
***********************************************************/
BLK request = NULL;
BOOLEAN retval = FALSE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ field_name
retval = TRUE;
END_FOR;
CMP_release(tdbb, (REQ)request);
return retval;
}
void DYN_modify_sql_field(GBL gbl,
UCHAR** ptr,
TEXT* relation_name,
TEXT* field_name)
{
/**************************************
*
2002-06-30 10:46:51 +02:00
* D Y N _ m o d i f y _ s q l _ f i e l d
2001-05-23 15:26:42 +02:00
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement
* to modify the datatype of a field.
*
* If there are dependencies on the field, abort the operation
* unless the dependency is an index. In this case, rebuild the
* index once the operation has completed.
*
* If the original datatype of the field was a domain:
* if the new type is a domain, just make the change to the new domain
* if it exists
*
* if the new type is a base type, just make the change
*
* If the original datatype of the field was a base type:
* if the new type is a base type, just make the change
*
* if the new type is a domain, make the change to the field
* definition and remove the entry for RDB$FIELD_SOURCE from the original
* field. In other words ... clean up after ourselves
*
* The following conversions are not allowed:
* Blob to anything
* Array to anything
* Date to anything
* Char to any numeric
* Varchar to any numeric
* Anything to Blob
* Anything to Array
*
* The following operations return a warning
* Decreasing the length of a char (varchar) field
*
2002-06-30 10:46:51 +02:00
* CVC: This is a misleading comment. There's no code that
* produces a warning. This condition raises an error, too.
*
2001-05-23 15:26:42 +02:00
**************************************/
TDBB tdbb;
DBB dbb;
BLK request = NULL, first_request;
UCHAR verb;
BOOLEAN found = FALSE, update_domain = FALSE;
BOOLEAN dtype, scale, prec, subtype, charlen, collation, fldlen, nullflg,
charset;
DYN_FLD orig_fld, new_fld, dom_fld;
2002-06-30 10:46:51 +02:00
BOOLEAN has_dimensions = FALSE;
SSHORT field_adjusted_count = 0;
TEXT *err_one_type_change_only = "Only one data type change to the field allowed at a time";
2001-05-23 15:26:42 +02:00
tdbb = GET_THREAD_DATA;
dbb = tdbb->tdbb_database;
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
dtype = scale = prec = subtype = charlen = collation = fldlen = nullflg =
charset = FALSE;
/* Allocate the field structures */
orig_fld = (DYN_FLD) gds__alloc(sizeof(struct dyn_fld));
if (!orig_fld)
DYN_error_punt(FALSE, 211, NULL, NULL, NULL, NULL, NULL);
MOVE_CLEAR(orig_fld, sizeof(struct dyn_fld));
new_fld = (DYN_FLD) gds__alloc(sizeof(struct dyn_fld));
if (!new_fld)
DYN_error_punt(FALSE, 211, NULL, NULL, NULL, NULL, NULL);
MOVE_CLEAR(new_fld, sizeof(struct dyn_fld));
dom_fld = (DYN_FLD) gds__alloc(sizeof(struct dyn_fld));
if (!dom_fld)
DYN_error_punt(FALSE, 211, NULL, NULL, NULL, NULL, NULL);
MOVE_CLEAR(dom_fld, sizeof(struct dyn_fld));
GET_STRING(ptr, orig_fld->dyn_fld_name);
/* check to see if the field being altered is involved in any type of dependency.
* If there is a dependency, call DYN_error_punt (inside the function).
*/
check_sptrig_dependency(tdbb, dbb, gbl, relation_name,
orig_fld->dyn_fld_name);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
RFR IN RDB$RELATION_FIELDS WITH RFR.RDB$RELATION_NAME = relation_name
AND RFR.RDB$FIELD_NAME = orig_fld->dyn_fld_name
first_request = request;
request = NULL;
found = TRUE;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME = RFR.RDB$FIELD_SOURCE
/* Get information about the original field type. If a conversion
* can not be at any time made between
* the two datatypes, error.
*/
DSC_make_descriptor(&orig_fld->dyn_dsc,
FLD.RDB$FIELD_TYPE,
FLD.RDB$FIELD_SCALE,
FLD.RDB$FIELD_LENGTH,
FLD.RDB$FIELD_SUB_TYPE,
FLD.RDB$CHARACTER_SET_ID,
FLD.RDB$COLLATION_ID);
2002-06-30 10:46:51 +02:00
orig_fld->dyn_charbytelen = FLD.RDB$FIELD_LENGTH;
2001-05-23 15:26:42 +02:00
orig_fld->dyn_dtype = FLD.RDB$FIELD_TYPE;
orig_fld->dyn_precision = FLD.RDB$FIELD_PRECISION;
orig_fld->dyn_charlen = FLD.RDB$CHARACTER_LENGTH;
orig_fld->dyn_collation = FLD.RDB$COLLATION_ID;
orig_fld->dyn_null_flag = FLD.RDB$NULL_FLAG;
strcpy(orig_fld->dyn_fld_source, RFR.RDB$FIELD_SOURCE);
/* If the original field type is an array, force its blr type to blr_blob */
if (FLD.RDB$DIMENSIONS != 0)
2002-06-30 10:46:51 +02:00
{
2001-05-23 15:26:42 +02:00
orig_fld->dyn_dtype = blr_blob;
2002-06-30 10:46:51 +02:00
has_dimensions = TRUE;
}
2001-05-23 15:26:42 +02:00
while ((verb = *(*ptr)++) != gds_dyn_end) {
2001-05-23 15:26:42 +02:00
switch (verb) {
case gds_dyn_fld_source:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, dom_fld->dyn_fld_source);
get_domain_type(tdbb, dbb, gbl, dom_fld);
update_domain = TRUE;
break;
case gds_dyn_rel_name:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, new_fld->dyn_rel_name);
break;
case gds_dyn_fld_length:
2001-05-23 15:26:42 +02:00
fldlen = TRUE;
new_fld->dyn_dsc.dsc_length = DYN_get_number(ptr);
2002-06-30 10:46:51 +02:00
if (++field_adjusted_count > 2)
DYN_error_punt(FALSE, 5, err_one_type_change_only, NULL, NULL, NULL, NULL);
switch (new_fld->dyn_dtype)
{
case blr_text:
case blr_text2:
case blr_varying:
case blr_varying2:
case blr_cstring:
case blr_cstring2:
new_fld->dyn_charbytelen = new_fld->dyn_dsc.dsc_length;
break;
default:
new_fld->dyn_charbytelen = 0; /* It won't be used, anyway. */
break;
}
2001-05-23 15:26:42 +02:00
break;
case gds_dyn_fld_type:
2001-05-23 15:26:42 +02:00
dtype = TRUE;
new_fld->dyn_dtype = DYN_get_number(ptr);
2002-06-30 10:46:51 +02:00
if (++field_adjusted_count > 2)
DYN_error_punt(FALSE, 5, err_one_type_change_only, NULL, NULL, NULL, NULL);
2001-05-23 15:26:42 +02:00
switch (new_fld->dyn_dtype) {
case blr_text:
case blr_text2:
case blr_varying:
case blr_varying2:
case blr_cstring:
case blr_cstring2:
2002-06-30 10:46:51 +02:00
if (new_fld->dyn_dsc.dsc_length && !new_fld->dyn_charbytelen)
new_fld->dyn_charbytelen = new_fld->dyn_dsc.dsc_length;
new_fld->dyn_dsc.dsc_length = DSC_string_length (&new_fld->dyn_dsc);
2001-05-23 15:26:42 +02:00
break;
case blr_short:
new_fld->dyn_dsc.dsc_length = 2;
break;
case blr_long:
case blr_float:
new_fld->dyn_dsc.dsc_length = 4;
break;
case blr_int64:
case blr_sql_time:
case blr_sql_date:
case blr_timestamp:
case blr_double:
case blr_d_float:
new_fld->dyn_dsc.dsc_length = 8;
break;
default:
break;
}
break;
case gds_dyn_fld_scale:
2001-05-23 15:26:42 +02:00
scale = TRUE;
new_fld->dyn_dsc.dsc_scale = DYN_get_number(ptr);
break;
case isc_dyn_fld_precision:
prec = TRUE;
new_fld->dyn_precision = DYN_get_number(ptr);
break;
case gds_dyn_fld_sub_type:
2001-05-23 15:26:42 +02:00
subtype = TRUE;
new_fld->dyn_dsc.dsc_sub_type = DYN_get_number(ptr);
break;
case gds_dyn_fld_char_length:
2001-05-23 15:26:42 +02:00
charlen = TRUE;
new_fld->dyn_charlen = DYN_get_number(ptr);
break;
case gds_dyn_fld_collation:
2001-05-23 15:26:42 +02:00
collation = TRUE;
new_fld->dyn_collation = DYN_get_number(ptr);
break;
case gds_dyn_fld_character_set:
2001-05-23 15:26:42 +02:00
charset = TRUE;
new_fld->dyn_charset = DYN_get_number(ptr);
break;
case gds_dyn_fld_not_null:
2001-05-23 15:26:42 +02:00
nullflg = TRUE;
new_fld->dyn_null_flag = TRUE;
break;
case gds_dyn_fld_dimensions:
2001-05-23 15:26:42 +02:00
new_fld->dyn_dtype = blr_blob;
break;
/* These should only be defined for BLOB types and should not come through with
* any other types. BLOB types are detected above
*/
case gds_dyn_fld_segment_length:
2001-05-23 15:26:42 +02:00
DYN_get_number(ptr);
break;
default:
--(*ptr);
DYN_execute(gbl, ptr, relation_name, RFR.RDB$FIELD_SOURCE,
(TEXT*)NULL_PTR, (TEXT*)NULL_PTR, (TEXT*)NULL_PTR);
2001-05-23 15:26:42 +02:00
}
}
END_FOR; /* FLD in RDB$FIELDS */
CMP_release(tdbb, (REQ)request);
request = NULL;
/* Now that we have all of the information needed, let's check to see if the field type can be modifed */
if (update_domain) {
ULONG retval;
2002-06-30 10:46:51 +02:00
/* CVC: Since get_domain_type() called above already called DSC_make_descriptor,
there's no point in calling it again, since it will increment AGAIN the length
of varchar fields! This bug detected thanks to new check field dyn_charbytelen.
2001-05-23 15:26:42 +02:00
DSC_make_descriptor(&dom_fld->dyn_dsc,
dom_fld->dyn_dtype,
dom_fld->dyn_dsc.dsc_scale,
dom_fld->dyn_dsc.dsc_length,
dom_fld->dyn_dsc.dsc_sub_type,
dom_fld->dyn_charset, dom_fld->dyn_collation);
2002-06-30 10:46:51 +02:00
*/
2001-05-23 15:26:42 +02:00
if ((retval = check_update_fld_type(orig_fld, dom_fld)) !=
SUCCESS) modify_err_punt(tdbb, retval, orig_fld, dom_fld);
/* if the original definition was a base field type, remove the entries from RDB$FIELDS */
if (!strncmp(orig_fld->dyn_fld_source, "RDB$", 4)) {
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME =
RFR.RDB$FIELD_SOURCE
ERASE FLD;
END_FOR;
CMP_release(tdbb, (REQ)request);
request = NULL;
}
request = first_request;
MODIFY RFR USING
strcpy(RFR.RDB$FIELD_SOURCE, dom_fld->dyn_fld_source);
RFR.RDB$FIELD_SOURCE.NULL = FALSE;
END_MODIFY;
first_request = request;
}
else {
ULONG retval;
DSC_make_descriptor(&new_fld->dyn_dsc,
new_fld->dyn_dtype,
new_fld->dyn_dsc.dsc_scale,
new_fld->dyn_dsc.dsc_length,
new_fld->dyn_dsc.dsc_sub_type,
new_fld->dyn_charset, new_fld->dyn_collation);
if ((retval = check_update_fld_type(orig_fld, new_fld)) !=
SUCCESS) modify_err_punt(tdbb, retval, orig_fld, new_fld);
/* check to see if the original data type for the field was based on a domain. If it
* was (and now it isn't), remove the domain information and replace it with a generated
* field name for RDB$FIELDS
*/
if (strncmp(orig_fld->dyn_fld_source, "RDB$", 4)) {
request = first_request;
MODIFY RFR USING
DYN_UTIL_generate_field_name(tdbb, gbl,
RFR.RDB$FIELD_SOURCE);
strcpy(new_fld->dyn_fld_name, RFR.RDB$FIELD_SOURCE);
END_MODIFY;
first_request = request;
request = NULL;
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS
FLD.RDB$SYSTEM_FLAG.NULL = TRUE;
FLD.RDB$FIELD_SCALE.NULL = TRUE;
FLD.RDB$FIELD_PRECISION.NULL = TRUE;
FLD.RDB$FIELD_SUB_TYPE.NULL = TRUE;
FLD.RDB$SEGMENT_LENGTH.NULL = TRUE;
FLD.RDB$COMPUTED_BLR.NULL = TRUE;
FLD.RDB$COMPUTED_SOURCE.NULL = TRUE;
FLD.RDB$DEFAULT_VALUE.NULL = TRUE;
FLD.RDB$DEFAULT_SOURCE.NULL = TRUE;
FLD.RDB$VALIDATION_BLR.NULL = TRUE;
FLD.RDB$VALIDATION_SOURCE.NULL = TRUE;
FLD.RDB$NULL_FLAG.NULL = TRUE;
FLD.RDB$EDIT_STRING.NULL = TRUE;
FLD.RDB$DIMENSIONS.NULL = TRUE;
FLD.RDB$CHARACTER_LENGTH.NULL = TRUE;
FLD.RDB$CHARACTER_SET_ID.NULL = TRUE;
FLD.RDB$COLLATION_ID.NULL = TRUE;
if (dtype) {
FLD.RDB$FIELD_TYPE = new_fld->dyn_dtype;
FLD.RDB$FIELD_TYPE.NULL = FALSE;
}
if (scale) {
FLD.RDB$FIELD_SCALE = new_fld->dyn_dsc.dsc_scale;
FLD.RDB$FIELD_SCALE.NULL = FALSE;
}
if (prec) {
FLD.RDB$FIELD_PRECISION = new_fld->dyn_precision;
FLD.RDB$FIELD_PRECISION.NULL = FALSE;
}
if (subtype) {
FLD.RDB$FIELD_SUB_TYPE =
new_fld->dyn_dsc.dsc_sub_type;
FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
}
if (charlen) {
FLD.RDB$CHARACTER_LENGTH = new_fld->dyn_charlen;
FLD.RDB$CHARACTER_LENGTH.NULL = FALSE;
}
if (fldlen) {
2002-06-30 10:46:51 +02:00
/* CVC: Rescue from the wrong field_length with a helper. */
if (new_fld->dyn_dsc.dsc_dtype <= dtype_varying && new_fld->dyn_charbytelen)
FLD.RDB$FIELD_LENGTH = new_fld->dyn_charbytelen;
else
FLD.RDB$FIELD_LENGTH = new_fld->dyn_dsc.dsc_length;
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_LENGTH.NULL = FALSE;
}
/* Copy the field name into RDB$FIELDS */
strcpy(FLD.RDB$FIELD_NAME, new_fld->dyn_fld_name);
END_STORE;
CMP_release(tdbb, (REQ)request);
request = NULL;
}
else { /* the original and new definitions are both base types */
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME = RFR.RDB$FIELD_SOURCE
MODIFY FLD USING
if (dtype) {
FLD.RDB$FIELD_TYPE = new_fld->dyn_dtype;
FLD.RDB$FIELD_TYPE.NULL = FALSE;
}
if (scale) {
FLD.RDB$FIELD_SCALE = new_fld->dyn_dsc.dsc_scale;
FLD.RDB$FIELD_SCALE.NULL = FALSE;
}
if (prec) {
FLD.RDB$FIELD_PRECISION = new_fld->dyn_precision;
FLD.RDB$FIELD_PRECISION.NULL = FALSE;
}
if (subtype) {
FLD.RDB$FIELD_SUB_TYPE =
new_fld->dyn_dsc.dsc_sub_type;
FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
}
if (charlen) {
FLD.RDB$CHARACTER_LENGTH = new_fld->dyn_charlen;
FLD.RDB$CHARACTER_LENGTH.NULL = FALSE;
}
if (fldlen) {
2002-06-30 10:46:51 +02:00
/* CVC: Rescue from the wrong field_length with a helper. */
if (new_fld->dyn_dsc.dsc_dtype <= dtype_varying && new_fld->dyn_charbytelen)
FLD.RDB$FIELD_LENGTH = new_fld->dyn_charbytelen;
else
FLD.RDB$FIELD_LENGTH = new_fld->dyn_dsc.dsc_length;
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_LENGTH.NULL = FALSE;
}
END_MODIFY;
END_FOR; /* FLD in RDB$FIELDS */
CMP_release(tdbb, (REQ)request);
request = NULL;
}
} /* else not a domain */
request = first_request;
END_FOR; /* RFR IN RDB$RELATION_FIELDS */
CMP_release(tdbb, (REQ)request);
request = NULL;
if (!found)
DYN_error_punt(FALSE, 96, NULL, NULL, NULL, NULL, NULL);
/* msg 96: "Local column not found" */
/* Update any indicies that exist */
modify_lfield_index(tdbb, dbb, gbl, relation_name, orig_fld->dyn_fld_name,
orig_fld->dyn_fld_name);
if (new_fld)
gds__free((SLONG *) new_fld);
if (dom_fld)
gds__free((SLONG *) dom_fld);
if (orig_fld)
gds__free((SLONG *) orig_fld);
2001-12-24 03:51:06 +01:00
}
catch (...) {
if (new_fld) {
gds__free((SLONG *) new_fld);
}
if (dom_fld) {
gds__free((SLONG *) dom_fld);
}
if (orig_fld) {
gds__free((SLONG *) orig_fld);
}
DYN_error_punt(TRUE, 95, NULL, NULL, NULL, NULL, NULL);
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
}
2001-05-23 15:26:42 +02:00
}
void get_domain_type(TDBB tdbb, DBB dbb, GBL gbl, DYN_FLD dom_fld)
{
/**************************************
*
* g e t _ d o m a i n _ t y p e
*
**************************************
*
* Functional description
* Retrives the type information for a domain so
* that it can be compared to a local field before
* modifying the datatype of a field.
*
**************************************/
BLK request = NULL;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ dom_fld->dyn_fld_source;
DSC_make_descriptor(&dom_fld->dyn_dsc,
FLD.RDB$FIELD_TYPE,
FLD.RDB$FIELD_SCALE,
FLD.RDB$FIELD_LENGTH,
FLD.RDB$FIELD_SUB_TYPE,
FLD.RDB$CHARACTER_SET_ID, FLD.RDB$COLLATION_ID);
2002-06-30 10:46:51 +02:00
dom_fld->dyn_charbytelen = FLD.RDB$FIELD_LENGTH;
2001-05-23 15:26:42 +02:00
dom_fld->dyn_dtype = FLD.RDB$FIELD_TYPE;
dom_fld->dyn_precision = FLD.RDB$FIELD_PRECISION;
dom_fld->dyn_charlen = FLD.RDB$CHARACTER_LENGTH;
dom_fld->dyn_collation = FLD.RDB$COLLATION_ID;
dom_fld->dyn_null_flag = FLD.RDB$NULL_FLAG;
END_FOR;
CMP_release(tdbb, (REQ)request);
}
static ULONG check_update_fld_type(DYN_FLD orig_fld, DYN_FLD new_fld)
{
/**************************************
*
* c h e c k _ u p d a t e _ f l d _ t y p e
*
**************************************
*
* Functional description
* Compare the original field type with the new field type to
* determine if the original type can be changed to the new type
*
* The following conversions are not allowed:
* Blob to anything
* Array to anything
* Date to anything
* Char to any numeric
* Varchar to any numeric
* Anything to Blob
* Anything to Array
*
* This function returns an error code if the conversion can not be
* made. If the conversion can be made, SUCCESS is returned
**************************************/
/* Check to make sure that the old and new types are compatible */
switch (orig_fld->dyn_dtype) {
/* CHARACTER types */
case blr_text:
case blr_varying:
case blr_cstring:
switch (new_fld->dyn_dtype) {
case blr_blob:
case blr_blob_id:
return isc_dyn_dtype_invalid;
/* Cannot change datatype for column %s.
The operation cannot be performed on BLOB, or ARRAY columns. */
break;
case blr_sql_date:
case blr_sql_time:
case blr_timestamp:
case blr_int64:
case blr_long:
case blr_short:
case blr_d_float:
case blr_double:
case blr_float:
return isc_dyn_dtype_conv_invalid;
/* Cannot convert column %s from character to non-character data. */
break;
/* If the original field is a character field and the new field is a character field,
* is there enough space in the new field? */
case blr_text:
case blr_varying:
case blr_cstring:
{
USHORT maxflen = 0;
2002-06-30 10:46:51 +02:00
/* CVC: Because our caller invoked DSC_make_descriptor() on new_fld previously,
we should have the added bytes for varchar. For cstring, we are used, since
DSC_make_descriptor(DSC_string_length) != DSC_string_length(DSC_make_descriptor). */
2001-05-23 15:26:42 +02:00
maxflen = DSC_string_length(&orig_fld->dyn_dsc);
2002-06-30 10:46:51 +02:00
/* We can have this assertion since this case is for both string fields. */
assert(DSC_string_length(&new_fld->dyn_dsc) - maxflen
== new_fld->dyn_charbytelen - orig_fld->dyn_charbytelen);
/* if (new_fld->dyn_dsc.dsc_length < maxflen) */
if (DSC_string_length(&new_fld->dyn_dsc) < maxflen)
2001-05-23 15:26:42 +02:00
return isc_dyn_char_fld_too_small;
/* New size specified for column %s must be greater than %d characters. */
}
break;
default:
assert(FALSE);
return 87; /* MODIFY RDB$FIELDS FAILED */
}
break;
/* BLOB and ARRAY types */
case blr_blob:
case blr_blob_id:
return isc_dyn_dtype_invalid;
/* Cannot change datatype for column %s.
The operation cannot be performed on BLOB, or ARRAY columns. */
break;
/* DATE types */
case blr_sql_date:
case blr_sql_time:
case blr_timestamp:
switch (new_fld->dyn_dtype) {
case blr_sql_date:
if (orig_fld->dyn_dtype == blr_sql_time)
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
break;
case blr_sql_time:
if (orig_fld->dyn_dtype == blr_sql_date)
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
break;
case blr_timestamp:
if (orig_fld->dyn_dtype == blr_sql_time)
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
break;
/* If the original field is a date field and the new field is a character field,
* is there enough space in the new field? */
case blr_text:
case blr_text2:
case blr_varying:
case blr_varying2:
case blr_cstring:
case blr_cstring2:
{
USHORT maxflen = 0;
maxflen = DSC_string_length(&orig_fld->dyn_dsc);
if (new_fld->dyn_dsc.dsc_length < maxflen)
return isc_dyn_char_fld_too_small;
/* New size specified for column %s must be greater than %d characters. */
}
break;
default:
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
}
break;
/* NUMERIC types */
case blr_int64:
case blr_long:
case blr_short:
case blr_d_float:
case blr_double:
case blr_float:
switch (new_fld->dyn_dtype) {
case blr_blob:
case blr_blob_id:
return isc_dyn_dtype_invalid;
/* Cannot change datatype for column %s.
The operation cannot be performed on BLOB, or ARRAY columns. */
break;
case blr_sql_date:
case blr_sql_time:
case blr_timestamp:
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
/* If the original field is a numeric field and the new field is a numeric field,
* is there enough space in the new field (do not allow the base type to decrease) */
case blr_short:
switch (orig_fld->dyn_dtype) {
case blr_short:
break;
default:
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
}
break;
case blr_long:
switch (orig_fld->dyn_dtype) {
case blr_long:
case blr_short:
break;
default:
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
}
break;
case blr_float:
switch (orig_fld->dyn_dtype) {
case blr_float:
case blr_short:
break;
default:
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
}
break;
case blr_int64:
switch (orig_fld->dyn_dtype) {
case blr_int64:
case blr_long:
case blr_short:
break;
default:
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
}
break;
case blr_d_float:
case blr_double:
switch (orig_fld->dyn_dtype) {
case blr_double:
case blr_d_float:
case blr_float:
case blr_short:
case blr_long:
break;
default:
return isc_dyn_invalid_dtype_conversion;
/* Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. */
}
break;
/* If the original field is a numeric field and the new field is a character field,
* is there enough space in the new field? */
case blr_text:
case blr_varying:
case blr_cstring:
{
USHORT maxflen = 0;
maxflen = DSC_string_length(&orig_fld->dyn_dsc);
if (new_fld->dyn_dsc.dsc_length < maxflen)
return isc_dyn_char_fld_too_small;
/* New size specified for column %s must be greater than %d characters. */
}
break;
default:
assert(FALSE);
return 87; /* MODIFY RDB$FIELDS FAILED */
}
break;
default:
assert(FALSE);
return 87; /* MODIFY RDB$FIELDS FAILED */
}
return SUCCESS;
}
static void modify_err_punt(TDBB tdbb,
ULONG errorcode,
DYN_FLD orig_fld_def, DYN_FLD new_fld_def)
{
/**************************************
*
* m o d i f y _ e r r _ p u n t
*
**************************************
*
* Functional description
* A generic error routine that calls DYN_error_punt
* based on the error code returned by check_update_field_type.
*
* This function is called by DYN_modify_global_field and by
* DYN_modify_sql_field
**************************************/
switch (errorcode) {
case isc_dyn_dtype_invalid:
DYN_error_punt(FALSE, 207, orig_fld_def->dyn_fld_name, NULL, NULL,
NULL, NULL);
/* Cannot change datatype for column %s.The operation cannot be performed on DATE, BLOB, or ARRAY columns. */
break;
case isc_dyn_dtype_conv_invalid:
DYN_error_punt(FALSE, 210, orig_fld_def->dyn_fld_name, NULL, NULL,
NULL, NULL);
/* Cannot convert column %s from character to non-character data. */
break;
case isc_dyn_char_fld_too_small:
/* TMN: Bad, bad, bad cast. int -> TEXT* */
DYN_error_punt(FALSE,
208,
orig_fld_def->dyn_fld_name,
(TEXT*)DSC_string_length(&orig_fld_def->dyn_dsc),
NULL,
NULL,
NULL);
/* msg 208: New size specified for column %s must be greater than %d characters. */
break;
case isc_dyn_invalid_dtype_conversion:
{
TEXT orig_type[25], new_type[25];
DSC_get_dtype_name(&orig_fld_def->dyn_dsc, orig_type,
sizeof(orig_type));
DSC_get_dtype_name(&new_fld_def->dyn_dsc, new_type,
sizeof(new_type));
DYN_error_punt(FALSE, 209, orig_fld_def->dyn_fld_name, orig_type,
new_type, NULL, NULL);
/* Cannot convert base type %s to base type %s. */
break;
}
default:
DYN_error_punt(TRUE, 95, NULL, NULL, NULL, NULL, NULL);
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
}
}