mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-27 04:43:02 +01:00
2843 lines
74 KiB
Plaintext
2843 lines
74 KiB
Plaintext
|
/*
|
||
|
* 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,
|
||
|
* if it has dimensions, rdb$field_dimensions should be updated, too.
|
||
|
*/
|
||
|
|
||
|
#include "../jrd/ib_stdio.h"
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "../jrd/ibsetjmp.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 "../include/jrd/gds.h"
|
||
|
#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_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/thd_proto.h"
|
||
|
#include "../jrd/vio_proto.h"
|
||
|
#include "../jrd/dsc_proto.h"
|
||
|
#ifndef WINDOWS_ONLY
|
||
|
#include "../jrd/ail.h"
|
||
|
#endif
|
||
|
|
||
|
#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 };
|
||
|
static void drop_cache(GBL);
|
||
|
static void drop_log(GBL);
|
||
|
static void modify_lfield_type(GBL, UCHAR **, TEXT *, TEXT *);
|
||
|
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];
|
||
|
JMP_BUF env, *old_env;
|
||
|
#ifndef WINDOWS_ONLY
|
||
|
SSHORT num_log_buffers = 0;
|
||
|
USHORT log_buffer_size = 0;
|
||
|
SLONG check_point_len = 0, group_commit_wait = -1;
|
||
|
SSHORT log_params_defined = FALSE;
|
||
|
#endif
|
||
|
#ifdef SUPERSERVER
|
||
|
USHORT first_log_file = TRUE;
|
||
|
#endif
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = NULL;
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 84, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 84: "MODIFY DATABASE failed" */
|
||
|
}
|
||
|
|
||
|
INF_database_info(alloc_info, sizeof(alloc_info), s, sizeof(s));
|
||
|
|
||
|
if (s[0] != gds__info_allocation) {
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
DYN_error_punt(TRUE, 84, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 84: "MODIFY DATABASE failed" */
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
switch (verb) {
|
||
|
case gds__dyn_security_class:
|
||
|
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:
|
||
|
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:
|
||
|
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:
|
||
|
DYN_define_file(gbl, ptr, (SLONG) 0, &start, 158);
|
||
|
break;
|
||
|
|
||
|
#ifdef SUPERSERVER
|
||
|
case gds__dyn_def_default_log:
|
||
|
DYN_define_log_file(gbl, ptr, first_log_file, TRUE);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_def_log_file:
|
||
|
DYN_define_log_file(gbl, ptr, first_log_file, FALSE);
|
||
|
first_log_file = FALSE;
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case gds__dyn_def_cache_file:
|
||
|
DYN_define_cache(gbl, ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_log_group_commit_wait:
|
||
|
#ifndef WINDOWS_ONLY
|
||
|
group_commit_wait = DYN_get_number(ptr);
|
||
|
log_params_defined = TRUE;
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_log_buffer_size:
|
||
|
#ifndef WINDOWS_ONLY
|
||
|
log_buffer_size = DYN_get_number(ptr);
|
||
|
log_params_defined = TRUE;
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_log_check_point_length:
|
||
|
#ifndef WINDOWS_ONLY
|
||
|
check_point_len = DYN_get_number(ptr);
|
||
|
log_params_defined = TRUE;
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_log_num_of_buffers:
|
||
|
#ifndef WINDOWS_ONLY
|
||
|
num_log_buffers = DYN_get_number(ptr);
|
||
|
log_params_defined = TRUE;
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_drop_cache:
|
||
|
drop_cache(gbl);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_drop_log:
|
||
|
drop_log(gbl);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_character_set_name:
|
||
|
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, NULL_PTR, NULL_PTR,
|
||
|
NULL_PTR, NULL_PTR, NULL_PTR);
|
||
|
}
|
||
|
END_MODIFY;
|
||
|
END_FOR;
|
||
|
|
||
|
#ifndef WINDOWS_ONLY
|
||
|
if (log_params_defined)
|
||
|
AIL_set_log_options(check_point_len, num_log_buffers, log_buffer_size,
|
||
|
group_commit_wait);
|
||
|
#endif
|
||
|
|
||
|
if (!DYN_REQUEST(drq_m_database))
|
||
|
DYN_REQUEST(drq_m_database) = request;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
}
|
||
|
|
||
|
|
||
|
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];
|
||
|
JMP_BUF env, *old_env;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_m_xcp, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 145, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 145: "MODIFY EXCEPTION failed" */
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
switch (verb) {
|
||
|
case gds__dyn_xcp_msg:
|
||
|
GET_STRING(ptr, X.RDB$MESSAGE);
|
||
|
X.RDB$MESSAGE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_xcp_msg2:
|
||
|
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;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 144, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 144: "Exception not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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;
|
||
|
JMP_BUF env, *old_env;
|
||
|
DYN_FLD orig_dom, new_dom;
|
||
|
BOOLEAN dtype, scale, prec, subtype, charlen, collation, fldlen, nullflg,
|
||
|
charset;
|
||
|
TEXT *qryname, *qryhdr, *qryhdr2, *edtstr, *edtstr2, *missingval,
|
||
|
*singvald, *fldvald, *fldvaldsrc, *fldvaldsrc2, *desc, *desc2,
|
||
|
*delvald, *deldflt, *flddftval, *flddfltsrc;
|
||
|
|
||
|
BOOLEAN bqryname, bqryhdr, bqryhdr2, bedtstr, bedtstr2, bmissingval,
|
||
|
bsingvald, bfldvald, bfldvaldsrc, bfldvaldsrc2, bdesc, bdesc2,
|
||
|
bdelvald, bdeldflt, bflddftval, bflddfltsrc;
|
||
|
BOOLEAN has_dimensions = FALSE;
|
||
|
|
||
|
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);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
if (orig_dom)
|
||
|
gds__free((SLONG *) orig_dom);
|
||
|
|
||
|
if (new_dom)
|
||
|
gds__free((SLONG *) new_dom);
|
||
|
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 87, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 87: "MODIFY RDB$FIELDS failed" */
|
||
|
}
|
||
|
|
||
|
/* Allocate the field structures */
|
||
|
orig_dom = (DYN_FLD) gds__alloc(sizeof(struct dyn_fld));
|
||
|
if (!orig_dom)
|
||
|
DYN_error_punt(TRUE, 211, NULL, NULL, NULL, NULL, NULL);
|
||
|
|
||
|
MOVE_CLEAR(orig_dom, sizeof(struct dyn_fld));
|
||
|
|
||
|
new_dom = (DYN_FLD) gds__alloc(sizeof(struct dyn_fld));
|
||
|
if (!new_dom)
|
||
|
DYN_error_punt(TRUE, 211, NULL, NULL, NULL, NULL, NULL);
|
||
|
|
||
|
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);
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
switch (verb)
|
||
|
{
|
||
|
case gds__dyn_fld_name:
|
||
|
{
|
||
|
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, request);
|
||
|
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. */
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case gds__dyn_rel_name:
|
||
|
GET_STRING(ptr, new_dom->dyn_rel_name);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_length:
|
||
|
fldlen = TRUE;
|
||
|
new_dom->dyn_dsc.dsc_length = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_type:
|
||
|
dtype = TRUE;
|
||
|
new_dom->dyn_dtype = DYN_get_number(ptr);
|
||
|
|
||
|
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_dsc.dsc_length =
|
||
|
DSC_string_length(&new_dom->dyn_dsc);
|
||
|
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:
|
||
|
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:
|
||
|
subtype = TRUE;
|
||
|
new_dom->dyn_dsc.dsc_sub_type = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_char_length:
|
||
|
charlen = TRUE;
|
||
|
new_dom->dyn_charlen = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_collation:
|
||
|
collation = TRUE;
|
||
|
new_dom->dyn_collation = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_character_set:
|
||
|
charset = TRUE;
|
||
|
new_dom->dyn_charset = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_not_null:
|
||
|
nullflg = TRUE;
|
||
|
new_dom->dyn_null_flag = TRUE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_query_name:
|
||
|
qryname = (TEXT *) * ptr;
|
||
|
bqryname = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_query_header:
|
||
|
qryhdr = (TEXT *) * ptr;
|
||
|
bqryhdr = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_fld_query_header2:
|
||
|
qryhdr2 = (TEXT *) * ptr;
|
||
|
bqryhdr2 = TRUE;
|
||
|
DYN_skip_attribute2(ptr);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case gds__dyn_fld_edit_string:
|
||
|
edtstr = (TEXT *) * ptr;
|
||
|
bedtstr = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_fld_edit_string2:
|
||
|
edtstr2 = (TEXT *) * ptr;
|
||
|
bedtstr2 = TRUE;
|
||
|
DYN_skip_attribute2(ptr);
|
||
|
break;
|
||
|
#endif
|
||
|
case gds__dyn_fld_missing_value:
|
||
|
missingval = (TEXT *) * ptr;
|
||
|
bmissingval = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_single_validation:
|
||
|
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:
|
||
|
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:
|
||
|
fldvaldsrc = (TEXT *) * ptr;
|
||
|
bfldvaldsrc = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_fld_validation_source2:
|
||
|
fldvaldsrc2 = (TEXT *) * ptr;
|
||
|
bfldvaldsrc2 = TRUE;
|
||
|
DYN_skip_attribute2(ptr);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case gds__dyn_description:
|
||
|
desc = (TEXT *) * ptr;
|
||
|
bdesc = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_description2:
|
||
|
desc2 = (TEXT *) * ptr;
|
||
|
bdesc2 = TRUE;
|
||
|
DYN_skip_attribute2(ptr);
|
||
|
break;
|
||
|
#endif
|
||
|
case gds__dyn_del_validation:
|
||
|
bdelvald = TRUE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_del_default:
|
||
|
bdeldflt = TRUE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_default_value:
|
||
|
flddftval = (TEXT *) * ptr;
|
||
|
bflddftval = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_default_source:
|
||
|
flddfltsrc = (TEXT *) * ptr;
|
||
|
bflddfltsrc = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_dimensions:
|
||
|
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:
|
||
|
DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
--(*ptr);
|
||
|
DYN_execute(gbl, ptr, relation_name, field_name,
|
||
|
NULL_PTR, NULL_PTR, NULL_PTR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* 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.
|
||
|
*/
|
||
|
|
||
|
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) {
|
||
|
FLD.RDB$FIELD_LENGTH = new_dom->dyn_dsc.dsc_length;
|
||
|
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, &qryhdr, &FLD.RDB$QUERY_HEADER))
|
||
|
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, &qryhdr2, &FLD.RDB$QUERY_HEADER))
|
||
|
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, &missingval,
|
||
|
&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, &fldvald, &FLD.RDB$VALIDATION_BLR))
|
||
|
FLD.RDB$VALIDATION_BLR.NULL = FALSE;
|
||
|
else
|
||
|
FLD.RDB$VALIDATION_BLR.NULL = TRUE;
|
||
|
}
|
||
|
|
||
|
if (bfldvaldsrc) {
|
||
|
if (DYN_put_text_blob
|
||
|
(gbl, &fldvaldsrc,
|
||
|
&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, &fldvaldsrc2,
|
||
|
&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, &desc, &FLD.RDB$DESCRIPTION))
|
||
|
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, &desc2, &FLD.RDB$DESCRIPTION))
|
||
|
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, &flddftval, &FLD.RDB$DEFAULT_VALUE);
|
||
|
}
|
||
|
|
||
|
if (bflddfltsrc) {
|
||
|
FLD.RDB$DEFAULT_SOURCE.NULL = FALSE;
|
||
|
DYN_put_text_blob(gbl, &flddfltsrc, &FLD.RDB$DEFAULT_SOURCE);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 89, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 89: "Global field not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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];
|
||
|
JMP_BUF env, *old_env;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_m_index, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 91, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 91: "MODIFY RDB$INDICES failed" */
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
switch (verb) {
|
||
|
case gds__dyn_idx_unique:
|
||
|
IDX.RDB$UNIQUE_FLAG = DYN_get_number(ptr);
|
||
|
IDX.RDB$UNIQUE_FLAG.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_idx_inactive:
|
||
|
IDX.RDB$INDEX_INACTIVE = DYN_get_number(ptr);
|
||
|
IDX.RDB$INDEX_INACTIVE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_description:
|
||
|
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:
|
||
|
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:
|
||
|
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;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 93, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 93: "Index field not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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;
|
||
|
JMP_BUF env, *old_env;
|
||
|
|
||
|
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)
|
||
|
switch (verb) {
|
||
|
case gds__dyn_rel_name:
|
||
|
GET_STRING(ptr, r);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_system_flag:
|
||
|
system_flag = DYN_get_number(ptr);
|
||
|
sfflag = TRUE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_position:
|
||
|
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:
|
||
|
query_name = (TEXT *) * ptr;
|
||
|
qnflag = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_query_header:
|
||
|
query_header = (TEXT *) * ptr;
|
||
|
qhflag = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_fld_query_header2:
|
||
|
query_header = (TEXT *) * ptr;
|
||
|
qhflag = TRUE;
|
||
|
DYN_skip_attribute2(ptr);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case gds__dyn_fld_edit_string:
|
||
|
edit_string = (TEXT *) * ptr;
|
||
|
esflag = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_fld_edit_string2:
|
||
|
edit_string = (TEXT *) * ptr;
|
||
|
esflag = TRUE;
|
||
|
DYN_skip_attribute2(ptr);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case gds__dyn_security_class:
|
||
|
security_class = (TEXT *) * ptr;
|
||
|
scflag = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_description:
|
||
|
description = (TEXT *) * ptr;
|
||
|
dflag = TRUE;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_description2:
|
||
|
description = (TEXT *) * ptr;
|
||
|
dflag = TRUE;
|
||
|
DYN_skip_attribute2(ptr);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
default:
|
||
|
--(*ptr);
|
||
|
DYN_execute(gbl, ptr, relation_name, field_name,
|
||
|
NULL_PTR, NULL_PTR, NULL_PTR);
|
||
|
}
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_m_lfield, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 95, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
|
||
|
}
|
||
|
|
||
|
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];
|
||
|
GET_STRING(&new_name, new_fld);
|
||
|
|
||
|
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, &query_header, &FLD.RDB$QUERY_HEADER))
|
||
|
#else
|
||
|
if (DYN_put_blr_blob2
|
||
|
(gbl, &query_header, &FLD.RDB$QUERY_HEADER))
|
||
|
#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, &description, &FLD.RDB$DESCRIPTION))
|
||
|
#else
|
||
|
if (DYN_put_text_blob
|
||
|
(gbl, &description, &FLD.RDB$DESCRIPTION))
|
||
|
#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;
|
||
|
|
||
|
if (npflag && found)
|
||
|
modify_lfield_position(tdbb, dbb, gbl, r, f, position,
|
||
|
existing_position);
|
||
|
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 96, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 96: "Local column not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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];
|
||
|
JMP_BUF env, *old_env;
|
||
|
|
||
|
GET_STRING(ptr, procedure_name);
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = NULL;
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 141, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 141: "MODIFY RDB$PROCEDURES failed" */
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
switch (verb) {
|
||
|
case gds__dyn_system_flag:
|
||
|
P.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
|
||
|
P.RDB$SYSTEM_FLAG.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_prc_blr:
|
||
|
P.RDB$PROCEDURE_BLR.NULL = FALSE;
|
||
|
DYN_put_blr_blob(gbl, ptr, &P.RDB$PROCEDURE_BLR);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_description:
|
||
|
DYN_put_text_blob(gbl, ptr, &P.RDB$DESCRIPTION);
|
||
|
P.RDB$DESCRIPTION.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_prc_source:
|
||
|
DYN_put_text_blob(gbl, ptr, &P.RDB$PROCEDURE_SOURCE);
|
||
|
P.RDB$PROCEDURE_SOURCE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_prc_inputs:
|
||
|
P.RDB$PROCEDURE_INPUTS = DYN_get_number(ptr);
|
||
|
P.RDB$PROCEDURE_INPUTS.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_prc_outputs:
|
||
|
P.RDB$PROCEDURE_OUTPUTS = DYN_get_number(ptr);
|
||
|
P.RDB$PROCEDURE_OUTPUTS.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_security_class:
|
||
|
GET_STRING(ptr, P.RDB$SECURITY_CLASS);
|
||
|
P.RDB$SECURITY_CLASS.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
--(*ptr);
|
||
|
DYN_execute(gbl, ptr, NULL_PTR, NULL_PTR,
|
||
|
NULL_PTR, NULL_PTR, procedure_name);
|
||
|
}
|
||
|
|
||
|
END_MODIFY;
|
||
|
END_FOR;
|
||
|
|
||
|
if (!DYN_REQUEST(drq_m_prcs))
|
||
|
DYN_REQUEST(drq_m_prcs) = request;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 140, procedure_name, NULL, NULL, NULL, NULL);
|
||
|
/* msg 140: "Procedure %s not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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];
|
||
|
JMP_BUF env, *old_env;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
field_name[0] = '\0';
|
||
|
GET_STRING(ptr, name);
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_m_relation, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 99, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 99: "MODIFY RDB$RELATIONS failed" */
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
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_security_class:
|
||
|
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:
|
||
|
if (REL.RDB$EXTERNAL_FILE.NULL) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
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(old_env, request, -1);
|
||
|
DYN_error_punt(FALSE, 98, NULL, NULL, NULL, NULL,
|
||
|
NULL);
|
||
|
/* msg 98: "drop EXTERNAL FILE not allowed" */
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_description:
|
||
|
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:
|
||
|
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,
|
||
|
NULL_PTR, NULL_PTR, NULL_PTR);
|
||
|
}
|
||
|
END_MODIFY;
|
||
|
END_FOR;
|
||
|
|
||
|
if (!DYN_REQUEST(drq_m_relation))
|
||
|
DYN_REQUEST(drq_m_relation) = request;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 101, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 101: "Relation field not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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;
|
||
|
JMP_BUF env, *old_env;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_m_trigger, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 102, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 102: "MODIFY TRIGGER failed" */
|
||
|
}
|
||
|
|
||
|
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
|
||
|
|
||
|
if (!DYN_REQUEST(drq_m_trigger))
|
||
|
DYN_REQUEST(drq_m_trigger) = request;
|
||
|
|
||
|
found = TRUE;
|
||
|
MODIFY X
|
||
|
while ((verb = *(*ptr)++) != gds__dyn_end)
|
||
|
switch (verb) {
|
||
|
case gds__dyn_trg_name:
|
||
|
GET_STRING(ptr, X.RDB$TRIGGER_NAME);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_trg_type:
|
||
|
X.RDB$TRIGGER_TYPE = DYN_get_number(ptr);
|
||
|
X.RDB$TRIGGER_TYPE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_trg_sequence:
|
||
|
X.RDB$TRIGGER_SEQUENCE = DYN_get_number(ptr);
|
||
|
X.RDB$TRIGGER_SEQUENCE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_trg_inactive:
|
||
|
X.RDB$TRIGGER_INACTIVE = DYN_get_number(ptr);
|
||
|
X.RDB$TRIGGER_INACTIVE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_rel_name:
|
||
|
GET_STRING(ptr, X.RDB$RELATION_NAME);
|
||
|
X.RDB$RELATION_NAME.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_trg_blr:
|
||
|
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:
|
||
|
source = (TEXT *) * ptr;
|
||
|
DYN_skip_attribute(ptr);
|
||
|
DYN_put_text_blob(gbl, &source, &X.RDB$TRIGGER_SOURCE);
|
||
|
X.RDB$TRIGGER_SOURCE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_trg_source2:
|
||
|
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:
|
||
|
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:
|
||
|
DYN_put_text_blob2(gbl, ptr, &X.RDB$DESCRIPTION);
|
||
|
X.RDB$DESCRIPTION.NULL = FALSE;
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
default:
|
||
|
--(*ptr);
|
||
|
DYN_execute(gbl, ptr, NULL_PTR, NULL_PTR,
|
||
|
trigger_name, NULL_PTR, NULL_PTR);
|
||
|
}
|
||
|
END_MODIFY;
|
||
|
END_FOR;
|
||
|
|
||
|
if (!DYN_REQUEST(drq_m_trigger))
|
||
|
DYN_REQUEST(drq_m_trigger) = request;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 147, trigger_name, NULL, NULL, NULL, NULL);
|
||
|
/* msg 147: "Trigger %s not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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];
|
||
|
JMP_BUF env, *old_env;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_m_trg_msg, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, -1);
|
||
|
DYN_error_punt(TRUE, 105, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 105: "MODIFY TRIGGER MESSAGE failed" */
|
||
|
}
|
||
|
|
||
|
number = DYN_get_number(ptr);
|
||
|
if (trigger_name)
|
||
|
strcpy(t, trigger_name);
|
||
|
else if (*(*ptr)++ == gds__dyn_trg_name)
|
||
|
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)
|
||
|
switch (verb) {
|
||
|
case gds__dyn_trg_msg_number:
|
||
|
X.RDB$MESSAGE_NUMBER = DYN_get_number(ptr);
|
||
|
X.RDB$MESSAGE_NUMBER.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_trg_msg:
|
||
|
GET_STRING(ptr, X.RDB$MESSAGE);
|
||
|
X.RDB$MESSAGE.NULL = FALSE;
|
||
|
break;
|
||
|
|
||
|
#if (defined JPN_SJIS || defined JPN_EUC)
|
||
|
case gds__dyn_trg_msg2:
|
||
|
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;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
}
|
||
|
|
||
|
|
||
|
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;
|
||
|
JMP_BUF env, *old_env;
|
||
|
USHORT found = FALSE;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_d_cache, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, drq_s_cache);
|
||
|
DYN_error_punt(TRUE, 63, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 63: ERASE RDB$FILE failed */
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
|
||
|
if (!DYN_REQUEST(drq_d_cache))
|
||
|
DYN_REQUEST(drq_d_cache) = request;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 149, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 149: "Shared cache file not found" */
|
||
|
}
|
||
|
|
||
|
|
||
|
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;
|
||
|
JMP_BUF env, *old_env;
|
||
|
USHORT found = FALSE;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
request = (BLK) CMP_find_request(tdbb, drq_d_log, DYN_REQUESTS);
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_rundown_request(old_env, request, drq_d_log);
|
||
|
DYN_error_punt(TRUE, 153, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 153: ERASE RDB$LOG_FILE failed */
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
if (!found)
|
||
|
DYN_error_punt(FALSE, 152, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 152: "Write ahead log not found" */
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
USHORT new_pos = 0;
|
||
|
SLONG max_position = -1;
|
||
|
JMP_BUF env, *old_env;
|
||
|
BOOLEAN move_down = FALSE;
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
DYN_error_punt(TRUE, 95, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
|
||
|
}
|
||
|
|
||
|
/* 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);
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
/**************************************
|
||
|
*
|
||
|
* D Y N _ m o d i f y _ sql _ f i e l d
|
||
|
*
|
||
|
**************************************
|
||
|
*
|
||
|
* 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
|
||
|
*
|
||
|
**************************************/
|
||
|
TDBB tdbb;
|
||
|
DBB dbb;
|
||
|
BLK request = NULL, first_request;
|
||
|
UCHAR verb;
|
||
|
JMP_BUF env, *old_env;
|
||
|
BOOLEAN found = FALSE, update_domain = FALSE;
|
||
|
BOOLEAN dtype, scale, prec, subtype, charlen, collation, fldlen, nullflg,
|
||
|
charset;
|
||
|
DYN_FLD orig_fld, new_fld, dom_fld;
|
||
|
|
||
|
tdbb = GET_THREAD_DATA;
|
||
|
dbb = tdbb->tdbb_database;
|
||
|
|
||
|
old_env = (JMP_BUF *) tdbb->tdbb_setjmp;
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) env;
|
||
|
|
||
|
dtype = scale = prec = subtype = charlen = collation = fldlen = nullflg =
|
||
|
charset = FALSE;
|
||
|
|
||
|
if (SETJMP(env)) {
|
||
|
if (new_fld)
|
||
|
gds__free((SLONG *) new_fld);
|
||
|
|
||
|
if (dom_fld)
|
||
|
gds__free((SLONG *) dom_fld);
|
||
|
|
||
|
if (orig_fld)
|
||
|
gds__free((SLONG *) orig_fld);
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
DYN_error_punt(TRUE, 95, NULL, NULL, NULL, NULL, NULL);
|
||
|
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
|
||
|
}
|
||
|
|
||
|
/* 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);
|
||
|
|
||
|
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)
|
||
|
orig_fld->dyn_dtype = blr_blob;
|
||
|
|
||
|
while ((verb = *(*ptr)++) != gds__dyn_end) {
|
||
|
switch (verb) {
|
||
|
case gds__dyn_fld_source:
|
||
|
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:
|
||
|
GET_STRING(ptr, new_fld->dyn_rel_name);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_length:
|
||
|
fldlen = TRUE;
|
||
|
new_fld->dyn_dsc.dsc_length = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_type:
|
||
|
dtype = TRUE;
|
||
|
new_fld->dyn_dtype = DYN_get_number(ptr);
|
||
|
|
||
|
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_dsc.dsc_length =
|
||
|
DSC_string_length(&new_fld->dyn_dsc);
|
||
|
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:
|
||
|
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:
|
||
|
subtype = TRUE;
|
||
|
new_fld->dyn_dsc.dsc_sub_type = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_char_length:
|
||
|
charlen = TRUE;
|
||
|
new_fld->dyn_charlen = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_collation:
|
||
|
collation = TRUE;
|
||
|
new_fld->dyn_collation = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_character_set:
|
||
|
charset = TRUE;
|
||
|
new_fld->dyn_charset = DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_not_null:
|
||
|
nullflg = TRUE;
|
||
|
new_fld->dyn_null_flag = TRUE;
|
||
|
break;
|
||
|
|
||
|
case gds__dyn_fld_dimensions:
|
||
|
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:
|
||
|
DYN_get_number(ptr);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
--(*ptr);
|
||
|
DYN_execute(gbl, ptr, relation_name, RFR.RDB$FIELD_SOURCE,
|
||
|
NULL_PTR, NULL_PTR, NULL_PTR);
|
||
|
}
|
||
|
}
|
||
|
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;
|
||
|
|
||
|
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);
|
||
|
|
||
|
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) {
|
||
|
FLD.RDB$FIELD_LENGTH = new_fld->dyn_dsc.dsc_length;
|
||
|
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) {
|
||
|
FLD.RDB$FIELD_LENGTH =
|
||
|
new_fld->dyn_dsc.dsc_length;
|
||
|
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);
|
||
|
|
||
|
tdbb->tdbb_setjmp = (UCHAR *) old_env;
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
|
||
|
/* 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" */
|
||
|
}
|
||
|
}
|