8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 06:43:02 +01:00
firebird-mirror/src/jrd/dyn_def.epp

2210 lines
55 KiB
Plaintext
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Data Definition Utility
* MODULE: dyn_define.epp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Dynamic data definition DYN_define_<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): ______________________________________.
*
2002-06-30 10:46:51 +02:00
* 23-May-2001 Claudio Valderrama - Forbid zero length identifiers,
* they are not ANSI SQL compliant.
* 2001.10.08 Claudio Valderrama: Add case isc_dyn_system_flag to
* DYN_define_trigger() in order to receive values for special triggers
* as defined in constants.h.
* 2001.10.08 Ann Harrison: Changed dyn_create_index so it doesn't consider
* simple unique indexes when finding a "referred index", but only
* indexes that support unique constraints or primary keys.
2005-05-28 00:45:31 +02:00
* 26-Sep-2001 Paul Beach - External File Directory Config. Parameter
* 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY)
* 2002.08.10 Dmitry Yemanov: ALTER VIEW
2002-10-30 07:40:58 +01:00
*
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
*
2005-05-28 00:45:31 +02:00
* 2004.01.16 Vlad Horsun: added support for default parameters
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2010-01-10 18:56:57 +01:00
#include "dyn_consts.h"
#include "../common/classes/fb_string.h"
2001-05-23 15:26:42 +02:00
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../jrd/common.h"
#include "../jrd/jrd.h"
#include "../jrd/ods.h"
#include "../jrd/tra.h"
#include "../jrd/scl.h"
#include "../jrd/drq.h"
#include "../jrd/req.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/met.h"
#include "../jrd/btr.h"
#include "../jrd/ini.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/intl.h"
#include "../jrd/dyn.h"
#include "../jrd/gdsassert.h"
#include "../jrd/blb_proto.h"
#include "../jrd/cmp_proto.h"
#include "../jrd/dyn_proto.h"
#include "../jrd/dyn_df_proto.h"
#include "../jrd/dyn_ut_proto.h"
#include "../jrd/err_proto.h"
#include "../jrd/exe_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/inf_proto.h"
#include "../jrd/intl_proto.h"
#include "../jrd/isc_f_proto.h"
#include "../jrd/met_proto.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/vio_proto.h"
#include "../jrd/scl_proto.h"
#include "../jrd/gdsassert.h"
#include "../jrd/os/path_utils.h"
2003-12-31 06:36:12 +01:00
#include "../common/utils_proto.h"
2005-05-28 00:45:31 +02:00
#include "../jrd/IntlManager.h"
#include "../jrd/IntlUtil.h"
#include "../dsql/DdlNodes.h"
2001-05-23 15:26:42 +02:00
using MsgFormat::SafeArg;
using namespace Jrd;
using namespace Firebird;
typedef Firebird::ObjectsArray<Firebird::MetaName> MetaNameArray;
2004-04-29 13:16:31 +02:00
const int FOR_KEY_UPD_CASCADE = 0x01;
const int FOR_KEY_UPD_NULL = 0x02;
const int FOR_KEY_UPD_DEFAULT = 0x04;
const int FOR_KEY_UPD_NONE = 0x08;
const int FOR_KEY_DEL_CASCADE = 0x10;
const int FOR_KEY_DEL_NULL = 0x20;
const int FOR_KEY_DEL_DEFAULT = 0x40;
const int FOR_KEY_DEL_NONE = 0x80;
2001-05-23 15:26:42 +02:00
DATABASE DB = STATIC "ODS.RDB";
2001-05-23 15:26:42 +02:00
static bool is_it_user_name(Global*, const Firebird::MetaName&, thread_db*);
2001-05-23 15:26:42 +02:00
void DYN_define_file(Global* gbl,
const UCHAR** ptr,
2001-12-24 03:51:06 +01:00
SLONG shadow_number,
SLONG* start,
USHORT msg)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ f i l e
*
**************************************
*
* Functional description
* Define a database or shadow file.
*
**************************************/
UCHAR verb;
SLONG temp;
USHORT man_auto;
SSHORT id;
2001-05-23 15:26:42 +02:00
thread_db* tdbb = JRD_get_thread_data();
Database* dbb = tdbb->getDatabase();
2001-05-23 15:26:42 +02:00
if (!tdbb->getAttachment()->locksmith())
{
ERR_post(Arg::Gds(isc_adm_task_denied));
}
2001-12-24 03:51:06 +01:00
try {
2009-11-25 05:06:48 +01:00
id = -1;
Firebird::PathName temp_f;
GET_STRING(ptr, temp_f);
if (!ISC_expand_filename(temp_f, false))
2009-11-26 01:20:59 +01:00
DYN_error_punt(false, 231); // File name is invalid.
2001-05-23 15:26:42 +02:00
2010-04-18 03:10:05 +02:00
if (dbb->dbb_filename == temp_f)
2009-11-25 05:06:48 +01:00
DYN_error_punt(false, 166);
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, id = drq_l_files, DYN_REQUESTS);
2009-11-25 05:06:48 +01:00
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIRST 1 X IN RDB$FILES WITH X.RDB$FILE_NAME EQ temp_f.c_str()
2010-04-18 03:10:05 +02:00
{
2009-11-25 05:06:48 +01:00
DYN_error_punt(false, 166);
2010-04-18 03:10:05 +02:00
}
END_FOR
2001-05-23 15:26:42 +02:00
2010-04-18 03:10:05 +02:00
request.reset(tdbb, id = drq_s_files, DYN_REQUESTS);
2009-11-25 05:06:48 +01:00
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FILES
2010-04-18 03:10:05 +02:00
{
2009-11-25 05:06:48 +01:00
temp_f.copyTo(X.RDB$FILE_NAME, sizeof(X.RDB$FILE_NAME));
X.RDB$SHADOW_NUMBER = (SSHORT)shadow_number;
X.RDB$FILE_FLAGS = 0;
X.RDB$FILE_FLAGS.NULL = FALSE;
X.RDB$FILE_START.NULL = TRUE;
X.RDB$FILE_LENGTH.NULL = TRUE;
while ((verb = *(*ptr)++) != isc_dyn_end)
2001-05-23 15:26:42 +02:00
{
2009-11-25 05:06:48 +01:00
switch (verb)
{
case isc_dyn_file_start:
temp = DYN_get_number(ptr);
*start = MAX(*start, temp);
X.RDB$FILE_START = *start;
X.RDB$FILE_START.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_file_length:
X.RDB$FILE_LENGTH = DYN_get_number(ptr);
X.RDB$FILE_LENGTH.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_shadow_man_auto:
man_auto = (USHORT)DYN_get_number(ptr);
if (man_auto)
X.RDB$FILE_FLAGS |= FILE_manual;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_shadow_conditional:
if (DYN_get_number(ptr))
X.RDB$FILE_FLAGS |= FILE_conditional;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
default:
DYN_unsupported_verb();
}
2001-05-23 15:26:42 +02:00
}
2009-11-25 05:06:48 +01:00
*start += X.RDB$FILE_LENGTH;
2010-04-18 03:10:05 +02:00
}
END_STORE
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
}
2009-01-20 09:33:59 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2001-12-24 03:51:06 +01:00
if (id == drq_l_files)
DYN_error_punt(false, 166);
2001-12-24 03:51:06 +01:00
else
DYN_error_punt(true, msg);
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
}
2009-11-25 05:06:48 +01:00
void DYN_define_difference(Global* gbl, const UCHAR** ptr)
{
/**************************************
*
* D Y N _ d e f i n e _ d i f f e r e n c e
*
**************************************
*
* Functional description
* Define backup difference file.
*
**************************************/
SSHORT id = -1;
thread_db* tdbb = JRD_get_thread_data();
if (!tdbb->getAttachment()->locksmith())
{
ERR_post(Arg::Gds(isc_adm_task_denied));
}
2009-11-26 01:20:59 +01:00
try
{
2009-11-25 05:06:48 +01:00
bool found = false;
id = drq_l_difference;
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_l_difference, DYN_REQUESTS);
2009-11-25 05:06:48 +01:00
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIL IN RDB$FILES
2010-04-18 03:10:05 +02:00
{
2009-11-25 05:06:48 +01:00
if (FIL.RDB$FILE_FLAGS & FILE_difference)
found = true;
}
2010-04-18 03:10:05 +02:00
END_FOR
2010-04-18 03:10:05 +02:00
if (found)
2009-11-25 05:06:48 +01:00
goto dyn_punt_216;
2010-04-18 03:10:05 +02:00
request.reset(tdbb, drq_s_difference, DYN_REQUESTS);
2009-11-25 05:06:48 +01:00
id = drq_s_difference;
2010-04-18 03:10:05 +02:00
2009-11-25 05:06:48 +01:00
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FILES
2010-04-18 03:10:05 +02:00
{
2009-11-25 05:06:48 +01:00
GET_STRING(ptr, X.RDB$FILE_NAME);
X.RDB$FILE_FLAGS = FILE_difference;
X.RDB$FILE_FLAGS.NULL = FALSE;
X.RDB$FILE_START = 0;
X.RDB$FILE_START.NULL = FALSE;
X.RDB$FILE_LENGTH.NULL = TRUE;
X.RDB$SHADOW_NUMBER.NULL = TRUE;
2010-04-18 03:10:05 +02:00
}
END_STORE
}
2009-01-20 09:33:59 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
if (id == drq_s_difference)
{
DYN_error_punt(true, 150);
2009-11-21 08:38:05 +01:00
// msg 150: STORE RDB$FILES failed
}
else
{
DYN_error_punt(true, 156);
2009-11-21 08:38:05 +01:00
// msg 156: Difference file lookup failed
}
}
return;
2003-08-12 21:54:34 +02:00
dyn_punt_216:
DYN_error_punt(false, 216);
2009-11-21 08:38:05 +01:00
// msg 216: "Difference file is already defined"
}
void DYN_define_filter( Global* gbl, const UCHAR** ptr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ f i l t e r
*
**************************************
*
* Functional description
* Define a blob filter.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
2001-05-23 15:26:42 +02:00
Firebird::MetaName filter_name;
2002-06-30 10:46:51 +02:00
GET_STRING(ptr, filter_name);
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_filters, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
bool b_ending_store = false;
try {
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
2005-05-28 00:45:31 +02:00
X IN RDB$FILTERS USING
strcpy(X.RDB$FUNCTION_NAME, filter_name.c_str());
2001-12-25 05:10:23 +01:00
X.RDB$OUTPUT_SUB_TYPE.NULL = TRUE;
X.RDB$INPUT_SUB_TYPE.NULL = TRUE;
X.RDB$MODULE_NAME.NULL = TRUE;
X.RDB$ENTRYPOINT.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
2010-04-18 03:10:05 +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
{
2001-12-25 05:10:23 +01:00
switch (verb)
{
2003-11-08 17:40:17 +01:00
case isc_dyn_filter_in_subtype:
2001-12-25 05:10:23 +01:00
X.RDB$INPUT_SUB_TYPE = (SSHORT)DYN_get_number(ptr);
X.RDB$INPUT_SUB_TYPE.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_filter_out_subtype:
2001-12-25 05:10:23 +01:00
X.RDB$OUTPUT_SUB_TYPE = (SSHORT)DYN_get_number(ptr);
X.RDB$OUTPUT_SUB_TYPE.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_func_module_name:
2001-12-25 05:10:23 +01:00
GET_STRING(ptr, X.RDB$MODULE_NAME);
X.RDB$MODULE_NAME.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_func_entry_point:
2001-12-25 05:10:23 +01:00
GET_STRING(ptr, X.RDB$ENTRYPOINT);
X.RDB$ENTRYPOINT.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
default:
DYN_unsupported_verb();
}
2001-05-23 15:26:42 +02:00
}
2001-12-25 05:10:23 +01:00
}
2010-04-18 03:10:05 +02:00
END_STORE
2001-12-25 05:10:23 +01:00
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2009-11-25 05:06:48 +01:00
if (b_ending_store)
{
DYN_error_punt(true, 7);
2009-11-21 08:38:05 +01:00
// msg 7: "DEFINE BLOB FILTER failed"
2001-05-23 15:26:42 +02:00
}
2001-12-25 05:10:23 +01:00
throw;
}
2001-05-23 15:26:42 +02:00
}
void DYN_define_function( Global* gbl, const UCHAR** ptr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ f u n c t i o n
*
**************************************
*
* Functional description
* Define a user defined function.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
2001-05-23 15:26:42 +02:00
Firebird::MetaName function_name;
2002-06-30 10:46:51 +02:00
GET_STRING(ptr, function_name);
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
DDL_TRIGGER_CREATE_FUNCTION, function_name, gbl->sqlText);
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_funcs, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
bool b_ending_store = false;
try {
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
2005-05-28 00:45:31 +02:00
X IN RDB$FUNCTIONS USING
2010-04-18 03:10:05 +02:00
{
strcpy(X.RDB$FUNCTION_NAME, function_name.c_str());
2001-12-25 05:10:23 +01:00
X.RDB$RETURN_ARGUMENT.NULL = TRUE;
X.RDB$QUERY_NAME.NULL = TRUE;
X.RDB$MODULE_NAME.NULL = TRUE;
X.RDB$ENTRYPOINT.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
2009-12-21 17:48:06 +01:00
X.RDB$LEGACY_FLAG = 1;
X.RDB$LEGACY_FLAG.NULL = FALSE;
X.RDB$INVARIANT_FLAG.NULL = TRUE;
X.RDB$ENGINE_NAME.NULL = TRUE;
UCHAR verb;
2003-11-08 17:40:17 +01:00
while ((verb = *(*ptr)++) != isc_dyn_end)
2001-05-23 15:26:42 +02:00
{
2001-12-25 05:10:23 +01:00
switch (verb)
{
2003-11-08 17:40:17 +01:00
case isc_dyn_func_return_argument:
2001-12-25 05:10:23 +01:00
X.RDB$RETURN_ARGUMENT = (SSHORT)DYN_get_number(ptr);
X.RDB$RETURN_ARGUMENT.NULL = FALSE;
if (X.RDB$RETURN_ARGUMENT > MAX_UDF_ARGUMENTS)
DYN_error_punt(true, 10);
2009-11-21 08:38:05 +01:00
// msg 10: "DEFINE FUNCTION failed"
2001-12-25 05:10:23 +01:00
break;
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_func_module_name:
2001-12-25 05:10:23 +01:00
GET_STRING(ptr, X.RDB$MODULE_NAME);
X.RDB$MODULE_NAME.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_query_name:
2001-12-25 05:10:23 +01:00
GET_STRING(ptr, X.RDB$QUERY_NAME);
X.RDB$QUERY_NAME.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_func_entry_point:
2001-12-25 05:10:23 +01:00
GET_STRING(ptr, X.RDB$ENTRYPOINT);
X.RDB$ENTRYPOINT.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
default:
--(*ptr);
2010-01-24 16:16:23 +01:00
{
MetaNameProxy tmp(X.RDB$FUNCTION_NAME);
DYN_execute(gbl, ptr, NULL, NULL, NULL, &tmp, NULL);
2010-01-24 16:16:23 +01:00
}
2001-12-25 05:10:23 +01:00
}
2001-05-23 15:26:42 +02:00
}
2001-12-25 05:10:23 +01:00
b_ending_store = true;
}
2010-04-18 03:10:05 +02:00
END_STORE
2001-12-25 05:10:23 +01:00
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2009-11-25 05:06:48 +01:00
if (b_ending_store)
{
DYN_error_punt(true, 10);
2009-11-21 08:38:05 +01:00
// msg 10: "DEFINE FUNCTION failed"
2001-05-23 15:26:42 +02:00
}
2001-12-25 05:10:23 +01:00
throw;
2001-12-24 03:51:06 +01:00
}
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
DDL_TRIGGER_CREATE_FUNCTION, function_name, gbl->sqlText);
2001-05-23 15:26:42 +02:00
}
void DYN_define_function_arg(Global* gbl, const UCHAR** ptr, Firebird::MetaName* function_name)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ f u n c t i o n _ a r g
*
**************************************
*
* Functional description
* Define a user defined function argument.
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
2005-05-28 00:45:31 +02:00
2009-11-26 01:20:59 +01:00
try
{
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_func_args, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$FUNCTION_ARGUMENTS
2010-04-18 03:10:05 +02:00
{
2009-11-25 05:06:48 +01:00
X.RDB$ARGUMENT_POSITION = (SSHORT)DYN_get_number(ptr);
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
if (X.RDB$ARGUMENT_POSITION > MAX_UDF_ARGUMENTS)
DYN_error_punt(true, 12); // msg 12: "DEFINE FUNCTION ARGUMENT failed"
2009-11-25 05:06:48 +01:00
if (function_name)
2001-05-23 15:26:42 +02:00
{
2009-11-25 05:06:48 +01:00
strcpy(X.RDB$FUNCTION_NAME, function_name->c_str());
2001-05-23 15:26:42 +02:00
X.RDB$FUNCTION_NAME.NULL = FALSE;
2009-11-25 05:06:48 +01:00
}
else
X.RDB$FUNCTION_NAME.NULL = TRUE;
X.RDB$MECHANISM.NULL = TRUE;
X.RDB$FIELD_TYPE.NULL = TRUE;
X.RDB$FIELD_SCALE.NULL = TRUE;
X.RDB$FIELD_LENGTH.NULL = TRUE;
X.RDB$FIELD_SUB_TYPE.NULL = TRUE;
X.RDB$CHARACTER_SET_ID.NULL = TRUE;
X.RDB$FIELD_PRECISION.NULL = TRUE;
X.RDB$CHARACTER_LENGTH.NULL = TRUE;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
UCHAR verb;
while ((verb = *(*ptr)++) != isc_dyn_end)
switch (verb)
{
case isc_dyn_function_name:
GET_STRING(ptr, X.RDB$FUNCTION_NAME);
X.RDB$FUNCTION_NAME.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_func_mechanism:
X.RDB$MECHANISM = (SSHORT)DYN_get_number(ptr);
X.RDB$MECHANISM.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_fld_type:
X.RDB$FIELD_TYPE = (SSHORT)DYN_get_number(ptr);
X.RDB$FIELD_TYPE.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_fld_sub_type:
X.RDB$FIELD_SUB_TYPE = (SSHORT)DYN_get_number(ptr);
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_fld_scale:
X.RDB$FIELD_SCALE = (SSHORT)DYN_get_number(ptr);
X.RDB$FIELD_SCALE.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_fld_length:
X.RDB$FIELD_LENGTH = (SSHORT)DYN_get_number(ptr);
X.RDB$FIELD_LENGTH.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_fld_character_set:
X.RDB$CHARACTER_SET_ID = (SSHORT)DYN_get_number(ptr);
X.RDB$CHARACTER_SET_ID.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
case isc_dyn_fld_precision:
X.RDB$FIELD_PRECISION = (SSHORT)DYN_get_number(ptr);
X.RDB$FIELD_PRECISION.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
// Ignore the field character length as the system UDF parameter
// table has no place to store the information
// But IB6/FB has the place for this information. CVC 2001.
case isc_dyn_fld_char_length:
X.RDB$CHARACTER_LENGTH = (SSHORT)DYN_get_number (ptr);
X.RDB$CHARACTER_LENGTH.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
default:
DYN_unsupported_verb();
}
}
2010-04-18 03:10:05 +02:00
END_STORE
2001-12-24 03:51:06 +01:00
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_error_punt(true, 12);
2009-11-21 08:38:05 +01:00
// msg 12: "DEFINE FUNCTION ARGUMENT failed"
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
}
void DYN_define_index(Global* gbl,
const UCHAR** ptr,
const Firebird::MetaName* relation_name,
2001-05-23 15:26:42 +02:00
UCHAR index_type,
Firebird::MetaName* new_index_name,
Firebird::MetaName* referred_index_name,
Firebird::MetaName* cnst_name,
2001-05-23 15:26:42 +02:00
UCHAR* ri_actionP)
{
/**************************************
*
* D Y N _ d e f i n e _ i n d e x
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement that creates an index.
2001-05-23 15:26:42 +02:00
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
Firebird::MetaName index_name;
2001-12-25 05:10:23 +01:00
UCHAR verb;
Firebird::MetaName trigger_name;
2001-05-23 15:26:42 +02:00
if (ri_actionP)
*ri_actionP = 0;
2001-05-23 15:26:42 +02:00
2002-06-30 10:46:51 +02:00
GET_STRING(ptr, index_name);
2009-11-26 01:20:59 +01:00
if (index_name.isEmpty())
DYN_UTIL_generate_index_name(tdbb, gbl->gbl_transaction, index_name, index_type);
2002-06-30 10:46:51 +02:00
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
DDL_TRIGGER_CREATE_INDEX, index_name, gbl->sqlText);
try
{
DYN_UTIL_check_unique_name(tdbb, gbl->gbl_transaction, index_name, obj_index);
}
catch (const Exception& ex)
{
stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_error_punt(true, 21); // msg 21: "STORE RDB$INDICES failed"
}
2005-05-28 00:45:31 +02:00
try
2010-04-18 03:10:05 +02:00
{
CreateIndexNode::Definition definition;
definition.type = index_type;
if (new_index_name)
*new_index_name = index_name;
2001-05-23 15:26:42 +02:00
if (relation_name)
definition.relation = *relation_name;
2003-11-08 17:40:17 +01:00
else if (*(*ptr)++ == isc_dyn_rel_name)
GET_STRING(ptr, definition.relation);
2001-05-23 15:26:42 +02:00
else
DYN_error_punt(false, 14); // msg 14: "No relation specified for index"
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
while ((verb = *(*ptr)++) != isc_dyn_end)
2010-04-18 03:10:05 +02:00
{
2001-05-23 15:26:42 +02:00
switch (verb)
{
case isc_dyn_idx_unique:
definition.unique = bool(DYN_get_number(ptr));
break;
2001-05-23 15:26:42 +02:00
case isc_dyn_idx_inactive:
definition.inactive = bool(DYN_get_number(ptr));
break;
2001-05-23 15:26:42 +02:00
case isc_dyn_idx_type:
definition.descending = bool(DYN_get_number(ptr));
break;
2005-05-28 00:45:31 +02:00
case isc_dyn_fld_name:
{
MetaName& str = definition.columns.add();
GET_STRING(ptr, str);
break;
}
2001-05-23 15:26:42 +02:00
case isc_dyn_fld_computed_blr:
DYN_put_blr_blob(gbl, ptr, &definition.expressionBlr);
break;
2001-05-23 15:26:42 +02:00
case isc_dyn_fld_computed_source:
DYN_put_text_blob(gbl, ptr, &definition.expressionSource);
break;
2001-05-23 15:26:42 +02:00
// for foreign keys, point to the corresponding relation
2001-05-23 15:26:42 +02:00
case isc_dyn_idx_foreign_key:
GET_STRING(ptr, definition.refRelation);
2001-05-23 15:26:42 +02:00
break;
case isc_dyn_idx_ref_column:
2001-05-23 15:26:42 +02:00
{
MetaName& str = definition.refColumns.add();
GET_STRING(ptr, str);
2001-05-23 15:26:42 +02:00
break;
}
case isc_dyn_foreign_key_delete:
fb_assert(ri_actionP != NULL);
switch (verb = *(*ptr)++)
{
case isc_dyn_foreign_key_cascade:
*ri_actionP |= FOR_KEY_DEL_CASCADE;
if ((verb = *(*ptr)++) == isc_dyn_def_trigger)
{
DYN_define_trigger(gbl, ptr, relation_name, &trigger_name, true);
fb_assert(cnst_name);
DYN_UTIL_store_check_constraints(tdbb, gbl->gbl_transaction, *cnst_name, trigger_name);
}
else
DYN_unsupported_verb();
break;
2010-04-18 03:10:05 +02:00
case isc_dyn_foreign_key_null:
*ri_actionP |= FOR_KEY_DEL_NULL;
if ((verb = *(*ptr)++) == isc_dyn_def_trigger)
{
DYN_define_trigger(gbl, ptr, relation_name, &trigger_name, true);
fb_assert(cnst_name);
DYN_UTIL_store_check_constraints(tdbb, gbl->gbl_transaction, *cnst_name, trigger_name);
}
else
DYN_unsupported_verb();
break;
2001-05-23 15:26:42 +02:00
case isc_dyn_foreign_key_default:
*ri_actionP |= FOR_KEY_DEL_DEFAULT;
if ((verb = *(*ptr)++) == isc_dyn_def_trigger)
{
DYN_define_trigger(gbl, ptr, relation_name, &trigger_name, true);
fb_assert(cnst_name);
DYN_UTIL_store_check_constraints(tdbb, gbl->gbl_transaction, *cnst_name, trigger_name);
}
else
DYN_unsupported_verb();
break;
2001-05-23 15:26:42 +02:00
case isc_dyn_foreign_key_none:
*ri_actionP |= FOR_KEY_DEL_NONE;
break;
2001-05-23 15:26:42 +02:00
default:
fb_assert(0); // should not come here
DYN_unsupported_verb();
2001-05-23 15:26:42 +02:00
}
break;
2001-05-23 15:26:42 +02:00
case isc_dyn_foreign_key_update:
fb_assert(ri_actionP != NULL);
switch (verb = *(*ptr)++)
{
case isc_dyn_foreign_key_cascade:
*ri_actionP |= FOR_KEY_UPD_CASCADE;
if ((verb = *(*ptr)++) == isc_dyn_def_trigger)
{
DYN_define_trigger(gbl, ptr, relation_name, &trigger_name, true);
fb_assert(cnst_name);
DYN_UTIL_store_check_constraints(tdbb, gbl->gbl_transaction, *cnst_name, trigger_name);
}
else
DYN_unsupported_verb();
break;
case isc_dyn_foreign_key_null:
*ri_actionP |= FOR_KEY_UPD_NULL;
if ((verb = *(*ptr)++) == isc_dyn_def_trigger)
{
DYN_define_trigger(gbl, ptr, relation_name, &trigger_name, true);
fb_assert(cnst_name);
DYN_UTIL_store_check_constraints(tdbb, gbl->gbl_transaction, *cnst_name, trigger_name);
}
else
DYN_unsupported_verb();
break;
2008-12-18 11:57:12 +01:00
case isc_dyn_foreign_key_default:
*ri_actionP |= FOR_KEY_UPD_DEFAULT;
if ((verb = *(*ptr)++) == isc_dyn_def_trigger)
{
DYN_define_trigger(gbl, ptr, relation_name, &trigger_name, true);
fb_assert(cnst_name);
DYN_UTIL_store_check_constraints(tdbb, gbl->gbl_transaction, *cnst_name, trigger_name);
}
else
DYN_unsupported_verb();
break;
case isc_dyn_foreign_key_none:
*ri_actionP |= FOR_KEY_UPD_NONE;
break;
2001-05-23 15:26:42 +02:00
default:
fb_assert(0); // should not come here
DYN_unsupported_verb();
}
break;
2001-05-23 15:26:42 +02:00
default:
DYN_unsupported_verb();
2006-10-02 04:39:45 +02:00
}
2001-05-23 15:26:42 +02:00
}
CreateIndexNode::store(tdbb, gbl->gbl_transaction, index_name, definition,
referred_index_name);
2001-12-24 03:51:06 +01:00
}
catch (const Exception& ex)
2009-01-14 10:19:00 +01:00
{
stuff_exception(tdbb->tdbb_status_vector, ex);
throw;
2001-12-24 03:51:06 +01:00
}
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
DDL_TRIGGER_CREATE_INDEX, index_name, gbl->sqlText);
2001-05-23 15:26:42 +02:00
}
void DYN_define_local_field(Global* gbl,
const UCHAR** ptr,
const Firebird::MetaName* relation_name,
Firebird::MetaName* field_name)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ l o c a l _ f i e l d
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement.
*
**************************************/
UCHAR verb;
USHORT dtype, length, clength, precision;
2001-05-23 15:26:42 +02:00
SSHORT stype, scale;
SSHORT charset_id;
SLONG fld_pos;
thread_db* tdbb = JRD_get_thread_data();
2001-05-23 15:26:42 +02:00
Firebird::MetaName local_field_name;
2002-06-30 10:46:51 +02:00
GET_STRING(ptr, local_field_name);
SSHORT id = -1;
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
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_lfields, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
id = drq_s_lfields;
bool lflag, sflag, slflag, scflag, clflag, prflag;
scflag = lflag = sflag = slflag = clflag = prflag = false;
bool charset_id_flag = false;
const UCHAR* blr = NULL;
const UCHAR* source = NULL;
Firebird::MetaName relation_buffer;
2001-05-23 15:26:42 +02:00
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
2005-05-28 00:45:31 +02:00
RFR IN RDB$RELATION_FIELDS
2010-04-18 03:10:05 +02:00
{
strcpy(RFR.RDB$FIELD_NAME, local_field_name.c_str());
2001-05-23 15:26:42 +02:00
strcpy(RFR.RDB$FIELD_SOURCE, RFR.RDB$FIELD_NAME);
if (field_name) {
*field_name = RFR.RDB$FIELD_NAME;
}
2001-05-23 15:26:42 +02:00
RFR.RDB$RELATION_NAME.NULL = TRUE;
2009-11-25 05:06:48 +01:00
if (relation_name)
{
strcpy(RFR.RDB$RELATION_NAME, relation_name->c_str());
2001-05-23 15:26:42 +02:00
RFR.RDB$RELATION_NAME.NULL = FALSE;
}
RFR.RDB$SYSTEM_FLAG = 0;
RFR.RDB$SYSTEM_FLAG.NULL = FALSE;
RFR.RDB$NULL_FLAG.NULL = TRUE;
RFR.RDB$BASE_FIELD.NULL = TRUE;
RFR.RDB$UPDATE_FLAG.NULL = TRUE;
RFR.RDB$FIELD_POSITION.NULL = TRUE;
RFR.RDB$VIEW_CONTEXT.NULL = TRUE;
RFR.RDB$QUERY_NAME.NULL = TRUE;
RFR.RDB$QUERY_HEADER.NULL = TRUE;
RFR.RDB$SECURITY_CLASS.NULL = TRUE;
RFR.RDB$DEFAULT_VALUE.NULL = TRUE;
RFR.RDB$DEFAULT_SOURCE.NULL = TRUE;
RFR.RDB$EDIT_STRING.NULL = TRUE;
RFR.RDB$COLLATION_ID.NULL = TRUE;
RFR.RDB$GENERATOR_NAME.NULL = TRUE;
RFR.RDB$IDENTITY_TYPE.NULL = TRUE;
2008-12-18 11:57:12 +01:00
bool has_default = false;
2008-12-18 11:57:12 +01:00
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:
GET_STRING(ptr, relation_buffer);
relation_name = &relation_buffer;
strcpy(RFR.RDB$RELATION_NAME, relation_name->c_str());
2001-05-23 15:26:42 +02:00
RFR.RDB$RELATION_NAME.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_source:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, RFR.RDB$FIELD_SOURCE);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_base_fld:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, RFR.RDB$BASE_FIELD);
RFR.RDB$BASE_FIELD.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_query_name:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, RFR.RDB$QUERY_NAME);
RFR.RDB$QUERY_NAME.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_query_header:
2001-05-23 15:26:42 +02:00
DYN_put_blr_blob(gbl, ptr, &RFR.RDB$QUERY_HEADER);
RFR.RDB$QUERY_HEADER.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_edit_string:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, RFR.RDB$EDIT_STRING);
RFR.RDB$EDIT_STRING.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_position:
2001-05-23 15:26:42 +02:00
RFR.RDB$FIELD_POSITION = (SSHORT)DYN_get_number(ptr);
RFR.RDB$FIELD_POSITION.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_system_flag:
2001-05-23 15:26:42 +02:00
RFR.RDB$SYSTEM_FLAG = (SSHORT)DYN_get_number(ptr);
RFR.RDB$SYSTEM_FLAG.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_update_flag:
case isc_dyn_update_flag:
2001-05-23 15:26:42 +02:00
RFR.RDB$UPDATE_FLAG = (SSHORT)DYN_get_number(ptr);
RFR.RDB$UPDATE_FLAG.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_view_context:
2001-05-23 15:26:42 +02:00
RFR.RDB$VIEW_CONTEXT = (SSHORT)DYN_get_number(ptr);
RFR.RDB$VIEW_CONTEXT.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, RFR.RDB$SECURITY_CLASS);
RFR.RDB$SECURITY_CLASS.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_computed_blr:
2001-05-23 15:26:42 +02:00
DYN_UTIL_generate_field_name(tdbb, gbl, RFR.RDB$FIELD_SOURCE);
blr = *ptr;
DYN_skip_attribute(ptr);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_computed_source:
source = *ptr;
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_value:
has_default = true;
2001-05-23 15:26:42 +02:00
RFR.RDB$DEFAULT_VALUE.NULL = FALSE;
DYN_put_blr_blob(gbl, ptr, &RFR.RDB$DEFAULT_VALUE);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_default_source:
has_default = true;
2001-05-23 15:26:42 +02:00
RFR.RDB$DEFAULT_SOURCE.NULL = FALSE;
DYN_put_text_blob(gbl, ptr, &RFR.RDB$DEFAULT_SOURCE);
break;
case isc_dyn_fld_identity:
{
MetaName sequenceName;
DYN_UTIL_generate_generator_name(tdbb, sequenceName);
CreateSequenceNode::store(tdbb, gbl->gbl_transaction, sequenceName,
fb_sysflag_identity_generator);
strcpy(RFR.RDB$GENERATOR_NAME, sequenceName.c_str());
RFR.RDB$GENERATOR_NAME.NULL = FALSE;
RFR.RDB$IDENTITY_TYPE = IDENT_TYPE_BY_DEFAULT;
RFR.RDB$IDENTITY_TYPE.NULL = FALSE;
break;
}
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_not_null:
2001-05-23 15:26:42 +02:00
RFR.RDB$NULL_FLAG.NULL = FALSE;
RFR.RDB$NULL_FLAG = TRUE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_type:
2001-05-23 15:26:42 +02:00
dtype = (USHORT)DYN_get_number(ptr);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_length:
2001-05-23 15:26:42 +02:00
length = (USHORT)DYN_get_number(ptr);
lflag = true;
2001-05-23 15:26:42 +02:00
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_sub_type:
2001-05-23 15:26:42 +02:00
stype = (SSHORT)DYN_get_number(ptr);
sflag = true;
2001-05-23 15:26:42 +02:00
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_char_length:
2001-05-23 15:26:42 +02:00
clength = (USHORT)DYN_get_number(ptr);
clflag = true;
2001-05-23 15:26:42 +02:00
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_segment_length:
2001-05-23 15:26:42 +02:00
stype = (SSHORT)DYN_get_number(ptr);
slflag = true;
2001-05-23 15:26:42 +02:00
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_scale:
2001-05-23 15:26:42 +02:00
scale = (SSHORT)DYN_get_number(ptr);
scflag = true;
2001-05-23 15:26:42 +02:00
break;
case isc_dyn_fld_precision:
precision = (USHORT)DYN_get_number(ptr);
prflag = true;
2001-05-23 15:26:42 +02:00
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_character_set:
2001-05-23 15:26:42 +02:00
charset_id = (SSHORT)DYN_get_number(ptr);
charset_id_flag = true;
2001-05-23 15:26:42 +02:00
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_collation:
2001-05-23 15:26:42 +02:00
RFR.RDB$COLLATION_ID.NULL = FALSE;
RFR.RDB$COLLATION_ID = (SSHORT)DYN_get_number(ptr);
break;
default:
2010-01-28 16:01:57 +01:00
{
2010-01-24 16:16:23 +01:00
MetaNameProxy tmp(RFR.RDB$FIELD_SOURCE);
DYN_execute(gbl, ptr, relation_name, &tmp, NULL, NULL, NULL);
2010-01-24 16:16:23 +01:00
}
2001-05-23 15:26:42 +02:00
}
}
2001-05-23 15:26:42 +02:00
if (has_default && DYN_UTIL_is_array(tdbb, gbl, RFR.RDB$FIELD_SOURCE))
{
DYN_error_punt(false, 226, RFR.RDB$FIELD_SOURCE);
// msg 226: "Default value is not allowed for array type in domain %s"
}
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
dsc desc;
MET_get_domain(tdbb, RFR.RDB$FIELD_SOURCE, &desc, NULL);
if (!desc.isExact() || desc.dsc_scale != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
DYN_error_punt(false, 273,
SafeArg() << local_field_name.c_str() << relation_name->c_str());
}
}
2009-11-25 05:06:48 +01:00
if (RFR.RDB$FIELD_POSITION.NULL == TRUE)
{
2001-05-23 15:26:42 +02:00
fld_pos = -1;
fb_assert(relation_name);
2008-12-18 11:57:12 +01:00
DYN_UTIL_generate_field_position(tdbb, gbl, *relation_name, &fld_pos);
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
if (fld_pos >= 0)
{
2001-05-23 15:26:42 +02:00
RFR.RDB$FIELD_POSITION = (SSHORT)++fld_pos;
RFR.RDB$FIELD_POSITION.NULL = FALSE;
}
}
2009-11-25 05:06:48 +01:00
if (blr)
{
2004-03-07 08:58:55 +01:00
const SSHORT old_id = id;
2010-04-18 03:10:05 +02:00
AutoCacheRequest request2(tdbb, drq_s_gfields2, DYN_REQUESTS);
id = drq_s_gfields2;
2001-05-23 15:26:42 +02:00
2010-04-18 03:10:05 +02:00
STORE(REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction)
2001-05-23 15:26:42 +02:00
FLD IN RDB$FIELDS
2010-04-18 03:10:05 +02:00
{
2008-03-26 03:07:56 +01:00
FLD.RDB$SYSTEM_FLAG = 0;
FLD.RDB$SYSTEM_FLAG.NULL = FALSE;
strcpy(FLD.RDB$FIELD_NAME, RFR.RDB$FIELD_SOURCE);
2001-05-23 15:26:42 +02:00
DYN_put_blr_blob(gbl, &blr, &FLD.RDB$COMPUTED_BLR);
if (source) {
DYN_put_text_blob(gbl, &source, &FLD.RDB$COMPUTED_SOURCE);
2001-05-23 15:26:42 +02:00
}
FLD.RDB$FIELD_TYPE = dtype;
2008-03-26 03:07:56 +01:00
FLD.RDB$FIELD_TYPE.NULL = FALSE;
2009-11-25 05:06:48 +01:00
if (lflag)
{
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_LENGTH = length;
FLD.RDB$FIELD_LENGTH.NULL = FALSE;
}
else
FLD.RDB$FIELD_LENGTH.NULL = TRUE;
2009-11-25 05:06:48 +01:00
if (sflag)
{
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_SUB_TYPE = stype;
FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
}
else
FLD.RDB$FIELD_SUB_TYPE.NULL = TRUE;
2009-11-25 05:06:48 +01:00
if (clflag)
{
2001-05-23 15:26:42 +02:00
FLD.RDB$CHARACTER_LENGTH = clength;
FLD.RDB$CHARACTER_LENGTH.NULL = FALSE;
}
else
FLD.RDB$CHARACTER_LENGTH.NULL = TRUE;
2009-11-25 05:06:48 +01:00
if (slflag)
{
2001-05-23 15:26:42 +02:00
FLD.RDB$SEGMENT_LENGTH = stype;
FLD.RDB$SEGMENT_LENGTH.NULL = FALSE;
}
else
FLD.RDB$SEGMENT_LENGTH.NULL = TRUE;
2009-11-25 05:06:48 +01:00
if (scflag)
{
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_SCALE = scale;
FLD.RDB$FIELD_SCALE.NULL = FALSE;
}
else
FLD.RDB$FIELD_SCALE.NULL = TRUE;
2009-11-25 05:06:48 +01:00
if (prflag)
{
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_PRECISION = precision;
FLD.RDB$FIELD_PRECISION.NULL = FALSE;
}
else
FLD.RDB$FIELD_PRECISION.NULL = TRUE;
2009-11-25 05:06:48 +01:00
if (charset_id_flag)
{
2001-05-23 15:26:42 +02:00
FLD.RDB$CHARACTER_SET_ID = charset_id;
FLD.RDB$CHARACTER_SET_ID.NULL = FALSE;
}
else
FLD.RDB$CHARACTER_SET_ID.NULL = TRUE;
2010-04-18 03:10:05 +02:00
}
END_STORE
2001-05-23 15:26:42 +02:00
id = old_id;
}
if (!RFR.RDB$VIEW_CONTEXT.NULL)
{
fb_assert(relation_name);
2008-01-16 09:46:02 +01:00
DYN_UTIL_find_field_source(tdbb, gbl, *relation_name, RFR.RDB$VIEW_CONTEXT,
RFR.RDB$BASE_FIELD, RFR.RDB$FIELD_SOURCE);
}
2001-12-24 03:51:06 +01:00
}
2010-04-18 03:10:05 +02:00
END_STORE
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
} // try
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2009-11-25 05:06:48 +01:00
if (id == drq_s_lfields)
{
DYN_error_punt(true, 23);
2009-11-21 08:38:05 +01:00
// msg 23: "STORE RDB$RELATION_FIELDS failed"
2001-12-24 03:51:06 +01:00
}
2009-11-25 05:06:48 +01:00
else
{
DYN_error_punt(true, 22);
2009-11-21 08:38:05 +01:00
// msg 22: "STORE RDB$FIELDS failed"
2001-12-24 03:51:06 +01:00
}
}
2001-05-23 15:26:42 +02:00
}
void DYN_define_view(Global* gbl, const UCHAR** ptr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ v i e w
2001-05-23 15:26:42 +02:00
*
**************************************
*
* Functional description
* Execute a dynamic ddl statement.
*
**************************************/
Firebird::MetaName relation_name, owner_name;
Firebird::MetaName field_name; // unused, only passed empty to DYN_execute again.
2001-05-23 15:26:42 +02:00
thread_db* tdbb = JRD_get_thread_data();
2009-12-17 01:07:23 +01:00
Jrd::Attachment* attachment = tdbb->getAttachment();
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, relation_name);
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
DDL_TRIGGER_CREATE_VIEW, relation_name, gbl->sqlText);
SSHORT id = -1;
2001-05-23 15:26:42 +02:00
2004-02-08 18:08:34 +01:00
Firebird::PathName Path, Name;
2001-12-24 03:51:06 +01:00
try {
2001-05-23 15:26:42 +02:00
id = drq_l_rel_name;
DYN_UTIL_check_unique_name(tdbb, gbl->gbl_transaction, relation_name, obj_relation);
bool sql_prot = false;
rel_t rel_type = rel_persistent;
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_rels, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
id = drq_s_rels;
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
2005-05-28 00:45:31 +02:00
REL IN RDB$RELATIONS
2010-04-18 03:10:05 +02:00
{
strcpy(REL.RDB$RELATION_NAME, relation_name.c_str());
REL.RDB$SYSTEM_FLAG = 0;
REL.RDB$SYSTEM_FLAG.NULL = FALSE;
2001-05-23 15:26:42 +02:00
REL.RDB$VIEW_BLR.NULL = TRUE;
REL.RDB$VIEW_SOURCE.NULL = TRUE;
REL.RDB$SECURITY_CLASS.NULL = TRUE;
REL.RDB$EXTERNAL_FILE.NULL = TRUE;
REL.RDB$FLAGS = 0;
REL.RDB$FLAGS.NULL = FALSE;
2009-11-27 07:57:17 +01:00
REL.RDB$RELATION_TYPE.NULL = FALSE;
UCHAR verb;
2003-11-08 17:40:17 +01:00
while ((verb = *(*ptr)++) != isc_dyn_end)
2006-05-25 05:15:53 +02:00
{
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_sql_object:
2001-05-23 15:26:42 +02:00
REL.RDB$FLAGS |= REL_sql;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_view_blr:
2001-05-23 15:26:42 +02:00
REL.RDB$VIEW_BLR.NULL = FALSE;
rel_type = rel_view;
2001-05-23 15:26:42 +02:00
DYN_put_blr_blob(gbl, ptr, &REL.RDB$VIEW_BLR);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_view_source:
2001-05-23 15:26:42 +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:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, REL.RDB$SECURITY_CLASS);
REL.RDB$SECURITY_CLASS.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_rel_sql_protection:
2001-05-23 15:26:42 +02:00
REL.RDB$FLAGS |= REL_sql;
sql_prot = (bool) DYN_get_number(ptr);
2001-05-23 15:26:42 +02:00
break;
default:
--(*ptr);
2010-01-24 16:16:23 +01:00
{
const MetaName tmp(REL.RDB$RELATION_NAME);
DYN_execute(gbl, ptr, &tmp, &field_name, NULL, NULL, NULL);
2010-01-24 16:16:23 +01:00
}
2001-05-23 15:26:42 +02:00
}
} // while
2009-11-27 07:57:17 +01:00
// The relation type cannot be determined definitely inside the above loop,
// because there are many DYN codes that affect it.
REL.RDB$RELATION_TYPE = rel_type;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
if (sql_prot)
{
2009-12-17 01:07:23 +01:00
owner_name = attachment->att_user->usr_user_name;
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
if (rel_type == rel_view)
{
2006-09-01 12:51:57 +02:00
const SSHORT old_id2 = id;
2010-04-18 03:10:05 +02:00
AutoCacheRequest request2(tdbb, drq_l_view_rels, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
id = drq_l_view_rels;
2010-04-18 03:10:05 +02:00
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction)
2001-05-23 15:26:42 +02:00
VRL IN RDB$VIEW_RELATIONS CROSS
PREL IN RDB$RELATIONS OVER RDB$RELATION_NAME WITH
2009-12-17 16:07:02 +01:00
VRL.RDB$PACKAGE_NAME MISSING AND
VRL.RDB$VIEW_NAME EQ relation_name.c_str()
2010-04-18 03:10:05 +02:00
{
2009-11-21 08:38:05 +01:00
// CVC: This never matches so it causes unnecessary calls to verify,
// so I included a call to strip trailing blanks.
fb_utils::exact_name_limit(PREL.RDB$OWNER_NAME, sizeof(PREL.RDB$OWNER_NAME));
2009-11-25 05:06:48 +01:00
if (owner_name != PREL.RDB$OWNER_NAME)
{
SecurityClass::flags_t priv;
2008-12-18 11:57:12 +01:00
if (!DYN_UTIL_get_prot(tdbb, gbl, PREL.RDB$RELATION_NAME, "", &priv))
{
// I think this should be the responsability of DFW
// or the user will find ways to circumvent DYN.
DYN_error_punt(true, 115);
2009-11-21 08:38:05 +01:00
// msg 115: "CREATE VIEW failed"
}
2005-05-28 00:45:31 +02:00
2009-11-25 05:06:48 +01:00
if (!(priv & SCL_read))
{
ERR_post_nothrow(Arg::Gds(isc_no_priv) << Arg::Str("SELECT") << // Non-Translatable
// Remember, a view may be based on a view.
Arg::Str("TABLE/VIEW") << // Non-Translatable
// We want to print the name of the base table or view.
Arg::Str(PREL.RDB$RELATION_NAME));
2009-11-21 08:38:05 +01:00
// msg 32: no permission for %s access to %s %s
DYN_error_punt(true, 115);
2009-11-21 08:38:05 +01:00
// msg 115: "CREATE VIEW failed"
2001-05-23 15:26:42 +02:00
}
}
2010-04-18 03:10:05 +02:00
}
END_FOR
2006-09-01 12:51:57 +02:00
id = old_id2;
2001-05-23 15:26:42 +02:00
}
}
2010-04-18 03:10:05 +02:00
}
END_STORE
2001-05-23 15:26:42 +02:00
if (sql_prot)
{
2009-11-25 05:06:48 +01:00
for (const TEXT* p = ALL_PRIVILEGES; *p; p++)
{
2010-04-18 03:10:05 +02:00
request.reset(tdbb, drq_s_usr_prvs, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
id = drq_s_usr_prvs;
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$USER_PRIVILEGES
2010-04-18 03:10:05 +02:00
{
strcpy(X.RDB$RELATION_NAME, relation_name.c_str());
strcpy(X.RDB$USER, owner_name.c_str());
2001-05-23 15:26:42 +02:00
X.RDB$USER_TYPE = obj_user;
X.RDB$OBJECT_TYPE = obj_relation;
X.RDB$PRIVILEGE[0] = *p;
X.RDB$PRIVILEGE[1] = 0;
X.RDB$GRANT_OPTION = 1;
2010-04-18 03:10:05 +02:00
}
END_STORE
2001-05-23 15:26:42 +02:00
}
}
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
}
2009-01-14 10:19:00 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2009-11-25 05:06:48 +01:00
if (id == drq_s_rels)
{
DYN_error_punt(true, 24);
2009-11-21 08:38:05 +01:00
// msg 24: "STORE RDB$RELATIONS failed"
2001-12-24 03:51:06 +01:00
}
2009-11-25 05:06:48 +01:00
else if (id == drq_s_usr_prvs)
{
DYN_error_punt(true, 25);
2009-11-21 08:38:05 +01:00
// msg 25: "STORE RDB$USER_PRIVILEGES failed defining a relation"
2001-12-24 03:51:06 +01:00
}
2009-01-14 10:19:00 +01:00
switch (id)
{
case drq_l_rel_name:
2009-11-21 08:38:05 +01:00
DYN_error_punt(true, 24); // msg 24: "STORE RDB$RELATIONS failed"
2009-01-14 10:19:00 +01:00
break;
case drq_l_view_rels:
2009-11-21 08:38:05 +01:00
DYN_error_punt(true, 115); // msg 115: "CREATE VIEW failed"
2009-01-14 10:19:00 +01:00
break;
}
2001-12-24 03:51:06 +01:00
2009-11-21 08:38:05 +01:00
// Control should never reach this point, because id should
// always have one of the values test-for above.
fb_assert(false);
DYN_error_punt(true, 0);
2001-12-24 03:51:06 +01:00
}
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
DDL_TRIGGER_CREATE_VIEW, relation_name, gbl->sqlText);
2001-05-23 15:26:42 +02:00
}
void DYN_define_role( Global* gbl, const UCHAR** ptr)
2002-06-30 10:46:51 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ r o l e
*
**************************************
*
* Functional description
*
* Define a SQL role.
2005-05-28 00:45:31 +02:00
* ROLES cannot be named the same as any existing user name
2002-06-30 10:46:51 +02:00
*
**************************************/
thread_db* tdbb = JRD_get_thread_data();
2005-05-28 00:45:31 +02:00
Firebird::MetaName owner_name(tdbb->getAttachment()->att_user->usr_user_name);
owner_name.upper7();
2002-06-30 10:46:51 +02:00
Firebird::MetaName role_name;
2002-06-30 10:46:51 +02:00
GET_STRING(ptr, role_name);
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE,
DDL_TRIGGER_CREATE_ROLE, role_name, gbl->sqlText);
2009-11-25 05:06:48 +01:00
if (role_name == owner_name)
{
2009-11-21 08:38:05 +01:00
// user name could not be used for SQL role
DYN_error(false, 193, SafeArg() << owner_name.c_str());
2002-06-30 10:46:51 +02:00
ERR_punt();
}
2009-11-25 05:06:48 +01:00
if (role_name == NULL_ROLE)
{
2009-11-21 08:38:05 +01:00
// keyword NONE could not be used as SQL role name
DYN_error(false, 195, SafeArg() << role_name.c_str());
2002-06-30 10:46:51 +02:00
ERR_punt();
}
try {
2009-11-25 05:06:48 +01:00
if (is_it_user_name(gbl, role_name, tdbb))
{
2009-11-21 08:38:05 +01:00
// user name could not be used for SQL role
DYN_error(false, 193, SafeArg() << role_name.c_str());
2002-06-30 10:46:51 +02:00
goto do_err_punt;
}
Firebird::MetaName dummy_name;
2009-11-25 05:06:48 +01:00
if (DYN_is_it_sql_role(gbl, role_name, dummy_name, tdbb))
{
2009-11-21 08:38:05 +01:00
// SQL role @1 already exists
DYN_error(false, 194, SafeArg() << role_name.c_str());
2002-06-30 10:46:51 +02:00
goto do_err_punt;
}
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_role_gens, DYN_REQUESTS);
2002-06-30 10:46:51 +02:00
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
X IN RDB$ROLES
2010-04-18 03:10:05 +02:00
{
strcpy(X.RDB$ROLE_NAME, role_name.c_str());
strcpy(X.RDB$OWNER_NAME, owner_name.c_str());
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
2002-06-30 10:46:51 +02:00
}
2010-04-18 03:10:05 +02:00
END_STORE
2002-06-30 10:46:51 +02:00
2010-04-18 03:10:05 +02:00
if (*(*ptr)++ != isc_dyn_end)
2002-06-30 10:46:51 +02:00
goto do_error_punt_9;
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_error_punt(true, 8);
2009-11-21 08:38:05 +01:00
// msg 8: "DEFINE ROLE failed"
2002-06-30 10:46:51 +02:00
}
DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER,
DDL_TRIGGER_CREATE_ROLE, role_name, gbl->sqlText);
2002-06-30 10:46:51 +02:00
return;
do_err_punt:
ERR_punt();
return;
do_error_punt_9:
DYN_error_punt(true, 9);
2009-11-21 08:38:05 +01:00
// msg 9: "DEFINE ROLE unexpected dyn verb"
2002-06-30 10:46:51 +02:00
}
void DYN_define_sql_field(Global* gbl,
const UCHAR** ptr,
const Firebird::MetaName* relation_name,
Firebird::MetaName* field_name)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ s q l _ f i e l d
*
**************************************
*
* Functional description
* Define a local, SQL field. This will require generation of
* an global field name.
*
**************************************/
UCHAR verb;
USHORT dtype;
SLONG fld_pos;
thread_db* tdbb = JRD_get_thread_data();
2001-05-23 15:26:42 +02:00
Firebird::MetaName sql_field_name;
2002-06-30 10:46:51 +02:00
GET_STRING(ptr, sql_field_name);
SSHORT id = -1;
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
try {
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_sql_lfld, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
id = drq_s_sql_lfld;
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
2005-05-28 00:45:31 +02:00
RFR IN RDB$RELATION_FIELDS
2010-04-18 03:10:05 +02:00
{
strcpy(RFR.RDB$FIELD_NAME, sql_field_name.c_str());
if (field_name)
*field_name = RFR.RDB$FIELD_NAME;
2001-05-23 15:26:42 +02:00
if (relation_name)
strcpy(RFR.RDB$RELATION_NAME, relation_name->c_str());
2001-05-23 15:26:42 +02:00
RFR.RDB$SYSTEM_FLAG = 0;
RFR.RDB$SYSTEM_FLAG.NULL = FALSE;
RFR.RDB$QUERY_NAME.NULL = TRUE;
RFR.RDB$QUERY_HEADER.NULL = TRUE;
RFR.RDB$EDIT_STRING.NULL = TRUE;
RFR.RDB$FIELD_POSITION.NULL = TRUE;
RFR.RDB$VIEW_CONTEXT.NULL = TRUE;
RFR.RDB$BASE_FIELD.NULL = TRUE;
RFR.RDB$UPDATE_FLAG.NULL = TRUE;
RFR.RDB$NULL_FLAG.NULL = TRUE;
RFR.RDB$DEFAULT_SOURCE.NULL = TRUE;
RFR.RDB$DEFAULT_VALUE.NULL = TRUE;
RFR.RDB$COLLATION_ID.NULL = TRUE;
RFR.RDB$GENERATOR_NAME.NULL = TRUE;
RFR.RDB$IDENTITY_TYPE.NULL = TRUE;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
const SSHORT old_id = id;
2010-04-18 03:10:05 +02:00
AutoCacheRequest request2(tdbb, drq_s_sql_gfld, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
id = drq_s_sql_gfld;
2010-04-18 03:10:05 +02:00
STORE(REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction)
FLD IN RDB$FIELDS
2010-04-18 03:10:05 +02:00
{
FLD.RDB$SYSTEM_FLAG = 0;
FLD.RDB$SYSTEM_FLAG.NULL = FALSE;
2001-05-23 15:26:42 +02:00
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;
bool has_dimensions = false;
bool has_default = false;
2008-12-18 11:57:12 +01:00
2001-05-23 15:26:42 +02:00
DYN_UTIL_generate_field_name(tdbb, gbl, RFR.RDB$FIELD_SOURCE);
strcpy(FLD.RDB$FIELD_NAME, RFR.RDB$FIELD_SOURCE);
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, RFR.RDB$RELATION_NAME);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_query_name:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, RFR.RDB$QUERY_NAME);
RFR.RDB$QUERY_NAME.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_edit_string:
2001-05-23 15:26:42 +02:00
GET_STRING(ptr, RFR.RDB$EDIT_STRING);
RFR.RDB$EDIT_STRING.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_position:
2001-05-23 15:26:42 +02:00
RFR.RDB$FIELD_POSITION = DYN_get_number(ptr);
RFR.RDB$FIELD_POSITION.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_view_context:
2001-05-23 15:26:42 +02:00
RFR.RDB$VIEW_CONTEXT = DYN_get_number(ptr);
RFR.RDB$VIEW_CONTEXT.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_system_flag:
2009-06-07 11:49:58 +02:00
RFR.RDB$SYSTEM_FLAG = FLD.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
RFR.RDB$SYSTEM_FLAG.NULL = FLD.RDB$SYSTEM_FLAG.NULL = FALSE;
2001-05-23 15:26:42 +02:00
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_update_flag:
2001-05-23 15:26:42 +02:00
RFR.RDB$UPDATE_FLAG = DYN_get_number(ptr);
RFR.RDB$UPDATE_FLAG.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_length:
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_LENGTH = DYN_get_number(ptr);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_computed_blr:
2001-05-23 15:26:42 +02:00
FLD.RDB$COMPUTED_BLR.NULL = FALSE;
DYN_put_blr_blob(gbl, ptr, &FLD.RDB$COMPUTED_BLR);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_computed_source:
2001-05-23 15:26:42 +02:00
FLD.RDB$COMPUTED_SOURCE.NULL = FALSE;
DYN_put_text_blob(gbl, ptr, &FLD.RDB$COMPUTED_SOURCE);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_default_value:
if (has_dimensions)
{
DYN_error_punt(false, 225, sql_field_name.c_str());
// msg 225: "Default value is not allowed for array type in field %s"
}
has_default = true;
2001-05-23 15:26:42 +02:00
RFR.RDB$DEFAULT_VALUE.NULL = FALSE;
DYN_put_blr_blob(gbl, ptr, &RFR.RDB$DEFAULT_VALUE);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_default_source:
if (has_dimensions)
{
DYN_error_punt(false, 225, sql_field_name.c_str());
// msg 225: "Default value is not allowed for array type in field %s"
}
has_default = true;
2001-05-23 15:26:42 +02:00
RFR.RDB$DEFAULT_SOURCE.NULL = FALSE;
DYN_put_text_blob(gbl, ptr, &RFR.RDB$DEFAULT_SOURCE);
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_validation_blr:
2001-05-23 15:26:42 +02:00
FLD.RDB$VALIDATION_BLR.NULL = FALSE;
DYN_put_blr_blob(gbl, ptr, &FLD.RDB$VALIDATION_BLR);
break;
case isc_dyn_fld_identity:
{
MetaName sequenceName;
DYN_UTIL_generate_generator_name(tdbb, sequenceName);
CreateSequenceNode::store(tdbb, gbl->gbl_transaction, sequenceName,
fb_sysflag_identity_generator);
strcpy(RFR.RDB$GENERATOR_NAME, sequenceName.c_str());
RFR.RDB$GENERATOR_NAME.NULL = FALSE;
RFR.RDB$IDENTITY_TYPE = IDENT_TYPE_BY_DEFAULT;
RFR.RDB$IDENTITY_TYPE.NULL = FALSE;
break;
}
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_not_null:
2001-05-23 15:26:42 +02:00
RFR.RDB$NULL_FLAG.NULL = FALSE;
RFR.RDB$NULL_FLAG = TRUE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_query_header:
2001-05-23 15:26:42 +02:00
DYN_put_blr_blob(gbl, ptr, &RFR.RDB$QUERY_HEADER);
RFR.RDB$QUERY_HEADER.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_type:
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_TYPE = dtype = DYN_get_number(ptr);
switch (dtype)
{
case blr_short:
FLD.RDB$FIELD_LENGTH = 2;
break;
case blr_long:
case blr_float:
case blr_sql_date:
case blr_sql_time:
FLD.RDB$FIELD_LENGTH = 4;
break;
case blr_int64:
case blr_quad:
case blr_timestamp:
case blr_double:
case blr_d_float:
FLD.RDB$FIELD_LENGTH = 8;
break;
default:
if (dtype == blr_blob)
FLD.RDB$FIELD_LENGTH = 8;
break;
}
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_scale:
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_SCALE = DYN_get_number(ptr);
FLD.RDB$FIELD_SCALE.NULL = FALSE;
break;
case isc_dyn_fld_precision:
FLD.RDB$FIELD_PRECISION = DYN_get_number(ptr);
FLD.RDB$FIELD_PRECISION.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_sub_type:
2001-05-23 15:26:42 +02:00
FLD.RDB$FIELD_SUB_TYPE = DYN_get_number(ptr);
FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_char_length:
2001-05-23 15:26:42 +02:00
FLD.RDB$CHARACTER_LENGTH = DYN_get_number(ptr);
FLD.RDB$CHARACTER_LENGTH.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_character_set:
2001-05-23 15:26:42 +02:00
FLD.RDB$CHARACTER_SET_ID = DYN_get_number(ptr);
FLD.RDB$CHARACTER_SET_ID.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_collation:
2009-11-21 08:38:05 +01:00
// Note: the global field's collation is not set, just
2009-11-22 01:09:30 +01:00
// the local field. There is no full "domain"
// created for the local field.
// This is the same decision for items like NULL_FLAG
2001-05-23 15:26:42 +02:00
RFR.RDB$COLLATION_ID = DYN_get_number(ptr);
RFR.RDB$COLLATION_ID.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_dimensions:
if (has_default)
{
DYN_error_punt(false, 225, sql_field_name.c_str());
// msg 225: "Default value is not allowed for array type in field %s"
}
has_dimensions = true;
2001-05-23 15:26:42 +02:00
FLD.RDB$DIMENSIONS = DYN_get_number(ptr);
FLD.RDB$DIMENSIONS.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_fld_segment_length:
2001-05-23 15:26:42 +02:00
FLD.RDB$SEGMENT_LENGTH = DYN_get_number(ptr);
FLD.RDB$SEGMENT_LENGTH.NULL = FALSE;
break;
default:
--(*ptr);
2010-01-24 16:16:23 +01:00
{
MetaNameProxy tmp(RFR.RDB$FIELD_SOURCE);
DYN_execute(gbl, ptr, relation_name, &tmp, NULL, NULL, NULL);
2010-01-24 16:16:23 +01:00
}
2001-05-23 15:26:42 +02:00
}
}
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
bool exact = FLD.RDB$FIELD_TYPE == blr_short || FLD.RDB$FIELD_TYPE == blr_long ||
FLD.RDB$FIELD_TYPE == blr_int64;
if (!exact || FLD.RDB$FIELD_SCALE != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
DYN_error_punt(false, 273,
SafeArg() << sql_field_name.c_str() << relation_name->c_str());
}
}
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
if (RFR.RDB$FIELD_POSITION.NULL == TRUE)
{
2001-05-23 15:26:42 +02:00
fld_pos = -1;
fb_assert(relation_name);
2009-01-03 10:14:29 +01:00
DYN_UTIL_generate_field_position(tdbb, gbl, *relation_name, &fld_pos);
2001-05-23 15:26:42 +02:00
2009-11-25 05:06:48 +01:00
if (fld_pos >= 0)
{
2001-05-23 15:26:42 +02:00
RFR.RDB$FIELD_POSITION = ++fld_pos;
RFR.RDB$FIELD_POSITION.NULL = FALSE;
}
}
2010-04-18 03:10:05 +02:00
}
END_STORE
2001-05-23 15:26:42 +02:00
id = old_id;
2010-04-18 03:10:05 +02:00
}
END_STORE
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2009-11-25 05:06:48 +01:00
if (id == drq_s_sql_lfld)
{
DYN_error_punt(true, 29);
2009-11-21 08:38:05 +01:00
// msg 29: "STORE RDB$RELATION_FIELDS failed"
2001-12-24 03:51:06 +01:00
}
2009-11-25 05:06:48 +01:00
else
{
DYN_error_punt(true, 28);
2009-11-21 08:38:05 +01:00
// msg 28: "STORE RDB$FIELDS failed"
2001-12-24 03:51:06 +01:00
}
}
2001-05-23 15:26:42 +02:00
}
void DYN_define_shadow( Global* gbl, const UCHAR** ptr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ s h a d o w
*
**************************************
*
* Functional description
* Define a shadow.
*
**************************************/
2001-12-25 05:10:23 +01:00
thread_db* tdbb = JRD_get_thread_data();
2001-12-25 05:10:23 +01:00
bool found = false;
2001-05-23 15:26:42 +02:00
const SLONG shadow_number = DYN_get_number(ptr);
2001-05-23 15:26:42 +02:00
2009-11-21 08:38:05 +01:00
// If a shadow set identified by the shadow number already exists return error.
2001-05-23 15:26:42 +02:00
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_l_shadow, DYN_REQUESTS);
2001-12-24 03:51:06 +01:00
2010-04-18 03:10:05 +02:00
try
{
2001-12-24 03:51:06 +01:00
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
FIRST 1 X IN RDB$FILES WITH X.RDB$SHADOW_NUMBER EQ shadow_number
2010-04-18 03:10:05 +02:00
{
found = true;
2001-12-24 03:51:06 +01:00
}
2010-04-18 03:10:05 +02:00
END_FOR
2001-12-24 03:51:06 +01:00
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
DYN_error_punt(true, 164);
2009-11-21 08:38:05 +01:00
// msg 164: "Shadow lookup failed"
2001-05-23 15:26:42 +02:00
}
2009-11-25 05:06:48 +01:00
if (found)
{
DYN_error_punt(false, 165, SafeArg() << shadow_number);
2009-11-21 08:38:05 +01:00
// msg 165: "Shadow %ld already exists"
2001-12-24 03:51:06 +01:00
}
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
SLONG start = 0;
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_def_file:
2001-05-23 15:26:42 +02:00
DYN_define_file(gbl, ptr, shadow_number, &start, 157);
break;
default:
DYN_unsupported_verb();
}
}
}
//// TODO: remove this function after rework on constraints and views triggers
void DYN_define_trigger(Global* gbl,
const UCHAR** ptr,
const Firebird::MetaName* relation_name,
Firebird::MetaName* trigger_name,
const bool ignore_perm)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ t r i g g e r
*
**************************************
*
* Functional description
* Define a trigger for a relation.
*
*
* if the ignore_perm flag is true, then this trigger must be defined
2001-05-23 15:26:42 +02:00
* now (and fired at run time) without making SQL permissions checks.
* In particular, one should not need control permissions on the table
* to define this trigger. Currently used to define triggers for
* cascading referential interity.
2005-05-28 00:45:31 +02:00
*
2001-05-23 15:26:42 +02:00
**************************************/
thread_db* tdbb = JRD_get_thread_data();
2001-12-25 05:10:23 +01:00
Firebird::MetaName t;
2001-05-23 15:26:42 +02:00
2002-06-30 10:46:51 +02:00
GET_STRING(ptr, t);
2009-12-18 00:59:07 +01:00
if (t.isEmpty())
DYN_UTIL_generate_trigger_name(tdbb, gbl->gbl_transaction, t);
2001-05-23 15:26:42 +02:00
2009-12-17 02:36:33 +01:00
if (trigger_name)
*trigger_name = t;
2001-05-23 15:26:42 +02:00
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_triggers, DYN_REQUESTS);
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
bool b_ending_store = false;
const UCHAR* debug_info_ptr = NULL;
2001-12-25 05:10:23 +01:00
try {
2001-05-23 15:26:42 +02:00
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
2005-05-28 00:45:31 +02:00
X IN RDB$TRIGGERS
2010-04-18 03:10:05 +02:00
{
X.RDB$TRIGGER_TYPE.NULL = TRUE;
2001-05-23 15:26:42 +02:00
X.RDB$TRIGGER_SEQUENCE = 0;
X.RDB$TRIGGER_SEQUENCE.NULL = FALSE;
X.RDB$TRIGGER_INACTIVE = 0;
X.RDB$TRIGGER_INACTIVE.NULL = FALSE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
// ODS_12_0
X.RDB$ENTRYPOINT.NULL = TRUE;
X.RDB$ENGINE_NAME.NULL = TRUE;
2001-05-23 15:26:42 +02:00
2009-11-21 08:38:05 +01:00
// Currently, we make no difference between ignoring permissions in
// order to define this trigger and ignoring permissions checks when the
// trigger fires. The RDB$FLAGS is used to indicate permissions checks
// when the trigger fires. Later, if we need to make a difference
// between these, then the caller should pass the required value
// of RDB$FLAGS as an extra argument to this func.
2001-05-23 15:26:42 +02:00
X.RDB$FLAGS = ignore_perm ? TRG_ignore_perm : 0;
X.RDB$FLAGS.NULL = FALSE;
2009-11-25 05:06:48 +01:00
if (relation_name)
{
strcpy(X.RDB$RELATION_NAME, relation_name->c_str());
2001-05-23 15:26:42 +02:00
X.RDB$RELATION_NAME.NULL = FALSE;
}
else
X.RDB$RELATION_NAME.NULL = TRUE;
X.RDB$TRIGGER_BLR.NULL = TRUE;
X.RDB$TRIGGER_SOURCE.NULL = TRUE;
strcpy(X.RDB$TRIGGER_NAME, t.c_str());
UCHAR verb;
2003-11-08 17:40:17 +01:00
while ((verb = *(*ptr)++) != isc_dyn_end)
2001-12-25 05:10:23 +01:00
{
2001-05-23 15:26:42 +02:00
switch (verb)
{
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_sql_object:
2001-05-23 15:26:42 +02:00
X.RDB$FLAGS |= TRG_sql;
2002-06-30 10:46:51 +02:00
X.RDB$FLAGS.NULL = FALSE;
2001-05-23 15:26:42 +02:00
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);
2002-06-30 10:46:51 +02:00
X.RDB$TRIGGER_SEQUENCE.NULL = FALSE;
2001-05-23 15:26:42 +02:00
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);
2002-06-30 10:46:51 +02:00
X.RDB$TRIGGER_INACTIVE.NULL = FALSE;
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, X.RDB$RELATION_NAME);
X.RDB$RELATION_NAME.NULL = FALSE;
break;
2003-11-08 17:40:17 +01:00
case isc_dyn_trg_blr:
{
const UCHAR* blr = *ptr;
DYN_skip_attribute(ptr);
DYN_put_blr_blob(gbl, &blr, &X.RDB$TRIGGER_BLR);
X.RDB$TRIGGER_BLR.NULL = FALSE;
break;
}
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_trg_source:
{
const UCHAR* source = *ptr;
DYN_skip_attribute(ptr);
DYN_put_text_blob(gbl, &source, &X.RDB$TRIGGER_SOURCE);
X.RDB$TRIGGER_SOURCE.NULL = FALSE;
break;
}
2001-05-23 15:26:42 +02:00
case isc_dyn_system_flag:
2002-06-30 10:46:51 +02:00
X.RDB$SYSTEM_FLAG = DYN_get_number(ptr);
X.RDB$SYSTEM_FLAG.NULL = FALSE;
2009-11-21 08:38:05 +01:00
// fb_assert(!ignore_perm || ignore_perm &&
// X.RDB$SYSTEM_FLAG == fb_sysflag_referential_constraint);
2002-06-30 10:46:51 +02:00
break;
case isc_dyn_debug_info:
debug_info_ptr = *ptr;
DYN_skip_attribute(ptr);
break;
case isc_dyn_func_entry_point:
// ODS_12_0
GET_STRING(ptr, X.RDB$ENTRYPOINT);
X.RDB$ENTRYPOINT.NULL = FALSE;
break;
case isc_dyn_def_engine:
// ODS_12_0
GET_STRING(ptr, X.RDB$ENGINE_NAME);
X.RDB$ENGINE_NAME.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
default:
--(*ptr);
2010-01-24 16:16:23 +01:00
{
const MetaName tmp(X.RDB$RELATION_NAME);
DYN_execute(gbl, ptr, &tmp, NULL, &t, NULL, NULL);
2010-01-24 16:16:23 +01:00
}
2001-05-23 15:26:42 +02:00
}
}
if (X.RDB$RELATION_NAME.NULL && !tdbb->getAttachment()->locksmith())
ERR_post(Arg::Gds(isc_adm_task_denied));
2009-11-27 07:57:17 +01:00
X.RDB$VALID_BLR = TRUE;
X.RDB$VALID_BLR.NULL = FALSE;
if (debug_info_ptr)
{
X.RDB$DEBUG_INFO.NULL = FALSE;
DYN_put_blr_blob(gbl, &debug_info_ptr, &X.RDB$DEBUG_INFO);
}
else
X.RDB$DEBUG_INFO.NULL = TRUE;
2001-12-25 05:10:23 +01:00
b_ending_store = true;
2009-11-21 08:38:05 +01:00
// the END_STORE_SPECIAL adds the foll. lines of code to the END_STORE
// if (ignore_perm)
// request->getStatement()->flags |= JrdStatement::FLAG_IGNORE_PERM;
2009-11-21 08:38:05 +01:00
// after the request is compiled and before the request is sent.
// It makes the current request (to define the trigger) go through
// without checking any permissions lower in the engine
2010-04-18 03:10:05 +02:00
}
END_STORE_SPECIAL
2001-05-23 15:26:42 +02:00
if (ignore_perm)
request->getStatement()->flags &= ~JrdStatement::FLAG_IGNORE_PERM;
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2009-11-25 05:06:48 +01:00
if (b_ending_store)
{
DYN_error_punt(true, 31);
2009-11-21 08:38:05 +01:00
// msg 31: "DEFINE TRIGGER failed"
2001-12-25 05:10:23 +01:00
}
throw;
}
2001-05-23 15:26:42 +02:00
}
void DYN_define_view_relation( Global* gbl, const UCHAR** ptr, const Firebird::MetaName* view)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D Y N _ d e f i n e _ v i e w _ r e l a t i o n
*
**************************************
*
* Functional description
* Store a RDB$VIEW_RELATION record.
*
**************************************/
2001-12-25 05:10:23 +01:00
thread_db* tdbb = JRD_get_thread_data();
2001-12-25 05:10:23 +01:00
fb_assert(view);
2002-06-30 10:46:51 +02:00
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, drq_s_view_rels, DYN_REQUESTS);
SSHORT id = drq_s_view_rels;
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
bool b_ending_store = false;
2009-12-17 01:38:55 +01:00
try
{
2001-12-25 05:10:23 +01:00
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
2005-05-28 00:45:31 +02:00
VRL IN RDB$VIEW_RELATIONS
2010-04-18 03:10:05 +02:00
{
strcpy(VRL.RDB$VIEW_NAME, view->c_str());
2001-12-25 05:10:23 +01:00
GET_STRING(ptr, VRL.RDB$RELATION_NAME);
VRL.RDB$CONTEXT_NAME.NULL = TRUE;
VRL.RDB$VIEW_CONTEXT.NULL = TRUE;
VRL.RDB$CONTEXT_TYPE.NULL = TRUE;
VRL.RDB$PACKAGE_NAME.NULL = TRUE;
UCHAR verb;
2003-11-08 17:40:17 +01:00
while ((verb = *(*ptr)++) != isc_dyn_end)
2001-05-23 15:26:42 +02:00
{
2001-12-25 05:10:23 +01:00
switch (verb)
{
2003-11-08 17:40:17 +01:00
case isc_dyn_view_context:
2001-12-25 05:10:23 +01:00
VRL.RDB$VIEW_CONTEXT = DYN_get_number(ptr);
VRL.RDB$VIEW_CONTEXT.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
2003-11-08 17:40:17 +01:00
case isc_dyn_view_context_name:
2001-12-25 05:10:23 +01:00
GET_STRING(ptr, VRL.RDB$CONTEXT_NAME);
VRL.RDB$CONTEXT_NAME.NULL = FALSE;
break;
2001-05-23 15:26:42 +02:00
case isc_dyn_view_context_type:
VRL.RDB$CONTEXT_TYPE = DYN_get_number(ptr);
VRL.RDB$CONTEXT_TYPE.NULL = FALSE;
break;
case isc_dyn_pkg_name:
GET_STRING(ptr, VRL.RDB$PACKAGE_NAME);
VRL.RDB$PACKAGE_NAME.NULL = FALSE;
break;
2001-12-25 05:10:23 +01:00
default:
--(*ptr);
2010-01-24 16:16:23 +01:00
{
const MetaName tmp(VRL.RDB$RELATION_NAME);
DYN_execute(gbl, ptr, &tmp, NULL, NULL, NULL, NULL);
2010-01-24 16:16:23 +01:00
}
2001-12-25 05:10:23 +01:00
}
2001-05-23 15:26:42 +02:00
}
2001-12-25 05:10:23 +01:00
b_ending_store = true;
}
2010-04-18 03:10:05 +02:00
END_STORE
2001-12-25 05:10:23 +01:00
}
2009-01-14 10:19:00 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2009-11-25 05:06:48 +01:00
if (b_ending_store)
{
if (id == drq_s_view_rels)
{
DYN_error_punt(true, 34);
2009-11-21 08:38:05 +01:00
// msg 34: "STORE RDB$VIEW_RELATIONS failed"
}
2001-05-23 15:26:42 +02:00
}
2001-12-25 05:10:23 +01:00
throw;
}
2001-05-23 15:26:42 +02:00
}
bool is_it_user_name(Global* gbl, const Firebird::MetaName& role_name, thread_db* tdbb)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* i s _ i t _ u s e r _ n a m e
*
**************************************
*
* Functional description
*
* if role_name is user name returns true. Otherwise returns false.
2001-05-23 15:26:42 +02:00
*
**************************************/
2001-12-25 05:10:23 +01:00
USHORT request_id;
2001-05-23 15:26:42 +02:00
SET_TDBB(tdbb);
bool found = false;
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
try {
2009-11-21 08:38:05 +01:00
// If there is a user with privilege or a grantor on a relation we
// can infer there is a user with this name
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
request_id = drq_get_user_priv;
2010-04-18 03:10:05 +02:00
AutoCacheRequest request(tdbb, request_id, DYN_REQUESTS);
2001-12-25 05:10:23 +01:00
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
PRIV IN RDB$USER_PRIVILEGES WITH
(PRIV.RDB$USER EQ role_name.c_str() AND
2001-12-25 05:10:23 +01:00
PRIV.RDB$USER_TYPE = obj_user) OR
(PRIV.RDB$GRANTOR EQ role_name.c_str() AND
2001-12-25 05:10:23 +01:00
PRIV.RDB$OBJECT_TYPE = obj_relation)
2010-04-18 03:10:05 +02:00
{
2008-12-18 11:57:12 +01:00
found = true;
2010-04-18 03:10:05 +02:00
}
END_FOR
2001-05-23 15:26:42 +02:00
2010-04-18 03:10:05 +02:00
if (found)
2001-12-25 05:10:23 +01:00
return found;
2001-05-23 15:26:42 +02:00
2009-11-21 08:38:05 +01:00
// We can infer that 'role_name' is a user name if it owns any relations
// Note we can only get here if a user creates a table and revokes all
// his privileges on the table
2001-05-23 15:26:42 +02:00
2001-12-25 05:10:23 +01:00
request_id = drq_get_rel_owner;
2010-04-18 03:10:05 +02:00
request.reset(tdbb, request_id, DYN_REQUESTS);
2001-12-25 05:10:23 +01:00
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction)
REL IN RDB$RELATIONS WITH
2005-05-28 00:45:31 +02:00
REL.RDB$OWNER_NAME EQ role_name.c_str()
2010-04-18 03:10:05 +02:00
{
found = true;
2001-12-25 05:10:23 +01:00
}
2010-04-18 03:10:05 +02:00
END_FOR
2001-12-24 03:51:06 +01:00
}
2009-11-25 05:06:48 +01:00
catch (const Firebird::Exception& ex)
{
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
2001-12-24 03:51:06 +01:00
ERR_punt();
}
2001-05-23 15:26:42 +02:00
return found;
}