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

894 lines
22 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 "../common/common.h"
2001-05-23 15:26:42 +02:00
#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 "../common/gdsassert.h"
2001-05-23 15:26:42 +02:00
#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"
2010-10-12 10:02:57 +02:00
#include "../yvalve/gds_proto.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/inf_proto.h"
#include "../jrd/intl_proto.h"
2010-10-12 10:02:57 +02:00
#include "../common/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 "../common/gdsassert.h"
2010-10-12 10:02:57 +02:00
#include "../common/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"
2010-10-12 10:02:57 +02:00
#include "../common/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$DETERMINISTIC_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
}
2010-08-07 04:44:39 +02:00
void DYN_define_index(Global* gbl, const UCHAR** ptr, const Firebird::MetaName* relation_name)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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();
2010-08-07 04:44:39 +02:00
const UCHAR index_type = isc_dyn_def_idx;
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
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;
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
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);
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_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_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();
}
}
}
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;
}