2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Data Definition Utility
|
2003-10-25 12:55:41 +02:00
|
|
|
* MODULE: dyn_mod.epp
|
2001-05-23 15:26:42 +02:00
|
|
|
* 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 17:39:31 +01:00
|
|
|
* 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY)
|
2002-08-11 10:04:54 +02:00
|
|
|
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "firebird.h"
|
2004-04-29 00:36:29 +02:00
|
|
|
#include <stdio.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#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"
|
2003-11-08 17:40:17 +01:00
|
|
|
#include "../jrd/ibase.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"
|
2003-10-20 12:53:52 +02:00
|
|
|
#include "../jrd/ods.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/all_proto.h"
|
|
|
|
#include "../jrd/blb_proto.h"
|
|
|
|
#include "../jrd/cmp_proto.h"
|
|
|
|
#include "../jrd/dyn_proto.h"
|
2001-07-12 08:32:05 +02:00
|
|
|
#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"
|
2001-07-12 08:32:05 +02:00
|
|
|
#include "../jrd/met_proto.h"
|
2004-06-08 15:41:08 +02:00
|
|
|
#include "../jrd/thd.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/vio_proto.h"
|
|
|
|
#include "../jrd/dsc_proto.h"
|
2003-12-31 06:36:12 +01:00
|
|
|
#include "../common/utils_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
using namespace Jrd;
|
|
|
|
|
2002-12-16 17:25:10 +01:00
|
|
|
DATABASE DB = STATIC "ODS.RDB";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-03 23:43:56 +02:00
|
|
|
const int MAX_CHARS_SHORT = 6; /* 2**16 = 5 chars + sign */
|
|
|
|
const int MAX_CHARS_LONG = 11; /* 2**32 = 10 chars + sign */
|
|
|
|
const int MAX_CHARS_INT64 = 20; /* 2**64 = 19 chars + sign */
|
|
|
|
const int MAX_CHARS_DOUBLE = 22; /* 15 digits + 2 signs + E + decimal + 3 digit exp */
|
|
|
|
const int MAX_CHARS_FLOAT = 13; /* 7 digits + 2 signs + E + decimal + 2 digit exp */
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
static const UCHAR alloc_info[] = { isc_info_allocation, isc_info_end };
|
2004-10-03 06:49:04 +02:00
|
|
|
//static void drop_cache(Global*);
|
2004-03-31 19:38:53 +02:00
|
|
|
static void change_backup_mode(Global*, UCHAR verb);
|
2004-10-03 06:49:04 +02:00
|
|
|
//static void drop_log(Global*);
|
2002-07-05 17:00:26 +02:00
|
|
|
|
|
|
|
// Function not defined in this file MOD 04-July-2002
|
2004-03-31 19:38:53 +02:00
|
|
|
// static void modify_lfield_type(Global*, const UCHAR**, TEXT*, TEXT*);
|
2002-07-05 17:00:26 +02:00
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
static void modify_lfield_position(thread_db*, Database*, Global*, const TEXT*, const TEXT*,
|
2003-09-09 13:07:19 +02:00
|
|
|
USHORT, USHORT);
|
2004-03-31 19:38:53 +02:00
|
|
|
static bool check_view_dependency(thread_db*, Database*, Global*, const TEXT*, const TEXT*);
|
|
|
|
static bool check_sptrig_dependency(thread_db*, Database*, Global*, const TEXT*, const TEXT*);
|
|
|
|
static void modify_lfield_index(thread_db*, Database*, Global*, const TEXT*, const TEXT*,
|
2003-09-09 13:07:19 +02:00
|
|
|
const TEXT*);
|
2004-03-31 19:38:53 +02:00
|
|
|
static bool field_exists(thread_db*, Database*, Global*, const TEXT*, const TEXT*);
|
|
|
|
static bool domain_exists(thread_db*, Database*, Global*, const TEXT*);
|
|
|
|
static void get_domain_type(thread_db*, Database*, Global*, dyn_fld*);
|
2003-09-09 13:07:19 +02:00
|
|
|
static ULONG check_update_fld_type(const dyn_fld*, const dyn_fld*);
|
2004-03-11 06:04:26 +01:00
|
|
|
static void modify_err_punt(thread_db*, ULONG, const dyn_fld*, const dyn_fld*);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_database( Global* gbl, const UCHAR** ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D Y N _ m o d i f y _ d a t a b a s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Modify a database.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR s[128];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2003-10-29 11:53:47 +01:00
|
|
|
INF_database_info(reinterpret_cast<const SCHAR*>(alloc_info), sizeof(alloc_info),
|
|
|
|
reinterpret_cast<SCHAR*>(s), sizeof(s));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
if (s[0] != isc_info_allocation) {
|
2001-12-24 03:51:06 +01:00
|
|
|
goto dyn_punt_84;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
request = CMP_find_request(tdbb, drq_m_database, DYN_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-16 02:44:51 +01:00
|
|
|
const SSHORT length = gds__vax_integer(s + 1, 2);
|
|
|
|
SLONG start = gds__vax_integer(s + 3, length);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2004-10-03 06:49:04 +02:00
|
|
|
//#ifdef SUPERSERVER
|
|
|
|
// bool first_log_file = true;
|
|
|
|
//#endif
|
2003-11-05 10:02:33 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
MODIFY DBB USING
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_def_file:
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_define_file(gbl, ptr, (SLONG) 0, &start, 158);
|
|
|
|
break;
|
2003-08-06 18:30:49 +02:00
|
|
|
|
2003-09-21 15:33:45 +02:00
|
|
|
case isc_dyn_def_difference:
|
2003-08-06 18:30:49 +02:00
|
|
|
DYN_define_difference(gbl, ptr);
|
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-10-03 06:49:04 +02:00
|
|
|
/*
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifdef SUPERSERVER
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_def_default_log:
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_define_log_file(gbl, ptr, first_log_file, true);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_def_log_file:
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_define_log_file(gbl, ptr, first_log_file, false);
|
|
|
|
first_log_file = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_def_cache_file:
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_define_cache(gbl, ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_log_group_commit_wait:
|
2004-01-06 11:33:18 +01:00
|
|
|
DYN_get_number(ptr); // ignore
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_log_buffer_size:
|
2004-01-06 11:33:18 +01:00
|
|
|
DYN_get_number(ptr); // ignore
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_log_check_point_length:
|
2004-01-06 11:33:18 +01:00
|
|
|
DYN_get_number(ptr); // ignore
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_log_num_of_buffers:
|
2004-01-06 11:33:18 +01:00
|
|
|
DYN_get_number(ptr); // ignore
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_drop_cache:
|
2001-05-23 15:26:42 +02:00
|
|
|
drop_cache(gbl);
|
|
|
|
break;
|
2004-10-03 06:49:04 +02:00
|
|
|
*/
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-21 15:33:45 +02:00
|
|
|
case isc_dyn_drop_difference:
|
|
|
|
case isc_dyn_begin_backup:
|
|
|
|
case isc_dyn_end_backup:
|
2003-08-06 18:30:49 +02:00
|
|
|
change_backup_mode(gbl, verb);
|
|
|
|
break;
|
|
|
|
|
2004-10-03 06:49:04 +02:00
|
|
|
/*
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_drop_log:
|
2001-05-23 15:26:42 +02:00
|
|
|
drop_log(gbl);
|
|
|
|
break;
|
2004-10-03 06:49:04 +02:00
|
|
|
*/
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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);
|
2003-08-28 15:16:03 +02:00
|
|
|
DYN_execute(gbl, ptr, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
END_MODIFY;
|
|
|
|
END_FOR;
|
|
|
|
|
|
|
|
if (!DYN_REQUEST(drq_m_database))
|
|
|
|
DYN_REQUEST(drq_m_database) = request;
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 84, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 84: "MODIFY DATABASE failed" */
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
dyn_punt_84:
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 84, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 84: "MODIFY DATABASE failed" */
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_exception( Global* gbl, const UCHAR** ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D Y N _ m o d i f y _ e x c e p t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Modify an exception.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier t;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_m_xcp, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, t);
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
MODIFY X
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_xcp_msg:
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, X.RDB$MESSAGE);
|
|
|
|
X.RDB$MESSAGE.NULL = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 145, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 145: "MODIFY EXCEPTION failed" */
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!found)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-05 10:02:33 +01: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(
|
2004-03-31 19:38:53 +02:00
|
|
|
Global* gbl,
|
2003-11-05 10:02:33 +01:00
|
|
|
const UCHAR** ptr,
|
|
|
|
const TEXT* relation_name, TEXT* field_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-06-30 10:46:51 +02:00
|
|
|
SSHORT field_adjusted_count = 0;
|
2003-11-05 10:02:33 +01:00
|
|
|
const 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
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_m_gfield, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2003-11-05 10:02:33 +01:00
|
|
|
|
|
|
|
dyn_fld* orig_dom = 0;
|
|
|
|
dyn_fld* new_dom = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
/* Allocate the field structures */
|
2004-03-28 11:10:30 +02:00
|
|
|
orig_dom = (dyn_fld*) gds__alloc(sizeof(struct dyn_fld));
|
2001-12-24 03:51:06 +01:00
|
|
|
if (!orig_dom) {
|
2003-11-05 10:02:33 +01: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));
|
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
new_dom = (dyn_fld*) gds__alloc(sizeof(struct dyn_fld));
|
2001-12-24 03:51:06 +01:00
|
|
|
if (!new_dom) {
|
2003-11-05 10:02:33 +01: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));
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
bool dtype, scale, prec, subtype, charlen, collation, fldlen, nullflg,
|
|
|
|
charset;
|
|
|
|
dtype = scale = prec = subtype = charlen = collation = fldlen = nullflg =
|
|
|
|
charset = false;
|
|
|
|
|
|
|
|
bool bqryname, bqryhdr, bedtstr, bmissingval,
|
|
|
|
bfldvald, bfldvaldsrc, bfielddesc,
|
|
|
|
bdelvald, bdeldflt, bflddftval, bflddfltsrc;
|
|
|
|
bqryname = bqryhdr = bedtstr = bmissingval = false;
|
|
|
|
bfldvald = bfldvaldsrc = bfielddesc = bdelvald =
|
|
|
|
bdeldflt = bflddftval = bflddfltsrc = false;
|
|
|
|
|
|
|
|
const TEXT *qryname, *edtstr;
|
|
|
|
const UCHAR *qryhdr, *missingval, *fldvald, *fldvaldsrc, *fielddesc,
|
|
|
|
*flddftval, *flddfltsrc;
|
|
|
|
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, orig_dom->dyn_fld_name);
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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;
|
2004-02-20 07:43:27 +01:00
|
|
|
orig_dom->dyn_null_flag = FLD.RDB$NULL_FLAG != 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* If the original field type is an array, force its blr type to blr_blob */
|
2003-11-05 10:02:33 +01:00
|
|
|
bool has_dimensions = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (FLD.RDB$DIMENSIONS != 0)
|
|
|
|
{
|
|
|
|
orig_dom->dyn_dtype = blr_blob;
|
2003-11-05 10:02:33 +01:00
|
|
|
has_dimensions = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
bool single_validate = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
switch (verb)
|
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_name:
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier newfld;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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;
|
2004-07-06 07:59:40 +02:00
|
|
|
jrd_req* old_request = request;
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release (tdbb, 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;
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
request = old_request;
|
|
|
|
END_MODIFY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 204, orig_dom->dyn_fld_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
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
|
|
|
|
{
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 212, NULL, NULL, NULL, NULL, NULL);
|
2002-06-30 10:46:51 +02:00
|
|
|
/* msg 212: "Zero length identifiers not allowed" */
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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. */
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_length:
|
2003-11-05 10:02:33 +01:00
|
|
|
fldlen = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_dsc.dsc_length = DYN_get_number(ptr);
|
2002-06-30 10:46:51 +02:00
|
|
|
if (++field_adjusted_count > 2)
|
|
|
|
{
|
2004-08-26 13:07:57 +02:00
|
|
|
EXE_unwind(tdbb, request);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 5, err_one_type_change_only, NULL, NULL, NULL, NULL);
|
2002-06-30 10:46:51 +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:
|
|
|
|
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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_type:
|
2003-11-05 10:02:33 +01:00
|
|
|
dtype = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_dtype = DYN_get_number(ptr);
|
2002-06-30 10:46:51 +02:00
|
|
|
if (++field_adjusted_count > 2)
|
|
|
|
{
|
2004-08-26 13:07:57 +02:00
|
|
|
EXE_unwind(tdbb, request);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 5, err_one_type_change_only, NULL, NULL, NULL, NULL);
|
2002-06-30 10:46:51 +02:00
|
|
|
}
|
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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_scale:
|
2003-11-05 10:02:33 +01:00
|
|
|
scale = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_dsc.dsc_scale = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dyn_fld_precision:
|
2003-11-05 10:02:33 +01:00
|
|
|
prec = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_precision = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_sub_type:
|
2003-11-05 10:02:33 +01:00
|
|
|
subtype = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_dsc.dsc_sub_type = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_char_length:
|
2003-11-05 10:02:33 +01:00
|
|
|
charlen = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_charlen = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_collation:
|
2003-11-05 10:02:33 +01:00
|
|
|
collation = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_collation = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_character_set:
|
2003-11-05 10:02:33 +01:00
|
|
|
charset = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_dom->dyn_charset = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_not_null:
|
2003-11-05 10:02:33 +01:00
|
|
|
nullflg = true;
|
2004-02-20 07:43:27 +01:00
|
|
|
new_dom->dyn_null_flag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_query_name:
|
2003-11-05 10:02:33 +01:00
|
|
|
qryname = (TEXT*) * ptr;
|
|
|
|
bqryname = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_query_header:
|
2003-11-05 10:02:33 +01:00
|
|
|
qryhdr = *ptr;
|
|
|
|
bqryhdr = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_edit_string:
|
2003-11-05 10:02:33 +01:00
|
|
|
edtstr = (TEXT*) * ptr;
|
|
|
|
bedtstr = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_missing_value:
|
2003-11-05 10:02:33 +01:00
|
|
|
missingval = *ptr;
|
|
|
|
bmissingval = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_single_validation:
|
2001-05-23 15:26:42 +02:00
|
|
|
if (single_validate) {
|
2004-08-26 13:07:57 +02:00
|
|
|
EXE_unwind(tdbb, request);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 160, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* msg 160: "Only one constraint allowed for a domain" */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
2003-11-05 10:02:33 +01:00
|
|
|
single_validate = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_validation_blr:
|
2001-05-23 15:26:42 +02:00
|
|
|
if (single_validate && (!FLD.RDB$VALIDATION_BLR.NULL)) {
|
2004-08-26 13:07:57 +02:00
|
|
|
EXE_unwind(tdbb, request);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 160, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* msg 160: "Only one constraint allowed for a domain" */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
2003-11-05 10:02:33 +01:00
|
|
|
single_validate = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
fldvald = *ptr;
|
|
|
|
bfldvald = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_validation_source:
|
2003-11-05 10:02:33 +01:00
|
|
|
fldvaldsrc = *ptr;
|
|
|
|
bfldvaldsrc = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_description:
|
2003-11-05 10:02:33 +01:00
|
|
|
fielddesc = *ptr;
|
|
|
|
bfielddesc = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_del_validation:
|
2003-11-05 10:02:33 +01:00
|
|
|
bdelvald = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_del_default:
|
2003-11-05 10:02:33 +01:00
|
|
|
bdeldflt = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_default_value:
|
2003-11-05 10:02:33 +01:00
|
|
|
flddftval = *ptr;
|
|
|
|
bflddftval = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_default_source:
|
2003-11-05 10:02:33 +01:00
|
|
|
flddfltsrc = *ptr;
|
|
|
|
bflddfltsrc = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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.
|
|
|
|
*/
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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,
|
2003-08-28 15:16:03 +02:00
|
|
|
NULL, NULL, NULL);
|
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) {
|
|
|
|
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);
|
2004-04-11 09:14:27 +02:00
|
|
|
const ULONG retval = check_update_fld_type(orig_dom, new_dom);
|
2003-09-09 13:07:19 +02:00
|
|
|
if (retval != FB_SUCCESS)
|
|
|
|
modify_err_punt(tdbb, retval, orig_dom, new_dom);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
jrd_req* old_request = request;
|
2001-05-23 15:26:42 +02:00
|
|
|
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,
|
2004-12-16 04:03:13 +01:00
|
|
|
DOM.RDB$RELATION_NAME,
|
2001-05-23 15:26:42 +02:00
|
|
|
DOM.RDB$FIELD_NAME,
|
|
|
|
DOM.RDB$FIELD_NAME);
|
|
|
|
END_FOR;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
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) {
|
2003-11-05 10:02:33 +01:00
|
|
|
if (DYN_put_blr_blob(gbl, &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 (bedtstr) {
|
|
|
|
if (GET_STRING(&edtstr, FLD.RDB$EDIT_STRING))
|
|
|
|
FLD.RDB$EDIT_STRING.NULL = FALSE;
|
|
|
|
else
|
|
|
|
FLD.RDB$EDIT_STRING.NULL = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bmissingval) {
|
2003-11-05 10:02:33 +01:00
|
|
|
if (DYN_put_blr_blob(gbl, &missingval, &FLD.RDB$MISSING_VALUE))
|
|
|
|
FLD.RDB$MISSING_VALUE.NULL = FALSE;
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
|
|
|
FLD.RDB$MISSING_VALUE.NULL = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bfldvald) {
|
2003-11-05 10:02:33 +01:00
|
|
|
if (DYN_put_blr_blob(gbl, &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) {
|
2003-11-05 10:02:33 +01:00
|
|
|
if (DYN_put_text_blob(
|
|
|
|
gbl, &fldvaldsrc, &FLD.RDB$VALIDATION_SOURCE))
|
|
|
|
{
|
|
|
|
FLD.RDB$VALIDATION_SOURCE.NULL = FALSE;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
|
|
|
FLD.RDB$VALIDATION_SOURCE.NULL = TRUE;
|
|
|
|
}
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
if (bfielddesc) {
|
|
|
|
if (DYN_put_text_blob(gbl, &fielddesc, &FLD.RDB$DESCRIPTION))
|
2001-05-23 15:26:42 +02:00
|
|
|
FLD.RDB$DESCRIPTION.NULL = FALSE;
|
|
|
|
else
|
|
|
|
FLD.RDB$DESCRIPTION.NULL = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_put_blr_blob(gbl, &flddftval, &FLD.RDB$DEFAULT_VALUE);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bflddfltsrc) {
|
|
|
|
FLD.RDB$DEFAULT_SOURCE.NULL = FALSE;
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_put_text_blob(gbl, &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)
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(orig_dom);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (new_dom)
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(new_dom);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2001-12-24 03:51:06 +01:00
|
|
|
if (orig_dom) {
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(orig_dom);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (new_dom) {
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(new_dom);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 87, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 87: "MODIFY RDB$FIELDS failed" */
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!found)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-05 10:02:33 +01: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
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_index( Global* gbl, const UCHAR** ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D Y N _ m o d i f y _ i n d e x
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Modify an existing index
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier name;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_m_index, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, name);
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
MODIFY IDX USING
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
|
|
|
/* For V4 index selectivity can be set only to -1 */
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 91, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 91: "MODIFY RDB$INDICES failed" */
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!found)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-05 10:02:33 +01: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(
|
2004-03-31 19:38:53 +02:00
|
|
|
Global* gbl,
|
2003-11-05 10:02:33 +01:00
|
|
|
const UCHAR** ptr,
|
|
|
|
const TEXT* relation_name, TEXT* field_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-07-06 07:59:40 +02:00
|
|
|
USHORT position;
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier f, r;
|
|
|
|
TEXT *query_name, *edit_string,
|
2001-05-23 15:26:42 +02:00
|
|
|
*security_class, *new_name;
|
2003-11-05 10:02:33 +01:00
|
|
|
|
|
|
|
const UCHAR *query_header, *description;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
GET_STRING(ptr, f);
|
|
|
|
r[0] = 0;
|
2003-11-05 10:02:33 +01:00
|
|
|
|
|
|
|
bool sfflag, qnflag, qhflag, esflag, dflag, system_flag, scflag, nnflag,
|
|
|
|
ntflag, npflag;
|
2001-05-23 15:26:42 +02:00
|
|
|
sfflag = qnflag = qhflag = esflag = dflag = scflag = npflag = nnflag =
|
2003-11-05 10:02:33 +01:00
|
|
|
ntflag = false;
|
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_rel_name:
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, r);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_system_flag:
|
2001-05-23 15:26:42 +02:00
|
|
|
system_flag = DYN_get_number(ptr);
|
2003-11-05 10:02:33 +01:00
|
|
|
sfflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_position:
|
2001-05-23 15:26:42 +02:00
|
|
|
position = DYN_get_number(ptr);
|
2003-11-05 10:02:33 +01:00
|
|
|
npflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dyn_new_fld_name:
|
2003-11-05 10:02:33 +01:00
|
|
|
new_name = (TEXT*) * ptr;
|
|
|
|
nnflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_query_name:
|
2003-11-05 10:02:33 +01:00
|
|
|
query_name = (TEXT*) * ptr;
|
|
|
|
qnflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_query_header:
|
2003-11-05 10:02:33 +01:00
|
|
|
query_header = *ptr;
|
|
|
|
qhflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_edit_string:
|
2003-11-05 10:02:33 +01:00
|
|
|
edit_string = (TEXT*) * ptr;
|
|
|
|
esflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_security_class:
|
2003-11-05 10:02:33 +01:00
|
|
|
security_class = (TEXT*) * ptr;
|
|
|
|
scflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_description:
|
2003-11-05 10:02:33 +01:00
|
|
|
description = *ptr;
|
|
|
|
dflag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
--(*ptr);
|
2003-08-28 15:16:03 +02:00
|
|
|
DYN_execute(gbl, ptr, relation_name, field_name, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_m_lfield, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
USHORT existing_position;
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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) {
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier new_fld;
|
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);
|
2004-09-26 03:49:52 +02:00
|
|
|
fb_utils::exact_name(new_fld);
|
2002-06-30 10:46:51 +02:00
|
|
|
if (!new_fld[0])
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 212, NULL, NULL, NULL, NULL, NULL);
|
2002-06-30 10:46:51 +02:00
|
|
|
/* 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 {
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 205, f, new_fld, r, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* msg 205: Cannot rename field %s to %s. A field with that name already exists in table %s. */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qhflag) {
|
|
|
|
if (DYN_put_blr_blob
|
2003-11-05 10:02:33 +01:00
|
|
|
(gbl, &query_header, &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 (esflag) {
|
|
|
|
if (GET_STRING(&edit_string, FLD.RDB$EDIT_STRING))
|
|
|
|
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 (DYN_put_text_blob
|
2003-11-05 10:02:33 +01:00
|
|
|
(gbl, &description, &FLD.RDB$DESCRIPTION))
|
2001-05-23 15:26:42 +02:00
|
|
|
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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 95, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* 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
|
|
|
{
|
2003-11-05 10:02:33 +01: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
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_procedure( Global* gbl, const UCHAR** ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier procedure_name;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
GET_STRING(ptr, procedure_name);
|
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
request = CMP_find_request(tdbb, drq_m_prcs, DYN_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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);
|
2003-08-28 15:16:03 +02:00
|
|
|
DYN_execute(gbl, ptr, NULL, NULL, NULL, NULL, 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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 141, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 141: "MODIFY RDB$PROCEDURES failed" */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2003-11-05 10:02:33 +01: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
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_relation( Global* gbl, const UCHAR** ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D Y N _ m o d i f y _ r e l a t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Modify an existing relation
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier name, field_name;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-06-30 10:46:51 +02:00
|
|
|
field_name[0] = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, name);
|
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_m_relation, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
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)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 177, NULL, NULL, NULL, NULL, NULL);
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
MODIFY REL USING
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_rel_ext_file:
|
2001-05-23 15:26:42 +02:00
|
|
|
if (REL.RDB$EXTERNAL_FILE.NULL) {
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 97, NULL, NULL, NULL, NULL,
|
2001-05-23 15:26:42 +02:00
|
|
|
NULL);
|
|
|
|
/* msg 97: "add EXTERNAL FILE not allowed" */
|
|
|
|
}
|
|
|
|
if (!GET_STRING(ptr, REL.RDB$EXTERNAL_FILE)) {
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 98, NULL, NULL, NULL, NULL,
|
2001-05-23 15:26:42 +02:00
|
|
|
NULL);
|
|
|
|
/* msg 98: "drop EXTERNAL FILE not allowed" */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
|
|
|
default:
|
|
|
|
--(*ptr);
|
2003-08-28 15:16:03 +02:00
|
|
|
DYN_execute(gbl, ptr, name, field_name, NULL, NULL, NULL);
|
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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 99, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 99: "MODIFY RDB$RELATIONS failed" */
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!found)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-05 10:02:33 +01: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
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_trigger( Global* gbl, const UCHAR** ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D Y N _ m o d i f y _ t r i g g e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Modify a trigger for a relation.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier trigger_name;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_m_trigger, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, trigger_name);
|
2003-11-05 10:02:33 +01:00
|
|
|
const UCHAR* source = NULL;
|
|
|
|
const UCHAR* blr = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
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)
|
|
|
|
{
|
2004-11-29 10:09:42 +01:00
|
|
|
case fb_sysflag_check_constraint:
|
|
|
|
case fb_sysflag_referential_constraint:
|
|
|
|
case fb_sysflag_view_check:
|
2002-06-30 10:46:51 +02:00
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
MODIFY X
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_trg_name:
|
2002-06-30 10:46:51 +02:00
|
|
|
{
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier new_trigger_name;
|
2002-06-30 10:46:51 +02:00
|
|
|
new_trigger_name[0] = 0;
|
|
|
|
/* GET_STRING(ptr, X.RDB$TRIGGER_NAME); */
|
|
|
|
GET_STRING(ptr, new_trigger_name);
|
2004-09-26 03:49:52 +02:00
|
|
|
fb_utils::exact_name(new_trigger_name);
|
2002-06-30 10:46:51 +02:00
|
|
|
if (!new_trigger_name[0])
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 212, NULL, NULL, NULL, NULL, NULL);
|
2002-06-30 10:46:51 +02:00
|
|
|
/* msg 212: "Zero length identifiers not allowed" */
|
|
|
|
strcpy (X.RDB$TRIGGER_NAME, new_trigger_name);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_trg_source:
|
2003-11-05 10:02:33 +01:00
|
|
|
source = *ptr;
|
2001-05-23 15:26:42 +02:00
|
|
|
DYN_skip_attribute(ptr);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_put_text_blob(gbl, &source, &X.RDB$TRIGGER_SOURCE);
|
2001-05-23 15:26:42 +02:00
|
|
|
X.RDB$TRIGGER_SOURCE.NULL = FALSE;
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
|
|
|
default:
|
|
|
|
--(*ptr);
|
2003-08-28 15:16:03 +02:00
|
|
|
DYN_execute(gbl, ptr, NULL, NULL, trigger_name, NULL, NULL);
|
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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 102, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 102: "MODIFY TRIGGER failed" */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2003-11-05 10:02:33 +01: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
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_trigger_msg( Global* gbl, const UCHAR** ptr, TEXT* trigger_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier t;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_m_trg_msg, DYN_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
const int number = DYN_get_number(ptr);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (trigger_name)
|
|
|
|
strcpy(t, trigger_name);
|
2003-11-08 17:40:17 +01:00
|
|
|
else if (*(*ptr)++ == isc_dyn_trg_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, t);
|
|
|
|
else
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 103, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* 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
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_trg_msg:
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, X.RDB$MESSAGE);
|
|
|
|
X.RDB$MESSAGE.NULL = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 105, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 105: "MODIFY TRIGGER MESSAGE failed" */
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_view( Global* gbl, const UCHAR** ptr)
|
2002-08-11 10:04:54 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* D Y N _ m o d i f y _ v i e w
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Execute a dynamic ddl statement.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-11-05 10:02:33 +01:00
|
|
|
SqlIdentifier view_name;
|
2002-08-11 10:04:54 +02:00
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2002-08-11 10:04:54 +02:00
|
|
|
|
|
|
|
view_name[0] = 0;
|
|
|
|
GET_STRING(ptr, view_name);
|
|
|
|
|
2004-09-26 03:49:52 +02:00
|
|
|
fb_utils::exact_name(view_name);
|
2002-08-11 10:04:54 +02:00
|
|
|
if (!view_name[0])
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 212, NULL, NULL, NULL, NULL, NULL);
|
2002-08-11 10:04:54 +02:00
|
|
|
/* msg 212: "Zero length identifiers not allowed" */
|
2003-09-09 13:07:19 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2002-08-11 10:04:54 +02:00
|
|
|
|
|
|
|
try {
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
request = CMP_find_request(tdbb, drq_m_relation, DYN_REQUESTS);
|
2002-08-11 10:04:54 +02:00
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = false;
|
2002-08-11 10:04:54 +02:00
|
|
|
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;
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2002-08-11 10:04:54 +02:00
|
|
|
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;
|
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end)
|
2002-08-11 10:04:54 +02:00
|
|
|
switch (verb)
|
|
|
|
{
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_system_flag:
|
2002-08-11 10:04:54 +02:00
|
|
|
REL.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
|
|
|
|
REL.RDB$SYSTEM_FLAG.NULL = FALSE;
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_view_blr:
|
2002-08-11 10:04:54 +02:00
|
|
|
DYN_put_blr_blob(gbl, ptr, &REL.RDB$VIEW_BLR);
|
|
|
|
REL.RDB$VIEW_BLR.NULL = FALSE;
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_view_source:
|
2002-08-11 10:04:54 +02:00
|
|
|
DYN_put_text_blob(gbl, ptr, &REL.RDB$VIEW_SOURCE);
|
|
|
|
REL.RDB$VIEW_SOURCE.NULL = FALSE;
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_security_class:
|
2002-08-11 10:04:54 +02:00
|
|
|
GET_STRING(ptr, REL.RDB$SECURITY_CLASS);
|
|
|
|
REL.RDB$SECURITY_CLASS.NULL = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
--(*ptr);
|
2003-08-28 15:16:03 +02:00
|
|
|
DYN_execute(gbl, ptr, REL.RDB$RELATION_NAME, NULL,
|
|
|
|
NULL, NULL, NULL);
|
2002-08-11 10:04:54 +02:00
|
|
|
}
|
|
|
|
END_MODIFY;
|
|
|
|
END_FOR;
|
|
|
|
|
|
|
|
if (!DYN_REQUEST(drq_m_relation))
|
|
|
|
DYN_REQUEST(drq_m_relation) = request;
|
|
|
|
|
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-08-11 10:04:54 +02:00
|
|
|
DYN_rundown_request(request, -1);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 99, NULL, NULL, NULL, NULL, NULL);
|
2002-08-11 10:04:54 +02:00
|
|
|
/* msg 99: "MODIFY RDB$RELATIONS failed" */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 61, NULL, NULL, NULL, NULL, NULL);
|
2002-08-11 10:04:54 +02:00
|
|
|
/* msg 61: "Relation not found" */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-03 06:49:04 +02:00
|
|
|
/*
|
2004-03-31 19:38:53 +02:00
|
|
|
static void drop_cache( Global* gbl)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-10-03 06:49:04 +02:00
|
|
|
// **************************************
|
|
|
|
// *
|
|
|
|
// * d r o p _ c a c h e
|
|
|
|
// *
|
|
|
|
// **************************************
|
|
|
|
// *
|
|
|
|
// * Functional description
|
|
|
|
// * Drop the database cache
|
|
|
|
// *
|
|
|
|
// **************************************
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_d_cache, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
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;
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2003-08-06 18:30:49 +02:00
|
|
|
DYN_rundown_request(request, drq_d_cache);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 63, NULL, NULL, NULL, NULL, NULL);
|
2004-10-03 06:49:04 +02:00
|
|
|
// msg 63: ERASE RDB$FILE failed
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!found)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 149, NULL, NULL, NULL, NULL, NULL);
|
2004-10-03 06:49:04 +02:00
|
|
|
// msg 149: "Shared cache file not found"
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2004-10-03 06:49:04 +02:00
|
|
|
*/
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
static void change_backup_mode( Global* gbl, UCHAR verb)
|
2003-08-06 18:30:49 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* c h a n g e _ b a c k u p _ m o d e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Drop backup difference file for the database,
|
|
|
|
* begin or end backup
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
bool invalid_state = false;
|
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2003-08-06 18:30:49 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_d_difference, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2003-08-06 18:30:49 +02:00
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
|
|
X IN RDB$FILES
|
|
|
|
|
|
|
|
if (X.RDB$FILE_FLAGS & FILE_difference) {
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2003-08-06 18:30:49 +02:00
|
|
|
switch (verb) {
|
2003-09-21 15:33:45 +02:00
|
|
|
case isc_dyn_drop_difference:
|
2003-08-06 18:30:49 +02:00
|
|
|
ERASE X;
|
|
|
|
break;
|
2003-09-21 15:33:45 +02:00
|
|
|
case isc_dyn_begin_backup:
|
2003-08-06 18:30:49 +02:00
|
|
|
if (X.RDB$FILE_FLAGS & FILE_backing_up) {
|
|
|
|
invalid_state = true;
|
2004-01-28 08:50:41 +01:00
|
|
|
}
|
|
|
|
else {
|
2003-08-06 18:30:49 +02:00
|
|
|
MODIFY X USING
|
|
|
|
X.RDB$FILE_FLAGS |= FILE_backing_up;
|
|
|
|
END_MODIFY;
|
|
|
|
}
|
|
|
|
break;
|
2003-09-21 15:33:45 +02:00
|
|
|
case isc_dyn_end_backup:
|
2003-08-06 18:30:49 +02:00
|
|
|
if (X.RDB$FILE_FLAGS & FILE_backing_up) {
|
|
|
|
if (X.RDB$FILE_NAME.NULL) {
|
|
|
|
ERASE X;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
MODIFY X USING
|
|
|
|
X.RDB$FILE_FLAGS &= ~FILE_backing_up;
|
|
|
|
END_MODIFY;
|
|
|
|
}
|
2004-01-28 08:50:41 +01:00
|
|
|
}
|
|
|
|
else {
|
2003-08-06 18:30:49 +02:00
|
|
|
invalid_state = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
END_FOR;
|
|
|
|
|
|
|
|
if (!DYN_REQUEST(drq_d_difference)) {
|
|
|
|
DYN_REQUEST(drq_d_difference) = request;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2003-08-06 18:30:49 +02:00
|
|
|
DYN_rundown_request(request, drq_d_difference);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 63, NULL, NULL, NULL, NULL, NULL);
|
2003-08-06 18:30:49 +02:00
|
|
|
/* msg 63: ERASE RDB$FILE failed */
|
|
|
|
}
|
|
|
|
|
2003-09-21 15:33:45 +02:00
|
|
|
if (!found && verb == isc_dyn_begin_backup) try {
|
2004-02-20 07:43:27 +01:00
|
|
|
request = CMP_find_request(tdbb, drq_s_difference, DYN_REQUESTS);
|
2003-08-06 18:30:49 +02:00
|
|
|
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
|
|
X IN RDB$FILES
|
|
|
|
X.RDB$FILE_NAME.NULL = TRUE;
|
|
|
|
X.RDB$FILE_FLAGS.NULL = FALSE;
|
|
|
|
X.RDB$FILE_FLAGS = FILE_difference | FILE_backing_up;
|
|
|
|
X.RDB$FILE_START = 0;
|
|
|
|
X.RDB$FILE_START.NULL = FALSE;
|
|
|
|
X.RDB$FILE_LENGTH.NULL = TRUE;
|
|
|
|
X.RDB$SHADOW_NUMBER.NULL = TRUE;
|
|
|
|
END_STORE;
|
|
|
|
|
|
|
|
found = true;
|
|
|
|
|
|
|
|
if (!DYN_REQUEST(drq_s_difference))
|
|
|
|
{
|
|
|
|
DYN_REQUEST(drq_s_difference) = request;
|
|
|
|
}
|
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2003-08-06 18:30:49 +02:00
|
|
|
DYN_rundown_request(request, drq_s_difference);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 150, NULL, NULL, NULL, NULL, NULL);
|
2003-08-06 18:30:49 +02:00
|
|
|
/* msg 150: STORE RDB$FILES failed */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (invalid_state) {
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, verb == isc_dyn_begin_backup ? 217 : 218,
|
2003-08-12 21:54:34 +02:00
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
/* msg 217: "Database is already in the physical backup mode" */
|
|
|
|
/* msg 218: "Database is not in the physical backup mode" */
|
2003-08-06 18:30:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
{
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, verb == isc_dyn_end_backup ? 218 : 215,
|
2003-08-12 21:54:34 +02:00
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
/* msg 218: "Database is not in the physical backup mode" */
|
|
|
|
/* msg 215: "Difference file is not defined" */
|
2003-08-06 18:30:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-03 06:49:04 +02:00
|
|
|
/*
|
2004-03-31 19:38:53 +02:00
|
|
|
static void drop_log( Global* gbl)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2004-11-07 15:30:38 +01:00
|
|
|
// **************************************
|
2004-10-03 06:49:04 +02:00
|
|
|
// *
|
|
|
|
// * d r o p _ l o g
|
|
|
|
// *
|
|
|
|
// **************************************
|
|
|
|
// *
|
|
|
|
// * Functional description
|
|
|
|
// * Delete all log files
|
|
|
|
// *
|
|
|
|
// **************************************
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, drq_d_log, DYN_REQUESTS);
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
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;
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
END_FOR;
|
|
|
|
|
|
|
|
if (!DYN_REQUEST(drq_d_log))
|
|
|
|
DYN_REQUEST(drq_d_log) = request;
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2002-04-04 09:10:40 +02:00
|
|
|
DYN_rundown_request(request, drq_d_log);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 153, NULL, NULL, NULL, NULL, NULL);
|
2004-10-03 06:49:04 +02:00
|
|
|
// msg 153: ERASE RDB$LOG_FILE failed
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!found)
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 152, NULL, NULL, NULL, NULL, NULL);
|
2004-10-03 06:49:04 +02:00
|
|
|
// msg 152: "Write ahead log not found"
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2004-10-03 06:49:04 +02:00
|
|
|
*/
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static void modify_lfield_position(thread_db* tdbb,
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb,
|
2004-03-31 19:38:53 +02:00
|
|
|
Global* gbl,
|
2003-09-09 13:07:19 +02:00
|
|
|
const TEXT* relation_name,
|
|
|
|
const TEXT* field_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
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
|
|
|
|
*
|
|
|
|
***********************************************************/
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
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 */
|
2003-09-09 13:07:19 +02:00
|
|
|
SLONG max_position = -1;
|
2001-05-23 15:26:42 +02:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
bool move_down = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (existing_position < new_position)
|
2003-09-09 13:07:19 +02:00
|
|
|
move_down = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
*/
|
2004-09-26 03:49:52 +02:00
|
|
|
fb_utils::exact_name(FLD.RDB$FIELD_NAME);
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
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 */
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
USHORT new_pos = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 95, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static bool check_view_dependency(thread_db* tdbb,
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb,
|
2004-03-31 19:38:53 +02:00
|
|
|
Global* gbl,
|
2003-09-09 13:07:19 +02:00
|
|
|
const TEXT* relation_name,
|
|
|
|
const TEXT* field_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/***********************************************************
|
|
|
|
*
|
|
|
|
* 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
|
2003-09-09 13:07:19 +02:00
|
|
|
* is referenced in a view, return true, else return false
|
|
|
|
* CVC: The function never has a chance to return true because it punts.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
***********************************************************/
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2003-09-09 13:07:19 +02:00
|
|
|
bool retval = false;
|
2003-11-05 10:02:33 +01:00
|
|
|
const TEXT* view_name = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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
|
2003-09-09 13:07:19 +02:00
|
|
|
retval = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
view_name = Z.RDB$VIEW_NAME;
|
|
|
|
END_FOR;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (retval)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 206, field_name, relation_name, view_name, NULL,
|
2001-05-23 15:26:42 +02:00
|
|
|
NULL);
|
|
|
|
/* msg 206: Column %s from table %s is referenced in %s. */
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static bool check_sptrig_dependency(thread_db* tdbb,
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb,
|
2004-03-31 19:38:53 +02:00
|
|
|
Global* gbl,
|
2003-09-09 13:07:19 +02:00
|
|
|
const TEXT* relation_name,
|
|
|
|
const TEXT* field_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/***********************************************************
|
|
|
|
*
|
|
|
|
* 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
|
2003-09-09 13:07:19 +02:00
|
|
|
* or trigger. If the field is refereneced, return true, else return
|
|
|
|
* false, but true causes the function to punt instead.
|
2001-05-23 15:26:42 +02:00
|
|
|
***********************************************************/
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2003-09-09 13:07:19 +02:00
|
|
|
bool retval = false;
|
2003-11-05 10:02:33 +01:00
|
|
|
const TEXT* dep_name = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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
|
2003-09-09 13:07:19 +02:00
|
|
|
retval = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
dep_name = DEP.RDB$DEPENDENT_NAME;
|
|
|
|
END_FOR;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (retval)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 206, field_name, relation_name, dep_name, NULL,
|
2001-05-23 15:26:42 +02:00
|
|
|
NULL);
|
|
|
|
/* msg 206: Column %s from table %s is referenced in %s. */
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static void modify_lfield_index(thread_db* tdbb,
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb,
|
2004-03-31 19:38:53 +02:00
|
|
|
Global* gbl,
|
2003-09-09 13:07:19 +02:00
|
|
|
const TEXT* relation_name,
|
|
|
|
const TEXT* field_name,
|
|
|
|
const TEXT* new_fld_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/***********************************************************
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
***********************************************************/
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static bool field_exists(thread_db* tdbb,
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb,
|
2004-03-31 19:38:53 +02:00
|
|
|
Global* gbl,
|
2003-09-09 13:07:19 +02:00
|
|
|
const TEXT* relation_name,
|
|
|
|
const TEXT* field_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/***********************************************************
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
***********************************************************/
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2003-09-09 13:07:19 +02:00
|
|
|
bool retval = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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
|
2003-09-09 13:07:19 +02:00
|
|
|
retval = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
END_FOR;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
static bool domain_exists(thread_db* tdbb, Database* dbb, Global* gbl, const TEXT* field_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/***********************************************************
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
***********************************************************/
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2003-09-09 13:07:19 +02:00
|
|
|
bool retval = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
|
|
|
|
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ field_name
|
2003-09-09 13:07:19 +02:00
|
|
|
retval = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
END_FOR;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void DYN_modify_sql_field(Global* gbl,
|
2003-11-05 10:02:33 +01:00
|
|
|
const UCHAR** ptr,
|
|
|
|
const TEXT* relation_name,
|
2001-05-23 15:26:42 +02:00
|
|
|
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
|
|
|
**************************************/
|
2002-06-30 10:46:51 +02:00
|
|
|
SSHORT field_adjusted_count = 0;
|
2003-11-05 10:02:33 +01:00
|
|
|
const 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
|
|
|
|
2004-05-22 16:28:54 +02:00
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
2004-03-07 08:58:55 +01:00
|
|
|
Database* dbb = tdbb->tdbb_database;
|
2003-11-05 10:02:33 +01:00
|
|
|
|
|
|
|
dyn_fld* orig_fld = 0;
|
|
|
|
dyn_fld* new_fld = 0;
|
|
|
|
dyn_fld* dom_fld = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
try {
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
/* Allocate the field structures */
|
2004-03-28 11:10:30 +02:00
|
|
|
orig_fld = (dyn_fld*) gds__alloc(sizeof(struct dyn_fld));
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!orig_fld)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 211, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
MOVE_CLEAR(orig_fld, sizeof(struct dyn_fld));
|
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
new_fld = (dyn_fld*) gds__alloc(sizeof(struct dyn_fld));
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!new_fld)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 211, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
MOVE_CLEAR(new_fld, sizeof(struct dyn_fld));
|
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
dom_fld = (dyn_fld*) gds__alloc(sizeof(struct dyn_fld));
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!dom_fld)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 211, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
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);
|
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
|
|
|
jrd_req* first_request = NULL;
|
2003-09-09 13:07:19 +02:00
|
|
|
bool found = false;
|
2003-11-05 10:02:33 +01:00
|
|
|
bool dtype, scale, prec, subtype, charlen, collation, fldlen, nullflg,
|
|
|
|
charset;
|
|
|
|
dtype = scale = prec = subtype = charlen = collation = fldlen = nullflg =
|
|
|
|
charset = false;
|
2003-09-09 13:07:19 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
found = true;
|
2003-11-05 10:02:33 +01:00
|
|
|
bool has_dimensions = false;
|
|
|
|
bool update_domain = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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;
|
2004-02-20 07:43:27 +01:00
|
|
|
orig_fld->dyn_null_flag = FLD.RDB$NULL_FLAG != 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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;
|
2003-11-05 10:02:33 +01:00
|
|
|
has_dimensions = true;
|
2002-06-30 10:46:51 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-07-06 07:59:40 +02:00
|
|
|
UCHAR verb;
|
2003-11-08 17:40:17 +01:00
|
|
|
while ((verb = *(*ptr)++) != isc_dyn_end) {
|
2001-05-23 15:26:42 +02:00
|
|
|
switch (verb) {
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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);
|
2003-11-05 10:02:33 +01:00
|
|
|
update_domain = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_rel_name:
|
2001-05-23 15:26:42 +02:00
|
|
|
GET_STRING(ptr, new_fld->dyn_rel_name);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_length:
|
2003-11-05 10:02:33 +01:00
|
|
|
fldlen = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_dsc.dsc_length = DYN_get_number(ptr);
|
2002-06-30 10:46:51 +02:00
|
|
|
if (++field_adjusted_count > 2)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 5, err_one_type_change_only, NULL, NULL, NULL, NULL);
|
2002-06-30 10:46:51 +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:
|
|
|
|
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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_type:
|
2003-11-05 10:02:33 +01:00
|
|
|
dtype = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_dtype = DYN_get_number(ptr);
|
2002-06-30 10:46:51 +02:00
|
|
|
if (++field_adjusted_count > 2)
|
2003-11-05 10:02:33 +01: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_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;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_scale:
|
2003-11-05 10:02:33 +01:00
|
|
|
scale = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_dsc.dsc_scale = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case isc_dyn_fld_precision:
|
2003-11-05 10:02:33 +01:00
|
|
|
prec = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_precision = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_sub_type:
|
2003-11-05 10:02:33 +01:00
|
|
|
subtype = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_dsc.dsc_sub_type = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_char_length:
|
2003-11-05 10:02:33 +01:00
|
|
|
charlen = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_charlen = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_collation:
|
2003-11-05 10:02:33 +01:00
|
|
|
collation = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_collation = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_character_set:
|
2003-11-05 10:02:33 +01:00
|
|
|
charset = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
new_fld->dyn_charset = DYN_get_number(ptr);
|
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_dyn_fld_not_null:
|
2003-11-05 10:02:33 +01:00
|
|
|
nullflg = true;
|
2004-02-20 07:43:27 +01:00
|
|
|
new_fld->dyn_null_flag = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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
|
|
|
|
*/
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
case isc_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,
|
2003-08-28 15:16:03 +02:00
|
|
|
NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
END_FOR; /* FLD in RDB$FIELDS */
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
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) {
|
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
|
|
|
|
2004-04-11 09:14:27 +02:00
|
|
|
const ULONG retval = check_update_fld_type(orig_fld, dom_fld);
|
2003-09-09 13:07:19 +02:00
|
|
|
if (retval != FB_SUCCESS)
|
|
|
|
modify_err_punt(tdbb, retval, orig_fld, dom_fld);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* if the original definition was a base field type, remove the entries from RDB$FIELDS */
|
2003-11-05 10:02:33 +01:00
|
|
|
if (!strncmp(orig_fld->dyn_fld_source, IMPLICIT_DOMAIN_PREFIX,
|
|
|
|
IMPLICIT_DOMAIN_PREFIX_LEN))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
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 {
|
|
|
|
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);
|
2004-04-11 09:14:27 +02:00
|
|
|
const ULONG retval = check_update_fld_type(orig_fld, new_fld);
|
2003-09-09 13:07:19 +02:00
|
|
|
if (retval != FB_SUCCESS)
|
|
|
|
modify_err_punt(tdbb, retval, orig_fld, new_fld);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
*/
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
if (strncmp(orig_fld->dyn_fld_source, IMPLICIT_DOMAIN_PREFIX,
|
|
|
|
IMPLICIT_DOMAIN_PREFIX_LEN))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
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;
|
|
|
|
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
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 */
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
request = NULL;
|
|
|
|
}
|
|
|
|
} /* else not a domain */
|
|
|
|
request = first_request;
|
|
|
|
END_FOR; /* RFR IN RDB$RELATION_FIELDS */
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
request = NULL;
|
|
|
|
|
|
|
|
if (!found)
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 96, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* 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)
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(new_fld);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (dom_fld)
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(dom_fld);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (orig_fld)
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(orig_fld);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2004-03-01 04:35:23 +01:00
|
|
|
catch (const std::exception& ex) {
|
|
|
|
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
2001-12-24 03:51:06 +01:00
|
|
|
if (new_fld) {
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(new_fld);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dom_fld) {
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(dom_fld);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (orig_fld) {
|
2003-11-05 10:02:33 +01:00
|
|
|
gds__free(orig_fld);
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 95, NULL, NULL, NULL, NULL, NULL);
|
2001-12-24 03:51:06 +01:00
|
|
|
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-31 19:38:53 +02:00
|
|
|
void get_domain_type(thread_db* tdbb, Database* dbb, Global* gbl, dyn_fld* dom_fld)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g e t _ d o m a i n _ t y p e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2003-09-09 13:07:19 +02:00
|
|
|
* Retrieves the type information for a domain so
|
2001-05-23 15:26:42 +02:00
|
|
|
* that it can be compared to a local field before
|
|
|
|
* modifying the datatype of a field.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-03-20 15:57:40 +01:00
|
|
|
jrd_req* request = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
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,
|
2003-09-09 13:07:19 +02:00
|
|
|
FLD.RDB$CHARACTER_SET_ID,
|
|
|
|
FLD.RDB$COLLATION_ID);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
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;
|
2004-02-20 07:43:27 +01:00
|
|
|
dom_fld->dyn_null_flag = FLD.RDB$NULL_FLAG != 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
END_FOR;
|
2004-08-26 13:07:57 +02:00
|
|
|
CMP_release(tdbb, request);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-09-09 13:07:19 +02:00
|
|
|
static ULONG check_update_fld_type(const dyn_fld* orig_fld,
|
|
|
|
const dyn_fld* new_fld)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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
|
2002-11-14 09:33:08 +01:00
|
|
|
* made. If the conversion can be made, FB_SUCCESS is returned
|
2001-05-23 15:26:42 +02:00
|
|
|
**************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* 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:
|
|
|
|
{
|
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
|
|
|
|
2004-04-11 09:14:27 +02:00
|
|
|
const USHORT maxflen = DSC_string_length(&orig_fld->dyn_dsc);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-06-30 10:46:51 +02:00
|
|
|
/* We can have this assertion since this case is for both string fields. */
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(DSC_string_length(&new_fld->dyn_dsc) - maxflen
|
2002-06-30 10:46:51 +02:00
|
|
|
== new_fld->dyn_charbytelen - orig_fld->dyn_charbytelen);
|
2004-04-11 09:14:27 +02:00
|
|
|
// if (new_fld->dyn_dsc.dsc_length < maxflen)
|
2002-06-30 10:46:51 +02:00
|
|
|
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:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(FALSE);
|
2001-05-23 15:26:42 +02:00
|
|
|
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:
|
|
|
|
{
|
2004-04-11 09:14:27 +02:00
|
|
|
const USHORT maxflen = DSC_string_length(&orig_fld->dyn_dsc);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-04-11 09:14:27 +02:00
|
|
|
// CVC: Solve bug #910423, missing DSC_string_length call.
|
|
|
|
// 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:
|
|
|
|
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:
|
|
|
|
{
|
2004-04-11 09:14:27 +02:00
|
|
|
const USHORT maxflen = DSC_string_length(&orig_fld->dyn_dsc);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-04-11 09:14:27 +02:00
|
|
|
// CVC: Solve bug #910423, missing DSC_string_length call.
|
|
|
|
// 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:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(FALSE);
|
2001-05-23 15:26:42 +02:00
|
|
|
return 87; /* MODIFY RDB$FIELDS FAILED */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(FALSE);
|
2001-05-23 15:26:42 +02:00
|
|
|
return 87; /* MODIFY RDB$FIELDS FAILED */
|
|
|
|
}
|
2002-11-14 09:33:08 +01:00
|
|
|
return FB_SUCCESS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static void modify_err_punt(thread_db* tdbb,
|
2001-05-23 15:26:42 +02:00
|
|
|
ULONG errorcode,
|
2003-09-09 13:07:19 +02:00
|
|
|
const dyn_fld* orig_fld_def,
|
|
|
|
const dyn_fld* new_fld_def)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* 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:
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 207, orig_fld_def->dyn_fld_name, NULL, NULL,
|
2001-05-23 15:26:42 +02:00
|
|
|
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:
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 210, orig_fld_def->dyn_fld_name, NULL, NULL,
|
2001-05-23 15:26:42 +02:00
|
|
|
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* */
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false,
|
2001-05-23 15:26:42 +02:00
|
|
|
208,
|
|
|
|
orig_fld_def->dyn_fld_name,
|
2004-01-21 08:18:30 +01:00
|
|
|
(TEXT*)(IPTR)DSC_string_length(&orig_fld_def->dyn_dsc),
|
2001-05-23 15:26:42 +02:00
|
|
|
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));
|
|
|
|
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(false, 209, orig_fld_def->dyn_fld_name, orig_type,
|
2001-05-23 15:26:42 +02:00
|
|
|
new_type, NULL, NULL);
|
|
|
|
/* Cannot convert base type %s to base type %s. */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2003-11-05 10:02:33 +01:00
|
|
|
DYN_error_punt(true, 95, NULL, NULL, NULL, NULL, NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* msg 95: "MODIFY RDB$RELATION_FIELDS failed" */
|
|
|
|
}
|
|
|
|
}
|
2003-09-09 13:07:19 +02:00
|
|
|
|