2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
2003-09-25 13:49:12 +02:00
|
|
|
* MODULE: met.epp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Meta data handler
|
|
|
|
*
|
|
|
|
* 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-02-24 17:39:31 +01:00
|
|
|
*
|
2002-07-01 18:59:09 +02:00
|
|
|
* 2001.6.25 Claudio Valderrama: Finish MET_lookup_generator_id() by
|
|
|
|
* assigning it a number in the compiled requests table.
|
|
|
|
*
|
|
|
|
* 2001.07.06 Sean Leyne - Code Cleanup, removed "#ifdef READONLY_DATABASE"
|
|
|
|
* conditionals, as the engine now fully supports
|
|
|
|
* readonly databases.
|
|
|
|
* 2001.10.03 Claudio Valderrama: MET_relation_owns_trigger() determines if
|
|
|
|
* there's a row in rdb$triggers with the given relation's and trigger's names.
|
|
|
|
* 2001.10.04 Claudio Valderrama: MET_relation_default_class() determines if the
|
|
|
|
* given security class name is the default security class for a relation.
|
|
|
|
* Modify MET_lookup_field() so it can verify the field's security class, too.
|
2002-09-19 18:02:58 +02:00
|
|
|
* 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY)
|
|
|
|
* 2002-09-16 Nickolay Samofatov - Deferred trigger compilation changes
|
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
|
|
|
*/
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
#include "firebird.h"
|
2004-04-29 00:43:34 +02:00
|
|
|
#include <stdio.h>
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2003-11-08 17:40:17 +01:00
|
|
|
#include "../jrd/ibase.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/jrd.h"
|
|
|
|
#include "../jrd/val.h"
|
|
|
|
#include "../jrd/irq.h"
|
|
|
|
#include "../jrd/tra.h"
|
|
|
|
#include "../jrd/lck.h"
|
|
|
|
#include "../jrd/ods.h"
|
|
|
|
#include "../jrd/btr.h"
|
|
|
|
#include "../jrd/req.h"
|
|
|
|
#include "../jrd/exe.h"
|
|
|
|
#include "../jrd/scl.h"
|
|
|
|
#include "../jrd/blb.h"
|
|
|
|
#include "../jrd/met.h"
|
2003-07-14 12:35:49 +02:00
|
|
|
#include "../jrd/os/pio.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/sdw.h"
|
|
|
|
#include "../jrd/flags.h"
|
|
|
|
#include "../jrd/lls.h"
|
|
|
|
#include "../jrd/intl.h"
|
|
|
|
#include "../jrd/align.h"
|
|
|
|
#include "../jrd/flu.h"
|
|
|
|
#include "../jrd/blob_filter.h"
|
2010-12-04 23:15:03 +01:00
|
|
|
#include "../dsql/StmtNodes.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../intl/charsets.h"
|
2010-10-13 12:39:52 +02:00
|
|
|
#include "../common/gdsassert.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/blb_proto.h"
|
|
|
|
#include "../jrd/cmp_proto.h"
|
|
|
|
#include "../jrd/dfw_proto.h"
|
2010-10-12 10:02:57 +02:00
|
|
|
#include "../common/dsc_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/err_proto.h"
|
2011-02-03 10:35:57 +01:00
|
|
|
#include "../jrd/evl_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/exe_proto.h"
|
|
|
|
#include "../jrd/ext_proto.h"
|
|
|
|
#include "../jrd/flu_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/idx_proto.h"
|
|
|
|
#include "../jrd/ini_proto.h"
|
|
|
|
|
|
|
|
#include "../jrd/lck_proto.h"
|
|
|
|
#include "../jrd/met_proto.h"
|
|
|
|
#include "../jrd/mov_proto.h"
|
|
|
|
#include "../jrd/par_proto.h"
|
|
|
|
#include "../jrd/pcmet_proto.h"
|
2003-07-14 12:35:49 +02:00
|
|
|
#include "../jrd/os/pio_proto.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/scl_proto.h"
|
|
|
|
#include "../jrd/sdw_proto.h"
|
2004-05-18 00:30:09 +02:00
|
|
|
#include "../jrd/thread_proto.h"
|
2003-12-31 06:36:12 +01:00
|
|
|
#include "../common/utils_proto.h"
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
#include "../jrd/PreparedStatement.h"
|
2010-10-12 13:36:51 +02:00
|
|
|
#include "../jrd/RecordSourceNodes.h"
|
2009-10-21 02:42:38 +02:00
|
|
|
#include "../jrd/DebugInterface.h"
|
2007-03-28 06:20:36 +02:00
|
|
|
#include "../common/classes/MsgPrint.h"
|
2009-12-21 18:43:01 +01:00
|
|
|
#include "../jrd/Function.h"
|
2007-03-28 06:20:36 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-07-12 08:32:05 +02:00
|
|
|
#ifdef HAVE_CTYPE_H
|
|
|
|
#include <ctype.h>
|
|
|
|
#endif
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Pick up relation ids
|
2004-05-18 18:40:20 +02:00
|
|
|
#include "../jrd/ini.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
DATABASE DB = FILENAME "ODS.RDB";
|
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
using namespace Jrd;
|
2008-08-27 14:20:47 +02:00
|
|
|
using namespace Firebird;
|
2004-03-20 15:57:40 +01:00
|
|
|
|
2008-03-01 20:14:46 +01:00
|
|
|
static int blocking_ast_dsql_cache(void* ast_object);
|
2009-10-21 02:42:38 +02:00
|
|
|
static DSqlCacheItem* get_dsql_cache_item(thread_db* tdbb, int type, const QualifiedName& name);
|
2004-03-18 06:56:06 +01:00
|
|
|
static int blocking_ast_procedure(void*);
|
|
|
|
static int blocking_ast_relation(void*);
|
2005-06-26 23:48:47 +02:00
|
|
|
static int partners_ast_relation(void*);
|
2010-06-15 14:27:33 +02:00
|
|
|
static int rescan_ast_relation(void*);
|
2011-05-30 16:26:15 +02:00
|
|
|
static ULONG get_rel_flags_from_FLAGS(USHORT);
|
2009-10-21 02:42:38 +02:00
|
|
|
static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, trig_vec**, const TEXT*, FB_UINT64, bool,
|
2010-06-12 18:32:46 +02:00
|
|
|
USHORT, const MetaName&, const string&, const bid*);
|
2006-04-05 18:34:18 +02:00
|
|
|
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
|
2004-03-11 06:04:26 +01:00
|
|
|
static void lookup_view_contexts(thread_db*, jrd_rel*);
|
2010-06-12 18:32:46 +02:00
|
|
|
static void make_relation_scope_name(const TEXT*, const USHORT, string& str);
|
2010-12-04 23:15:03 +01:00
|
|
|
static ValueExprNode* parse_field_default_blr(thread_db* tdbb, bid* blob_id);
|
2013-03-31 20:23:54 +02:00
|
|
|
static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, const MetaName name);
|
2008-12-18 11:57:12 +01:00
|
|
|
static bool resolve_charset_and_collation(thread_db*, USHORT*, const UCHAR*, const UCHAR*);
|
2010-04-19 00:19:11 +02:00
|
|
|
static void save_trigger_data(thread_db*, trig_vec**, jrd_rel*, JrdStatement*, blb*, bid*,
|
2010-06-12 18:32:46 +02:00
|
|
|
const TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&,
|
2009-10-21 02:42:38 +02:00
|
|
|
const bid*);
|
2010-01-19 19:33:03 +01:00
|
|
|
static void scan_partners(thread_db*, jrd_rel*);
|
2008-07-21 17:49:24 +02:00
|
|
|
static void store_dependencies(thread_db*, CompilerScratch*, const jrd_rel*,
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName&, int, jrd_tra*);
|
|
|
|
static bool verify_TRG_ignore_perm(thread_db*, const MetaName&);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2002-09-28 00:59:24 +02:00
|
|
|
// Decompile all triggers from vector
|
2004-04-18 04:50:38 +02:00
|
|
|
static void release_cached_triggers(thread_db* tdbb, trig_vec* vector)
|
2002-09-28 00:59:24 +02:00
|
|
|
{
|
2005-05-28 00:45:31 +02:00
|
|
|
if (!vector)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
2003-12-22 11:00:59 +01:00
|
|
|
return;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
|
|
|
for (size_t i = 0; i < vector->getCount(); i++)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
|
|
|
(*vector)[i].release(tdbb);
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2002-09-28 00:59:24 +02:00
|
|
|
}
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
|
2010-04-19 00:19:11 +02:00
|
|
|
static void inc_int_use_count(JrdStatement* statement)
|
2004-05-09 07:48:33 +02:00
|
|
|
{
|
2004-04-18 04:50:38 +02:00
|
|
|
// Increment int_use_count for all procedures in resource list of request
|
2010-04-19 00:19:11 +02:00
|
|
|
ResourceList& list = statement->resources;
|
2004-07-17 02:13:34 +02:00
|
|
|
size_t i;
|
2006-08-07 18:39:21 +02:00
|
|
|
for (list.find(Resource(Resource::rsc_procedure, 0, NULL, NULL, NULL), i);
|
2010-04-19 00:19:11 +02:00
|
|
|
i < list.getCount(); i++)
|
2004-04-18 04:50:38 +02:00
|
|
|
{
|
2004-05-09 07:48:33 +02:00
|
|
|
Resource& resource = list[i];
|
2005-05-28 00:45:31 +02:00
|
|
|
if (resource.rsc_type != Resource::rsc_procedure)
|
2004-04-18 04:50:38 +02:00
|
|
|
break;
|
|
|
|
fb_assert(resource.rsc_prc->prc_int_use_count >= 0);
|
|
|
|
++resource.rsc_prc->prc_int_use_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
|
2003-12-06 03:58:22 +01:00
|
|
|
// Increment int_use_count for all procedures used by triggers
|
2004-04-19 17:29:29 +02:00
|
|
|
static void post_used_procedures(trig_vec* vector)
|
2003-12-06 03:58:22 +01:00
|
|
|
{
|
2005-05-28 00:45:31 +02:00
|
|
|
if (!vector)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
2003-12-22 11:00:59 +01:00
|
|
|
return;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
|
|
|
for (size_t i = 0; i < vector->getCount(); i++)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement* stmt = (*vector)[i].statement;
|
|
|
|
if (stmt && !stmt->isActive())
|
|
|
|
inc_int_use_count(stmt);
|
2004-04-19 17:29:29 +02:00
|
|
|
}
|
2003-12-06 03:58:22 +01:00
|
|
|
}
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
void MET_get_domain(thread_db* tdbb, const MetaName& name, dsc* desc, FieldInfo* fieldInfo)
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2007-01-21 16:35:35 +01:00
|
|
|
* M E T _ g e t _ d o m a i n
|
2006-08-19 04:52:39 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2007-01-21 16:35:35 +01:00
|
|
|
* Get domain descriptor and informations.
|
2006-08-19 04:52:39 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2006-08-19 04:52:39 +02:00
|
|
|
bool found = false;
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest handle(tdbb, irq_l_domain, IRQ_REQUESTS);
|
2006-08-19 04:52:39 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2006-08-19 04:52:39 +02:00
|
|
|
if (DSC_make_descriptor(desc,
|
|
|
|
FLD.RDB$FIELD_TYPE,
|
|
|
|
FLD.RDB$FIELD_SCALE,
|
|
|
|
FLD.RDB$FIELD_LENGTH,
|
|
|
|
FLD.RDB$FIELD_SUB_TYPE,
|
|
|
|
FLD.RDB$CHARACTER_SET_ID,
|
|
|
|
FLD.RDB$COLLATION_ID))
|
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
found = true;
|
2007-01-17 02:19:01 +01:00
|
|
|
|
|
|
|
if (fieldInfo)
|
|
|
|
{
|
|
|
|
fieldInfo->nullable = FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0;
|
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
MemoryPool* csb_pool = attachment->createPool();
|
2007-01-21 16:35:35 +01:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, csb_pool);
|
|
|
|
try
|
2007-01-17 02:19:01 +01:00
|
|
|
{
|
2007-01-21 16:35:35 +01:00
|
|
|
if (FLD.RDB$DEFAULT_VALUE.NULL)
|
|
|
|
fieldInfo->defaultValue = NULL;
|
|
|
|
else
|
2010-11-07 21:26:11 +01:00
|
|
|
fieldInfo->defaultValue = parse_field_default_blr(tdbb, &FLD.RDB$DEFAULT_VALUE);
|
2007-01-17 02:19:01 +01:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
if (FLD.RDB$VALIDATION_BLR.NULL)
|
2010-11-07 21:26:11 +01:00
|
|
|
fieldInfo->validationExpr = NULL;
|
2008-01-16 10:29:37 +01:00
|
|
|
else
|
2010-11-07 21:26:11 +01:00
|
|
|
{
|
2013-03-31 20:23:54 +02:00
|
|
|
fieldInfo->validationExpr = parse_field_validation_blr(tdbb,
|
|
|
|
&FLD.RDB$VALIDATION_BLR, name);
|
2010-11-07 21:26:11 +01:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
}
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->deletePool(csb_pool);
|
2008-01-16 10:29:37 +01:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2007-01-17 02:19:01 +01:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
if (!found)
|
|
|
|
{
|
2008-08-27 14:20:47 +02:00
|
|
|
ERR_post(Arg::Gds(isc_domnotdef) << Arg::Str(name));
|
2008-01-16 10:29:37 +01:00
|
|
|
}
|
|
|
|
}
|
2007-01-17 02:19:01 +01:00
|
|
|
|
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName MET_get_relation_field(thread_db* tdbb,
|
|
|
|
const MetaName& relationName,
|
|
|
|
const MetaName& fieldName,
|
2008-06-26 12:48:28 +02:00
|
|
|
dsc* desc,
|
|
|
|
FieldInfo* fieldInfo)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ g e t _ r e l a t i o n _ f i e l d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get relation field descriptor and informations.
|
|
|
|
* Returns field source name.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2008-01-16 10:29:37 +01:00
|
|
|
bool found = false;
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName sourceName;
|
2007-01-17 02:19:01 +01:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest handle(tdbb, irq_l_relfield, IRQ_REQUESTS);
|
2007-01-17 02:19:01 +01:00
|
|
|
|
2008-01-16 10:29:37 +01:00
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
RFL IN RDB$RELATION_FIELDS CROSS
|
|
|
|
FLD IN RDB$FIELDS WITH
|
|
|
|
RFL.RDB$RELATION_NAME EQ relationName.c_str() AND
|
|
|
|
RFL.RDB$FIELD_NAME EQ fieldName.c_str() AND
|
|
|
|
FLD.RDB$FIELD_NAME EQ RFL.RDB$FIELD_SOURCE
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2008-01-16 10:29:37 +01:00
|
|
|
if (DSC_make_descriptor(desc,
|
|
|
|
FLD.RDB$FIELD_TYPE,
|
|
|
|
FLD.RDB$FIELD_SCALE,
|
|
|
|
FLD.RDB$FIELD_LENGTH,
|
|
|
|
FLD.RDB$FIELD_SUB_TYPE,
|
|
|
|
FLD.RDB$CHARACTER_SET_ID,
|
2011-03-22 19:59:13 +01:00
|
|
|
(RFL.RDB$COLLATION_ID.NULL ? FLD.RDB$COLLATION_ID : RFL.RDB$COLLATION_ID)))
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
sourceName = RFL.RDB$FIELD_SOURCE;
|
|
|
|
|
|
|
|
if (fieldInfo)
|
|
|
|
{
|
|
|
|
fieldInfo->nullable = RFL.RDB$NULL_FLAG.NULL ?
|
2008-12-18 11:57:12 +01:00
|
|
|
(FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0) : RFL.RDB$NULL_FLAG == 0;
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
MemoryPool* csb_pool = attachment->createPool();
|
2008-01-16 10:29:37 +01:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, csb_pool);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
bid* defaultId = NULL;
|
|
|
|
|
|
|
|
if (!RFL.RDB$DEFAULT_VALUE.NULL)
|
|
|
|
defaultId = &RFL.RDB$DEFAULT_VALUE;
|
|
|
|
else if (!FLD.RDB$DEFAULT_VALUE.NULL)
|
|
|
|
defaultId = &FLD.RDB$DEFAULT_VALUE;
|
|
|
|
|
|
|
|
if (defaultId)
|
2010-11-07 21:26:11 +01:00
|
|
|
fieldInfo->defaultValue = parse_field_default_blr(tdbb, defaultId);
|
2008-01-16 10:29:37 +01:00
|
|
|
else
|
|
|
|
fieldInfo->defaultValue = NULL;
|
|
|
|
|
2010-11-07 21:26:11 +01:00
|
|
|
if (FLD.RDB$VALIDATION_BLR.NULL)
|
|
|
|
fieldInfo->validationExpr = NULL;
|
2008-01-16 10:29:37 +01:00
|
|
|
else
|
2010-11-07 21:26:11 +01:00
|
|
|
{
|
2013-03-31 20:23:54 +02:00
|
|
|
fieldInfo->validationExpr = parse_field_validation_blr(tdbb,
|
|
|
|
&FLD.RDB$VALIDATION_BLR, RFL.RDB$FIELD_SOURCE);
|
2010-11-07 21:26:11 +01:00
|
|
|
}
|
2007-01-21 16:35:35 +01:00
|
|
|
}
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2007-01-21 16:35:35 +01:00
|
|
|
{
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->deletePool(csb_pool);
|
2007-01-21 16:35:35 +01:00
|
|
|
throw;
|
2007-01-17 02:19:01 +01:00
|
|
|
}
|
|
|
|
}
|
2006-08-19 04:52:39 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2007-01-21 16:35:35 +01:00
|
|
|
|
|
|
|
if (!found)
|
|
|
|
{
|
2008-12-14 10:28:25 +01:00
|
|
|
ERR_post(Arg::Gds(isc_dyn_column_does_not_exist) << Arg::Str(fieldName) <<
|
2008-08-27 14:20:47 +02:00
|
|
|
Arg::Str(relationName));
|
2007-01-21 16:35:35 +01:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
|
|
|
|
return sourceName;
|
2006-08-19 04:52:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
void MET_update_partners(thread_db* tdbb)
|
2002-09-30 16:21:34 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ u p d a t e _ p a r t n e r s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Mark all relations to update their links to FK partners
|
|
|
|
* Called when any index is deleted because engine don't know
|
|
|
|
* was it used in any FK or not
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2011-05-09 12:15:19 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2002-09-30 16:21:34 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_rel*>* relations = attachment->att_relations;
|
2002-09-30 16:21:34 +02:00
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_rel*>::iterator ptr = relations->begin();
|
2006-02-10 04:28:43 +01:00
|
|
|
for (const vec<jrd_rel*>::const_iterator end = relations->end(); ptr < end; ++ptr)
|
2002-09-30 16:21:34 +02:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
jrd_rel* relation = *ptr;
|
2004-01-03 11:59:52 +01:00
|
|
|
if (!relation) {
|
2003-12-22 11:00:59 +01:00
|
|
|
continue;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2005-06-26 23:48:47 +02:00
|
|
|
|
|
|
|
// signal other processes
|
2008-01-31 14:36:11 +01:00
|
|
|
LCK_lock(tdbb, relation->rel_partners_lock, LCK_EX, LCK_WAIT);
|
2005-06-26 23:48:47 +02:00
|
|
|
LCK_release(tdbb, relation->rel_partners_lock);
|
2002-09-30 16:21:34 +02:00
|
|
|
relation->rel_flags |= REL_check_partners;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
|
2004-05-21 08:16:17 +02:00
|
|
|
void adjust_dependencies(jrd_prc* procedure)
|
|
|
|
{
|
2009-11-07 12:58:54 +01:00
|
|
|
if (procedure->prc_int_use_count == -1)
|
|
|
|
{
|
|
|
|
// Already processed
|
2002-10-05 00:08:43 +02:00
|
|
|
return;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2003-12-22 11:00:59 +01:00
|
|
|
procedure->prc_int_use_count = -1; // Mark as undeletable
|
2010-04-19 00:19:11 +02:00
|
|
|
if (procedure->getStatement())
|
2009-11-07 12:58:54 +01:00
|
|
|
{
|
2009-12-27 23:05:22 +01:00
|
|
|
// Loop over procedures from resource list of request
|
2010-04-19 00:19:11 +02:00
|
|
|
ResourceList& list = procedure->getStatement()->resources;
|
2004-07-17 02:13:34 +02:00
|
|
|
size_t i;
|
2006-08-07 18:39:21 +02:00
|
|
|
for (list.find(Resource(Resource::rsc_procedure, 0, NULL, NULL, NULL), i);
|
2008-12-18 11:57:12 +01:00
|
|
|
i < list.getCount(); i++)
|
2003-06-30 15:11:40 +02:00
|
|
|
{
|
2004-05-09 07:48:33 +02:00
|
|
|
Resource& resource = list[i];
|
2005-05-28 00:45:31 +02:00
|
|
|
if (resource.rsc_type != Resource::rsc_procedure)
|
2004-04-18 04:50:38 +02:00
|
|
|
break;
|
|
|
|
procedure = resource.rsc_prc;
|
2009-11-07 12:58:54 +01:00
|
|
|
if (procedure->prc_int_use_count == procedure->prc_use_count)
|
|
|
|
{
|
2004-04-18 04:50:38 +02:00
|
|
|
// Mark it and all dependent procedures as undeletable
|
2005-05-28 00:45:31 +02:00
|
|
|
adjust_dependencies(procedure);
|
2002-10-05 00:08:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
|
2003-06-01 18:22:47 +02:00
|
|
|
#ifdef DEV_BUILD
|
2004-05-21 08:16:17 +02:00
|
|
|
void MET_verify_cache(thread_db* tdbb)
|
|
|
|
{
|
2003-06-01 18:22:47 +02:00
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ v e r i f y _ c a c h e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Check if all links between procedures are properly counted
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2011-05-09 12:15:19 +02:00
|
|
|
Jrd::Attachment* att = tdbb->getAttachment();
|
|
|
|
if (!att)
|
|
|
|
return;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_prc*>* procedures = att->att_procedures;
|
2009-11-07 12:58:54 +01:00
|
|
|
if (procedures)
|
|
|
|
{
|
2003-12-22 11:00:59 +01:00
|
|
|
jrd_prc* procedure;
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_prc*>::iterator ptr, end;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ++ptr)
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if ( (procedure = *ptr) && procedure->getStatement() /*&&
|
2005-05-28 00:45:31 +02:00
|
|
|
!(procedure->prc_flags & PRC_obsolete)*/ )
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(procedure->prc_int_use_count == 0);
|
2003-06-01 18:22:47 +02:00
|
|
|
}
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Walk procedures and calculate internal dependencies
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ptr++)
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if ( (procedure = *ptr) && procedure->getStatement() /*&&
|
2005-05-28 00:45:31 +02:00
|
|
|
!(procedure->prc_flags & PRC_obsolete)*/ )
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
inc_int_use_count(procedure->getStatement());
|
2003-06-01 18:22:47 +02:00
|
|
|
}
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Walk procedures again and check dependencies
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ptr++)
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if ( (procedure = *ptr) && procedure->getStatement() && /*
|
2003-06-01 18:22:47 +02:00
|
|
|
!(procedure->prc_flags & PRC_obsolete) && */
|
|
|
|
procedure->prc_use_count < procedure->prc_int_use_count)
|
|
|
|
{
|
|
|
|
char buffer[1024], *buf = buffer;
|
2005-05-28 00:45:31 +02:00
|
|
|
buf += sprintf(buf, "Procedure %d:%s is not properly counted (use count=%d, prc use=%d). Used by: \n",
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->getId(), procedure->getName().toString().c_str(),
|
|
|
|
procedure->prc_use_count, procedure->prc_int_use_count);
|
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_prc*>::const_iterator ptr2 = procedures->begin();
|
|
|
|
for (const vec<jrd_prc*>::const_iterator end2 = procedures->end();
|
2006-02-10 04:28:43 +01:00
|
|
|
ptr2 < end2; ++ptr2)
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
const jrd_prc* prc = *ptr2;
|
2010-04-19 00:19:11 +02:00
|
|
|
if (prc && prc->getStatement() /*&& !(prc->prc_flags & PRC_obsolete)*/ )
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2009-12-27 23:05:22 +01:00
|
|
|
// Loop over procedures from resource list of request
|
2010-04-19 00:19:11 +02:00
|
|
|
const ResourceList& list = prc->getStatement()->resources;
|
2004-07-17 02:13:34 +02:00
|
|
|
size_t i;
|
2006-08-07 18:39:21 +02:00
|
|
|
for (list.find(Resource(Resource::rsc_procedure, 0, NULL, NULL, NULL), i);
|
2005-05-28 00:45:31 +02:00
|
|
|
i < list.getCount(); i++)
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2004-04-18 04:50:38 +02:00
|
|
|
const Resource& resource = list[i];
|
2005-05-28 00:45:31 +02:00
|
|
|
if (resource.rsc_type != Resource::rsc_procedure)
|
2004-04-18 04:50:38 +02:00
|
|
|
break;
|
2009-12-27 23:05:22 +01:00
|
|
|
|
|
|
|
if (resource.rsc_prc == procedure)
|
|
|
|
{
|
2009-12-28 12:46:55 +01:00
|
|
|
// Do not enable this code in production builds unless
|
|
|
|
// the possible B.O. is fixed here.
|
2009-12-27 23:05:22 +01:00
|
|
|
buf += sprintf(buf, "%d:%s\n", prc->getId(),
|
|
|
|
prc->getName().toString().c_str());
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2003-06-01 18:22:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gds__log(buffer);
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(false);
|
2003-06-01 18:22:47 +02:00
|
|
|
}
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Fix back int_use_count
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ptr++)
|
2003-06-01 18:22:47 +02:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
if ( (procedure = *ptr) )
|
2005-05-28 00:45:31 +02:00
|
|
|
{
|
2003-06-01 18:22:47 +02:00
|
|
|
procedure->prc_int_use_count = 0;
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
}
|
2003-06-01 18:22:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
|
2004-04-10 21:46:48 +02:00
|
|
|
void MET_clear_cache(thread_db* tdbb)
|
2002-09-28 00:59:24 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2002-10-05 00:08:43 +02:00
|
|
|
* M E T _ c l e a r _ c a c h e
|
2002-09-28 00:59:24 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2005-05-28 00:45:31 +02:00
|
|
|
* Remove all unused objects from metadata cache to
|
2004-04-10 21:46:48 +02:00
|
|
|
* release resources they use
|
2002-09-28 00:59:24 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2003-06-01 18:22:47 +02:00
|
|
|
#ifdef DEV_BUILD
|
|
|
|
MET_verify_cache(tdbb);
|
|
|
|
#endif
|
2003-12-22 11:00:59 +01:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
Jrd::Attachment* att = tdbb->getAttachment();
|
2003-12-22 11:00:59 +01:00
|
|
|
|
2009-03-15 19:04:04 +01:00
|
|
|
for (int i = 0; i < DB_TRIGGER_MAX; i++) {
|
2011-05-09 12:15:19 +02:00
|
|
|
release_cached_triggers(tdbb, att->att_triggers[i]);
|
2009-03-15 19:04:04 +01:00
|
|
|
}
|
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_rel*>* relations = att->att_relations;
|
2009-03-15 21:09:15 +01:00
|
|
|
if (relations)
|
2005-12-02 08:35:34 +01:00
|
|
|
{ // scope
|
|
|
|
vec<jrd_rel*>::iterator ptr, end;
|
2006-02-10 04:28:43 +01:00
|
|
|
for (ptr = relations->begin(), end = relations->end(); ptr < end; ++ptr)
|
2005-12-02 08:35:34 +01:00
|
|
|
{
|
|
|
|
jrd_rel* relation = *ptr;
|
|
|
|
if (!relation)
|
|
|
|
continue;
|
|
|
|
release_cached_triggers(tdbb, relation->rel_pre_store);
|
|
|
|
release_cached_triggers(tdbb, relation->rel_post_store);
|
|
|
|
release_cached_triggers(tdbb, relation->rel_pre_erase);
|
|
|
|
release_cached_triggers(tdbb, relation->rel_post_erase);
|
|
|
|
release_cached_triggers(tdbb, relation->rel_pre_modify);
|
|
|
|
release_cached_triggers(tdbb, relation->rel_post_modify);
|
|
|
|
}
|
|
|
|
} // scope
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_prc*>* procedures = att->att_procedures;
|
2005-12-02 08:35:34 +01:00
|
|
|
if (procedures)
|
|
|
|
{
|
2003-12-22 11:00:59 +01:00
|
|
|
jrd_prc* procedure;
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_prc*>::iterator ptr, end;
|
2009-11-21 04:23:47 +01:00
|
|
|
// Walk procedures and calculate internal dependencies
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ++ptr)
|
2002-10-05 00:08:43 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if ( (procedure = *ptr) && procedure->getStatement() &&
|
2005-05-28 00:45:31 +02:00
|
|
|
!(procedure->prc_flags & PRC_obsolete) )
|
2002-09-28 00:59:24 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
inc_int_use_count(procedure->getStatement());
|
2002-09-28 00:59:24 +02:00
|
|
|
}
|
2002-10-05 00:08:43 +02:00
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
// Walk procedures again and adjust dependencies for procedures
|
|
|
|
// which will not be removed.
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ptr++)
|
2002-10-05 00:08:43 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if ( (procedure = *ptr) && procedure->getStatement() &&
|
2008-12-18 11:57:12 +01:00
|
|
|
!(procedure->prc_flags & PRC_obsolete) &&
|
|
|
|
procedure->prc_use_count != procedure->prc_int_use_count )
|
2002-10-05 00:08:43 +02:00
|
|
|
{
|
|
|
|
adjust_dependencies(procedure);
|
|
|
|
}
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Deallocate all used requests
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ptr++)
|
2002-10-05 00:08:43 +02:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
if ( (procedure = *ptr) )
|
2002-10-05 00:08:43 +02:00
|
|
|
{
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2010-04-19 00:19:11 +02:00
|
|
|
if ( procedure->getStatement() && !(procedure->prc_flags & PRC_obsolete) &&
|
2005-05-28 00:45:31 +02:00
|
|
|
procedure->prc_int_use_count >= 0 &&
|
|
|
|
procedure->prc_use_count == procedure->prc_int_use_count )
|
2002-10-05 00:08:43 +02:00
|
|
|
{
|
2012-04-12 15:03:25 +02:00
|
|
|
procedure->releaseStatement(tdbb);
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
if (procedure->prc_existence_lock) //// TODO: verify why this IF is necessary now
|
|
|
|
LCK_release(tdbb, procedure->prc_existence_lock);
|
2002-11-14 10:17:35 +01:00
|
|
|
procedure->prc_existence_lock = NULL;
|
|
|
|
procedure->prc_flags |= PRC_obsolete;
|
2003-06-01 18:22:47 +02:00
|
|
|
}
|
|
|
|
// Leave it in state 0 to avoid extra pass next time to clear it
|
|
|
|
// Note: we need to adjust prc_int_use_count for all procedures
|
|
|
|
// in cache because any of them may have been affected from
|
|
|
|
// dependencies earlier. Even procedures that were not scanned yet !
|
|
|
|
procedure->prc_int_use_count = 0;
|
2002-10-05 00:08:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-06-01 18:22:47 +02:00
|
|
|
#ifdef DEV_BUILD
|
|
|
|
MET_verify_cache(tdbb);
|
|
|
|
#endif
|
2002-09-28 00:59:24 +02:00
|
|
|
}
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
bool MET_procedure_in_use(thread_db* tdbb, jrd_prc* proc)
|
2003-12-06 03:58:22 +01:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ p r o c e d u r e _ i n _ u s e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2005-05-28 00:45:31 +02:00
|
|
|
* Determine if procedure is used by any user requests or transactions.
|
2004-02-20 07:43:27 +01:00
|
|
|
* Return false if procedure is used only inside cache or not used at all.
|
2003-12-06 03:58:22 +01:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
#ifdef DEV_BUILD
|
|
|
|
MET_verify_cache(tdbb);
|
|
|
|
#endif
|
2011-05-09 12:15:19 +02:00
|
|
|
Jrd::Attachment* att = tdbb->getAttachment();
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2003-12-06 03:58:22 +01:00
|
|
|
// This should not really happen
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_prc*>* procedures = att->att_procedures;
|
2004-01-03 11:59:52 +01:00
|
|
|
if (!procedures) {
|
2004-02-20 07:43:27 +01:00
|
|
|
return false;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2003-12-06 03:58:22 +01:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_rel*>* relations = att->att_relations;
|
2005-12-02 08:35:34 +01:00
|
|
|
{ // scope
|
|
|
|
vec<jrd_rel*>::iterator ptr, end;
|
2006-02-10 04:28:43 +01:00
|
|
|
for (ptr = relations->begin(), end = relations->end(); ptr < end; ++ptr)
|
2005-12-02 08:35:34 +01:00
|
|
|
{
|
|
|
|
jrd_rel* relation = *ptr;
|
|
|
|
if (!relation) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
post_used_procedures(relation->rel_pre_store);
|
|
|
|
post_used_procedures(relation->rel_post_store);
|
|
|
|
post_used_procedures(relation->rel_pre_erase);
|
|
|
|
post_used_procedures(relation->rel_post_erase);
|
|
|
|
post_used_procedures(relation->rel_pre_modify);
|
|
|
|
post_used_procedures(relation->rel_post_modify);
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2005-12-02 08:35:34 +01:00
|
|
|
} // scope
|
2003-12-22 11:00:59 +01:00
|
|
|
|
|
|
|
jrd_prc* procedure;
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_prc*>::iterator ptr, end;
|
2009-11-21 04:23:47 +01:00
|
|
|
// Walk procedures and calculate internal dependencies
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ++ptr)
|
2003-12-06 03:58:22 +01:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if ((procedure = *ptr) && procedure->getStatement() && !(procedure->prc_flags & PRC_obsolete))
|
|
|
|
inc_int_use_count(procedure->getStatement());
|
2003-12-06 03:58:22 +01:00
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
// Walk procedures again and adjust dependencies for procedures
|
|
|
|
// which will not be removed.
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ptr++)
|
2003-12-06 03:58:22 +01:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if ( (procedure = *ptr) && procedure->getStatement() &&
|
2008-12-18 11:57:12 +01:00
|
|
|
!(procedure->prc_flags & PRC_obsolete) &&
|
|
|
|
procedure->prc_use_count != procedure->prc_int_use_count && procedure != proc )
|
2003-12-06 03:58:22 +01:00
|
|
|
{
|
|
|
|
adjust_dependencies(procedure);
|
|
|
|
}
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
const bool result = proc->prc_use_count != proc->prc_int_use_count;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Fix back int_use_count
|
2008-12-18 11:57:12 +01:00
|
|
|
for (ptr = procedures->begin(), end = procedures->end(); ptr < end; ptr++)
|
2003-12-06 03:58:22 +01:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
if ( (procedure = *ptr) )
|
2005-05-28 00:45:31 +02:00
|
|
|
{
|
2003-12-06 03:58:22 +01:00
|
|
|
procedure->prc_int_use_count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef DEV_BUILD
|
|
|
|
MET_verify_cache(tdbb);
|
|
|
|
#endif
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_activate_shadow(thread_db* tdbb)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ a c t i v a t e _ s h a d o w
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Activate the current database, which presumably
|
|
|
|
* was formerly a shadow, by deleting all records
|
|
|
|
* corresponding to the shadow that this database
|
|
|
|
* represents.
|
|
|
|
* Get rid of write ahead log for the activated shadow.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Erase any secondary files of the primary database of the shadow being activated.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE handle) X IN RDB$FILES
|
|
|
|
WITH X.RDB$SHADOW_NUMBER NOT MISSING
|
2005-05-28 00:45:31 +02:00
|
|
|
AND X.RDB$SHADOW_NUMBER EQ 0
|
2008-12-18 11:57:12 +01:00
|
|
|
ERASE X;
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-05-22 00:07:35 +02:00
|
|
|
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
|
|
|
const char* dbb_file_name = pageSpace->file->fil_string;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// go through files looking for any that expand to the current database name
|
2003-12-22 11:00:59 +01:00
|
|
|
SCHAR expanded_name[MAXPATHLEN];
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle2;
|
|
|
|
handle.reset();
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE handle) X IN RDB$FILES
|
|
|
|
WITH X.RDB$SHADOW_NUMBER NOT MISSING
|
|
|
|
AND X.RDB$SHADOW_NUMBER NE 0
|
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
PIO_expand(X.RDB$FILE_NAME, (USHORT)strlen(X.RDB$FILE_NAME),
|
|
|
|
expanded_name, sizeof(expanded_name));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (!strcmp(expanded_name, dbb_file_name))
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE handle2) Y IN RDB$FILES
|
|
|
|
WITH X.RDB$SHADOW_NUMBER EQ Y.RDB$SHADOW_NUMBER
|
|
|
|
MODIFY Y
|
|
|
|
Y.RDB$SHADOW_NUMBER = 0;
|
2010-04-18 17:04:52 +02:00
|
|
|
END_MODIFY
|
|
|
|
END_FOR
|
2010-04-23 03:59:21 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
ERASE X;
|
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-27 07:59:21 +01:00
|
|
|
ULONG MET_align(const dsc* desc, ULONG value)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ a l i g n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Align value (presumed offset) on appropriate border
|
|
|
|
* and return.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-12-22 11:00:59 +01:00
|
|
|
USHORT alignment = desc->dsc_length;
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (desc->dsc_dtype)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case dtype_text:
|
|
|
|
case dtype_cstring:
|
|
|
|
return value;
|
|
|
|
|
|
|
|
case dtype_varying:
|
|
|
|
alignment = sizeof(USHORT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
alignment = MIN(alignment, FORMAT_ALIGNMENT);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return FB_ALIGN(value, alignment);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-07-12 03:38:41 +02:00
|
|
|
DeferredWork* MET_change_fields(thread_db* tdbb, jrd_tra* transaction, const dsc* field_source)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ c h a n g e _ f i e l d s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2006-08-19 04:52:39 +02:00
|
|
|
* Somebody is modifying RDB$FIELDS.
|
|
|
|
* Find all relations affected and schedule a format update.
|
|
|
|
* Find all procedures and triggers and schedule a BLR validate.
|
2009-12-26 14:22:52 +01:00
|
|
|
* Find all functions and schedule a BLR validate.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-07-11 06:57:28 +02:00
|
|
|
dsc relation_name;
|
2011-01-14 07:51:51 +01:00
|
|
|
DeferredWork* dw = NULL;
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_m_fields, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$RELATION_FIELDS WITH
|
2002-12-22 14:08:50 +01:00
|
|
|
X.RDB$FIELD_SOURCE EQ field_source->dsc_address
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2009-11-28 20:39:23 +01:00
|
|
|
relation_name.makeText(sizeof(X.RDB$RELATION_NAME), CS_METADATA,
|
|
|
|
(UCHAR*) X.RDB$RELATION_NAME);
|
2008-12-14 10:28:25 +01:00
|
|
|
SCL_check_relation(tdbb, &relation_name, SCL_control);
|
2006-07-11 06:57:28 +02:00
|
|
|
dw = DFW_post_work(transaction, dfw_update_format, &relation_name, 0);
|
2011-01-14 07:51:51 +01:00
|
|
|
|
|
|
|
AutoCacheRequest request2(tdbb, irq_m_fields4, IRQ_REQUESTS);
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request2)
|
|
|
|
RFL IN RDB$RELATION_FIELDS CROSS
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
PRC IN RDB$PROCEDURES
|
|
|
|
WITH RFL.RDB$FIELD_SOURCE EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_NAME EQ RFL.RDB$RELATION_NAME AND
|
|
|
|
DEP.RDB$FIELD_NAME EQ RFL.RDB$FIELD_NAME AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_relation AND
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_procedure AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ PRC.RDB$PROCEDURE_NAME AND
|
|
|
|
PRC.RDB$PACKAGE_NAME MISSING
|
|
|
|
{
|
|
|
|
MetaName proc_name(PRC.RDB$PROCEDURE_NAME);
|
|
|
|
|
|
|
|
dsc desc;
|
|
|
|
desc.makeText(proc_name.length(), CS_METADATA, (UCHAR*) proc_name.c_str());
|
|
|
|
|
|
|
|
DeferredWork* dw2 =
|
|
|
|
DFW_post_work(transaction, dfw_modify_procedure, &desc, PRC.RDB$PROCEDURE_ID);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
|
|
|
}
|
|
|
|
END_FOR
|
|
|
|
|
|
|
|
request2.reset(tdbb, irq_m_fields5, IRQ_REQUESTS);
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request2)
|
|
|
|
RFL IN RDB$RELATION_FIELDS CROSS
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
TRG IN RDB$TRIGGERS
|
|
|
|
WITH RFL.RDB$FIELD_SOURCE EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_NAME EQ RFL.RDB$RELATION_NAME AND
|
|
|
|
DEP.RDB$FIELD_NAME EQ RFL.RDB$FIELD_NAME AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_relation AND
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_trigger AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ TRG.RDB$TRIGGER_NAME
|
|
|
|
{
|
|
|
|
MetaName trigger_name(TRG.RDB$TRIGGER_NAME);
|
|
|
|
MetaName trigger_relation_name(TRG.RDB$RELATION_NAME);
|
|
|
|
|
|
|
|
dsc desc;
|
|
|
|
desc.makeText(trigger_name.length(), CS_METADATA, (UCHAR*) trigger_name.c_str());
|
|
|
|
|
|
|
|
DeferredWork* dw2 = DFW_post_work(transaction, dfw_modify_trigger, &desc, 0);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, TRG.RDB$TRIGGER_TYPE, dfw_arg_trg_type);
|
|
|
|
|
|
|
|
desc.dsc_length = trigger_relation_name.length();
|
|
|
|
desc.dsc_address = (UCHAR*) trigger_relation_name.c_str();
|
|
|
|
DFW_post_work_arg(transaction, dw2, &desc, 0, dfw_arg_check_blr);
|
|
|
|
}
|
|
|
|
END_FOR
|
|
|
|
|
|
|
|
request2.reset(tdbb, irq_m_fields8, IRQ_REQUESTS);
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request2)
|
|
|
|
RFL IN RDB$RELATION_FIELDS CROSS
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
FUN IN RDB$FUNCTIONS
|
|
|
|
WITH RFL.RDB$FIELD_SOURCE EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_NAME EQ RFL.RDB$RELATION_NAME AND
|
|
|
|
DEP.RDB$FIELD_NAME EQ RFL.RDB$FIELD_NAME AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_relation AND
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_udf AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ FUN.RDB$FUNCTION_NAME AND
|
|
|
|
FUN.RDB$PACKAGE_NAME MISSING
|
|
|
|
{
|
|
|
|
MetaName name(FUN.RDB$FUNCTION_NAME);
|
|
|
|
|
|
|
|
dsc desc;
|
|
|
|
desc.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
|
|
|
|
|
|
|
|
DeferredWork* dw2 =
|
|
|
|
DFW_post_work(transaction, dfw_modify_function, &desc, FUN.RDB$FUNCTION_ID);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
|
|
|
}
|
|
|
|
END_FOR
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2006-08-19 04:52:39 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
request.reset(tdbb, irq_m_fields2, IRQ_REQUESTS);
|
2006-08-19 04:52:39 +02:00
|
|
|
|
2009-11-27 03:33:40 +01:00
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
PRC IN RDB$PROCEDURES
|
|
|
|
WITH DEP.RDB$DEPENDED_ON_NAME EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_field AND
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_procedure AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ PRC.RDB$PROCEDURE_NAME AND
|
|
|
|
PRC.RDB$PACKAGE_NAME MISSING
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName proc_name(PRC.RDB$PROCEDURE_NAME);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2009-11-27 03:33:40 +01:00
|
|
|
dsc desc;
|
2009-11-28 20:39:23 +01:00
|
|
|
desc.makeText(proc_name.length(), CS_METADATA, (UCHAR*) proc_name.c_str());
|
2009-11-27 03:33:40 +01:00
|
|
|
|
|
|
|
DeferredWork* dw2 =
|
|
|
|
DFW_post_work(transaction, dfw_modify_procedure, &desc, PRC.RDB$PROCEDURE_ID);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2009-11-27 03:33:40 +01:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
request.reset(tdbb, irq_m_fields6, IRQ_REQUESTS);
|
2009-11-27 03:33:40 +01:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
PRC IN RDB$PROCEDURES
|
|
|
|
WITH DEP.RDB$DEPENDED_ON_NAME EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_field AND
|
|
|
|
(DEP.RDB$DEPENDENT_TYPE EQ obj_package_header OR
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_package_body) AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ PRC.RDB$PACKAGE_NAME
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName proc_name(PRC.RDB$PROCEDURE_NAME);
|
2006-08-19 04:52:39 +02:00
|
|
|
|
2009-11-27 03:33:40 +01:00
|
|
|
dsc desc;
|
2009-11-28 20:39:23 +01:00
|
|
|
desc.makeText(proc_name.length(), CS_METADATA, (UCHAR*) proc_name.c_str());
|
2009-11-27 03:33:40 +01:00
|
|
|
|
|
|
|
DeferredWork* dw2 = DFW_post_work(transaction, dfw_modify_procedure, &desc,
|
|
|
|
PRC.RDB$PROCEDURE_ID, PRC.RDB$PACKAGE_NAME);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2009-11-27 03:33:40 +01:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
request.reset(tdbb, irq_m_fields3, IRQ_REQUESTS);
|
2009-11-27 03:33:40 +01:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
TRG IN RDB$TRIGGERS
|
|
|
|
WITH DEP.RDB$DEPENDED_ON_NAME EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_field AND
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_trigger AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ TRG.RDB$TRIGGER_NAME
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName trigger_name(TRG.RDB$TRIGGER_NAME);
|
|
|
|
MetaName trigger_relation_name(TRG.RDB$RELATION_NAME);
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2009-11-27 03:33:40 +01:00
|
|
|
dsc desc;
|
2009-11-28 20:39:23 +01:00
|
|
|
desc.makeText(trigger_name.length(), CS_METADATA, (UCHAR*) trigger_name.c_str());
|
2009-11-27 03:33:40 +01:00
|
|
|
|
|
|
|
DeferredWork* dw2 = DFW_post_work(transaction, dfw_modify_trigger, &desc, 0);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, TRG.RDB$TRIGGER_TYPE, dfw_arg_trg_type);
|
|
|
|
|
|
|
|
desc.dsc_length = trigger_relation_name.length();
|
|
|
|
desc.dsc_address = (UCHAR*) trigger_relation_name.c_str();
|
|
|
|
DFW_post_work_arg(transaction, dw2, &desc, 0, dfw_arg_check_blr);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2009-11-27 03:33:40 +01:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
request.reset(tdbb, irq_m_fields7, IRQ_REQUESTS);
|
2009-12-25 14:30:38 +01:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
FUN IN RDB$FUNCTIONS
|
|
|
|
WITH DEP.RDB$DEPENDED_ON_NAME EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_field AND
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_udf AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ FUN.RDB$FUNCTION_NAME AND
|
|
|
|
FUN.RDB$PACKAGE_NAME MISSING
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName name(FUN.RDB$FUNCTION_NAME);
|
2009-12-25 14:30:38 +01:00
|
|
|
|
|
|
|
dsc desc;
|
|
|
|
desc.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
|
|
|
|
|
|
|
|
DeferredWork* dw2 =
|
|
|
|
DFW_post_work(transaction, dfw_modify_function, &desc, FUN.RDB$FUNCTION_ID);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2009-12-25 14:30:38 +01:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
request.reset(tdbb, irq_m_fields9, IRQ_REQUESTS);
|
2009-12-25 14:30:38 +01:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
DEP IN RDB$DEPENDENCIES CROSS
|
|
|
|
FUN IN RDB$FUNCTIONS
|
|
|
|
WITH DEP.RDB$DEPENDED_ON_NAME EQ field_source->dsc_address AND
|
|
|
|
DEP.RDB$DEPENDED_ON_TYPE EQ obj_field AND
|
|
|
|
(DEP.RDB$DEPENDENT_TYPE EQ obj_package_header OR
|
|
|
|
DEP.RDB$DEPENDENT_TYPE EQ obj_package_body) AND
|
|
|
|
DEP.RDB$DEPENDENT_NAME EQ FUN.RDB$PACKAGE_NAME
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName name(FUN.RDB$FUNCTION_NAME);
|
2009-12-25 14:30:38 +01:00
|
|
|
|
|
|
|
dsc desc;
|
|
|
|
desc.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
|
|
|
|
|
|
|
|
DeferredWork* dw2 = DFW_post_work(transaction, dfw_modify_function, &desc,
|
|
|
|
FUN.RDB$FUNCTION_ID, FUN.RDB$PACKAGE_NAME);
|
|
|
|
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2009-12-25 14:30:38 +01:00
|
|
|
|
2006-07-11 06:57:28 +02:00
|
|
|
return dw;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-30 06:10:52 +02:00
|
|
|
Format* MET_current(thread_db* tdbb, jrd_rel* relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ c u r r e n t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get the current format for a relation. The current format is the
|
|
|
|
* format in which new records are to be stored.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
if (relation->rel_current_format)
|
|
|
|
return relation->rel_current_format;
|
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
return relation->rel_current_format = MET_format(tdbb, relation, relation->rel_current_fmt);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_delete_dependencies(thread_db* tdbb,
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName& object_name,
|
2008-07-21 17:49:24 +02:00
|
|
|
int dependency_type,
|
|
|
|
jrd_tra* transaction)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ d e l e t e _ d e p e n d e n c i e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2005-05-28 00:45:31 +02:00
|
|
|
* Delete all dependencies for the specified
|
2001-05-23 15:26:42 +02:00
|
|
|
* object of given type.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
// if (!object_name)
|
|
|
|
// return;
|
|
|
|
//
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_d_deps, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-08-08 18:01:58 +02:00
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
2001-05-23 15:26:42 +02:00
|
|
|
DEP IN RDB$DEPENDENCIES
|
2005-05-12 20:28:04 +02:00
|
|
|
WITH DEP.RDB$DEPENDENT_NAME = object_name.c_str()
|
2001-05-23 15:26:42 +02:00
|
|
|
AND DEP.RDB$DEPENDENT_TYPE = dependency_type
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
ERASE DEP;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_delete_shadow(thread_db* tdbb, USHORT shadow_number)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ d e l e t e _ s h a d o w
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
2005-05-28 00:45:31 +02:00
|
|
|
* Functional description
|
2001-05-23 15:26:42 +02:00
|
|
|
* When any of the shadows in RDB$FILES for a particular
|
|
|
|
* shadow are deleted, stop shadowing to that file and
|
|
|
|
* remove all other files from the same shadow.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE handle)
|
2005-05-28 00:45:31 +02:00
|
|
|
X IN RDB$FILES WITH X.RDB$SHADOW_NUMBER EQ shadow_number
|
2008-12-18 11:57:12 +01:00
|
|
|
ERASE X;
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
for (Shadow* shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
|
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
if (shadow->sdw_number == shadow_number) {
|
2001-05-23 15:26:42 +02:00
|
|
|
shadow->sdw_flags |= SDW_shutdown;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2003-12-22 11:00:59 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// notify other processes to check for shadow deletion
|
2010-04-20 00:49:18 +02:00
|
|
|
if (SDW_lck_update(tdbb, 0))
|
2008-12-14 10:28:25 +01:00
|
|
|
SDW_notify(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-09 23:15:18 +01:00
|
|
|
bool MET_dsql_cache_use(thread_db* tdbb, int type, const MetaName& name, const MetaName& package)
|
2008-03-01 20:14:46 +01:00
|
|
|
{
|
2010-01-09 23:15:18 +01:00
|
|
|
DSqlCacheItem* item = get_dsql_cache_item(tdbb, type, QualifiedName(name, package));
|
2008-03-01 20:14:46 +01:00
|
|
|
|
2008-03-02 08:35:37 +01:00
|
|
|
const bool obsolete = item->obsolete;
|
2008-03-01 20:14:46 +01:00
|
|
|
|
|
|
|
if (!item->locked)
|
|
|
|
{
|
|
|
|
// lock to be notified by others when we should mark as obsolete
|
|
|
|
LCK_lock(tdbb, item->lock, LCK_SR, LCK_WAIT);
|
|
|
|
item->locked = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->obsolete = false;
|
|
|
|
|
|
|
|
return obsolete;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-09 23:15:18 +01:00
|
|
|
void MET_dsql_cache_release(thread_db* tdbb, int type, const MetaName& name, const MetaName& package)
|
2008-03-01 20:14:46 +01:00
|
|
|
{
|
2010-01-09 23:15:18 +01:00
|
|
|
DSqlCacheItem* item = get_dsql_cache_item(tdbb, type, QualifiedName(name, package));
|
2008-03-01 20:14:46 +01:00
|
|
|
|
|
|
|
// release lock
|
|
|
|
LCK_release(tdbb, item->lock);
|
|
|
|
|
2008-06-27 14:11:09 +02:00
|
|
|
// notify others through AST to mark as obsolete
|
2012-06-21 17:37:38 +02:00
|
|
|
const USHORT key_length = item->lock->lck_length;
|
|
|
|
AutoPtr<Lock> temp_lock(FB_NEW_RPT(*tdbb->getDefaultPool(), key_length)
|
|
|
|
Lock(tdbb, key_length, LCK_dsql_cache));
|
2008-06-27 14:11:09 +02:00
|
|
|
memcpy(temp_lock->lck_key.lck_string, item->lock->lck_key.lck_string, key_length);
|
|
|
|
|
|
|
|
if (LCK_lock(tdbb, temp_lock, LCK_EX, LCK_WAIT))
|
|
|
|
LCK_release(tdbb, temp_lock);
|
|
|
|
|
|
|
|
item->locked = false;
|
2008-03-01 20:14:46 +01:00
|
|
|
item->obsolete = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-22 11:00:59 +01:00
|
|
|
void MET_error(const TEXT* string, ...)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ e r r o r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Post an error in a metadata update
|
|
|
|
* Oh, wow.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TEXT s[128];
|
|
|
|
va_list ptr;
|
|
|
|
|
2004-05-24 01:28:06 +02:00
|
|
|
va_start(ptr, string);
|
2004-09-25 12:28:09 +02:00
|
|
|
VSNPRINTF(s, sizeof(s), string, ptr);
|
|
|
|
va_end(ptr);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-08-27 14:20:47 +02:00
|
|
|
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
|
|
|
Arg::Gds(isc_random) << Arg::Str(s));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-03-30 06:10:52 +02:00
|
|
|
Format* MET_format(thread_db* tdbb, jrd_rel* relation, USHORT number)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ f o r m a t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup a format for given relation.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-30 06:10:52 +02:00
|
|
|
Format* format;
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<Format*>* formats = relation->rel_formats;
|
2008-12-18 11:57:12 +01:00
|
|
|
if (formats && (number < formats->count()) && (format = (*formats)[number]))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
format = NULL;
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_r_format, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$FORMATS WITH X.RDB$RELATION_ID EQ relation->rel_id AND
|
2005-05-28 00:45:31 +02:00
|
|
|
X.RDB$FORMAT EQ number
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::open(tdbb, attachment->getSysTransaction(), &X.RDB$DESCRIPTOR);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
// Use generic representation of formats with 32-bit offsets
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
HalfStaticArray<UCHAR, BUFFER_MEDIUM> buffer;
|
2012-02-07 04:17:52 +01:00
|
|
|
blob->BLB_get_data(tdbb, buffer.getBuffer(blob->blb_length), blob->blb_length);
|
2009-11-27 03:33:40 +01:00
|
|
|
unsigned bufferPos = 2;
|
|
|
|
USHORT count = buffer[0] | (buffer[1] << 8);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
format = Format::newFormat(*relation->rel_pool, count);
|
2009-11-18 15:24:47 +01:00
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
Array<Ods::Descriptor> odsDescs;
|
2009-11-24 12:42:56 +01:00
|
|
|
Ods::Descriptor* odsDesc = odsDescs.getBuffer(count);
|
|
|
|
memcpy(odsDesc, buffer.begin() + bufferPos, count * sizeof(Ods::Descriptor));
|
2009-11-18 15:24:47 +01:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
for (Format::fmt_desc_iterator desc = format->fmt_desc.begin();
|
|
|
|
desc < format->fmt_desc.end(); ++desc, ++odsDesc)
|
|
|
|
{
|
|
|
|
*desc = *odsDesc;
|
|
|
|
if (odsDesc->dsc_offset)
|
|
|
|
format->fmt_length = odsDesc->dsc_offset + desc->dsc_length;
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-27 03:33:40 +01:00
|
|
|
const UCHAR* p = buffer.begin() + bufferPos + count * sizeof(Ods::Descriptor);
|
|
|
|
count = p[0] | (p[1] << 8);
|
|
|
|
p += 2;
|
|
|
|
|
|
|
|
while (count-- > 0)
|
2009-11-24 12:42:56 +01:00
|
|
|
{
|
2009-11-27 03:33:40 +01:00
|
|
|
USHORT offset = p[0] | (p[1] << 8);
|
2009-11-24 12:42:56 +01:00
|
|
|
p += 2;
|
2009-11-18 15:24:47 +01:00
|
|
|
|
2009-11-27 03:33:40 +01:00
|
|
|
const Ods::Descriptor* odsDflDesc = (Ods::Descriptor*) p;
|
|
|
|
p = (UCHAR*) (odsDflDesc + 1);
|
2009-11-18 15:24:47 +01:00
|
|
|
|
2011-02-03 10:35:57 +01:00
|
|
|
dsc desc = *odsDflDesc;
|
|
|
|
desc.dsc_address = const_cast<UCHAR*>(p);
|
2011-02-11 01:43:15 +01:00
|
|
|
EVL_make_value(tdbb, &desc, &format->fmt_defaults[offset], dbb->dbb_permanent);
|
2009-11-18 15:24:47 +01:00
|
|
|
|
2009-11-27 03:33:40 +01:00
|
|
|
p += desc.dsc_length;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-26 01:20:59 +01:00
|
|
|
if (!format)
|
2011-05-09 12:15:19 +02:00
|
|
|
format = Format::newFormat(*relation->rel_pool);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
format->fmt_version = number;
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Link the format block into the world
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-02-19 16:25:27 +01:00
|
|
|
formats = relation->rel_formats =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<Format*>::newVector(*relation->rel_pool, relation->rel_formats, number + 1);
|
2005-12-02 08:35:34 +01:00
|
|
|
(*formats)[number] = format;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
bool MET_get_char_coll_subtype(thread_db* tdbb, USHORT* id, const UCHAR* name, USHORT length)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2005-05-28 00:45:31 +02:00
|
|
|
* M E T _ g e t _ c h a r _ c o l l _ s u b t y p e
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Character types can be specified as either:
|
|
|
|
* a) A POSIX style locale name "<collation>.<characterset>"
|
|
|
|
* or
|
|
|
|
* b) A simple <characterset> name (using default collation)
|
|
|
|
* c) A simple <collation> name (use charset for collation)
|
|
|
|
*
|
|
|
|
* Given an ASCII7 string which could be any of the above, try to
|
|
|
|
* resolve the name in the order a, b, c
|
|
|
|
* a) is only tried iff the name contains a period.
|
|
|
|
* (in which case b) and c) are not tried).
|
|
|
|
*
|
|
|
|
* Return:
|
|
|
|
* 1 if no errors (and *id is set).
|
|
|
|
* 0 if the name could not be resolved.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(id != NULL);
|
|
|
|
fb_assert(name != NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-22 11:00:59 +01:00
|
|
|
const UCHAR* const end_name = name + length;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Force key to uppercase, following C locale rules for uppercasing
|
|
|
|
// At the same time, search for the first period in the string (if any)
|
2009-11-19 10:52:30 +01:00
|
|
|
UCHAR buffer[MAX_SQL_IDENTIFIER_SIZE]; // BASED ON RDB$COLLATION_NAME
|
2003-12-22 11:00:59 +01:00
|
|
|
UCHAR* p = buffer;
|
|
|
|
UCHAR* period = NULL;
|
2009-11-07 12:58:54 +01:00
|
|
|
for (; name < end_name && p < buffer + sizeof(buffer) - 1; p++, name++)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
*p = UPPER7(*name);
|
2004-01-03 11:59:52 +01:00
|
|
|
if ((*p == '.') && !period) {
|
2001-05-23 15:26:42 +02:00
|
|
|
period = p;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
*p = 0;
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Is there a period, separating collation name from character set?
|
2009-11-07 12:58:54 +01:00
|
|
|
if (period)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
*period = 0;
|
|
|
|
return resolve_charset_and_collation(tdbb, id, period + 1, buffer);
|
|
|
|
}
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Is it a character set name (implying charset default collation sequence)
|
2008-01-16 10:29:37 +01:00
|
|
|
|
|
|
|
bool res = resolve_charset_and_collation(tdbb, id, buffer, NULL);
|
2009-11-07 12:58:54 +01:00
|
|
|
if (!res)
|
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// Is it a collation name (implying implementation-default character set)
|
2008-01-16 10:29:37 +01:00
|
|
|
res = resolve_charset_and_collation(tdbb, id, NULL, buffer);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
return res;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-05 18:34:18 +02:00
|
|
|
bool MET_get_char_coll_subtype_info(thread_db* tdbb, USHORT id, SubtypeInfo* info)
|
2005-05-28 00:45:31 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ g e t _ c h a r _ c o l l _ s u b t y p e _ i n f o
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get charset and collation informations
|
|
|
|
* for a subtype ID.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
fb_assert(info != NULL);
|
|
|
|
|
2005-06-06 10:30:03 +02:00
|
|
|
const USHORT charset_id = id & 0x00FF;
|
|
|
|
const USHORT collation_id = id >> 8;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_subtype, IRQ_REQUESTS);
|
2005-05-28 00:45:31 +02:00
|
|
|
bool found = false;
|
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
FOR(REQUEST_HANDLE request) FIRST 1
|
|
|
|
CL IN RDB$COLLATIONS CROSS
|
|
|
|
CS IN RDB$CHARACTER_SETS
|
|
|
|
WITH CL.RDB$CHARACTER_SET_ID EQ charset_id AND
|
|
|
|
CL.RDB$COLLATION_ID EQ collation_id AND
|
|
|
|
CS.RDB$CHARACTER_SET_ID EQ CL.RDB$CHARACTER_SET_ID
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2009-11-24 12:42:56 +01:00
|
|
|
found = true;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
info->charsetName = CS.RDB$CHARACTER_SET_NAME;
|
|
|
|
info->collationName = CL.RDB$COLLATION_NAME;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
if (CL.RDB$BASE_COLLATION_NAME.NULL)
|
|
|
|
info->baseCollationName = info->collationName;
|
|
|
|
else
|
|
|
|
info->baseCollationName = CL.RDB$BASE_COLLATION_NAME;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
if (CL.RDB$SPECIFIC_ATTRIBUTES.NULL)
|
|
|
|
info->specificAttributes.clear();
|
|
|
|
else
|
|
|
|
{
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::open(tdbb, attachment->getSysTransaction(), &CL.RDB$SPECIFIC_ATTRIBUTES);
|
2013-01-25 13:34:19 +01:00
|
|
|
const ULONG length = blob->blb_length;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
// ASF: Here info->specificAttributes is in UNICODE_FSS charset.
|
|
|
|
// It will be converted to the collation charset in intl.cpp
|
2012-02-07 04:17:52 +01:00
|
|
|
blob->BLB_get_data(tdbb, info->specificAttributes.getBuffer(length), length);
|
2009-11-24 12:42:56 +01:00
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-24 12:42:56 +01:00
|
|
|
info->attributes = (USHORT)CL.RDB$COLLATION_ATTRIBUTES;
|
|
|
|
info->ignoreAttributes = CL.RDB$COLLATION_ATTRIBUTES.NULL;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2005-05-28 00:45:31 +02:00
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
DmlNode* MET_get_dependencies(thread_db* tdbb,
|
2008-06-26 12:48:28 +02:00
|
|
|
jrd_rel* relation,
|
|
|
|
const UCHAR* blob,
|
2009-08-02 06:10:07 +02:00
|
|
|
const ULONG blob_length,
|
2008-06-26 12:48:28 +02:00
|
|
|
CompilerScratch* view_csb,
|
|
|
|
bid* blob_id,
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement** statementPtr,
|
2008-06-26 12:48:28 +02:00
|
|
|
CompilerScratch** csb_ptr,
|
2010-01-26 09:29:03 +01:00
|
|
|
const MetaName& object_name,
|
2008-06-26 12:48:28 +02:00
|
|
|
int type,
|
|
|
|
USHORT flags,
|
2008-07-21 17:49:24 +02:00
|
|
|
jrd_tra* transaction,
|
2010-01-26 09:29:03 +01:00
|
|
|
const MetaName& domain_validation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ g e t _ d e p e n d e n c i e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2005-05-28 00:45:31 +02:00
|
|
|
* Get dependencies for an object by parsing
|
2001-05-23 15:26:42 +02:00
|
|
|
* the blr used in its definition.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-01-26 09:29:03 +01:00
|
|
|
fb_assert(domain_validation.isEmpty() || object_name == domain_validation); // for now
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5, domain_validation);
|
2005-03-28 23:52:55 +02:00
|
|
|
csb->csb_g_flags |= (csb_get_dependencies | flags);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
DmlNode* node;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (blob)
|
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
node = PAR_blr(tdbb, relation, blob, blob_length, view_csb, &csb, statementPtr,
|
|
|
|
(type == obj_trigger && relation != NULL), 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
node = MET_parse_blob(tdbb, relation, blob_id, &csb, statementPtr,
|
2010-10-12 13:36:51 +02:00
|
|
|
(type == obj_trigger && relation != NULL), type == obj_validation);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2006-08-30 06:54:44 +02:00
|
|
|
if (type == obj_computed)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-01-26 09:29:03 +01:00
|
|
|
MetaName domainName;
|
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle;
|
2010-04-23 03:59:21 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
RLF IN RDB$RELATION_FIELDS CROSS
|
|
|
|
FLD IN RDB$FIELDS WITH
|
|
|
|
RLF.RDB$FIELD_SOURCE EQ FLD.RDB$FIELD_NAME AND
|
2005-05-12 20:28:04 +02:00
|
|
|
RLF.RDB$RELATION_NAME EQ relation->rel_name.c_str() AND
|
|
|
|
RLF.RDB$FIELD_NAME EQ object_name.c_str()
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2010-01-26 09:29:03 +01:00
|
|
|
domainName = FLD.RDB$FIELD_NAME;
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-01-26 09:29:03 +01:00
|
|
|
MET_delete_dependencies(tdbb, domainName, type, transaction);
|
|
|
|
store_dependencies(tdbb, csb, relation, domainName, type, transaction);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MET_delete_dependencies(tdbb, object_name, type, transaction);
|
|
|
|
store_dependencies(tdbb, csb, relation, object_name, type, transaction);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (csb_ptr)
|
2004-03-11 06:04:26 +01:00
|
|
|
*csb_ptr = csb;
|
2001-05-23 15:26:42 +02:00
|
|
|
else
|
2004-03-11 06:04:26 +01:00
|
|
|
delete csb;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_fld* MET_get_field(jrd_rel* relation, USHORT id)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ g e t _ f i e l d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get the field block for a field if possible. If not,
|
|
|
|
* return NULL;
|
|
|
|
*
|
|
|
|
**************************************/
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_fld*>* vector;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
if (!relation || !(vector = relation->rel_fields) || id >= vector->count())
|
2003-12-22 11:00:59 +01:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
return (*vector)[id];
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_get_shadow_files(thread_db* tdbb, bool delete_files)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ g e t _ s h a d o w _ f i l e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Check the shadows found in the database against
|
2005-05-28 00:45:31 +02:00
|
|
|
* our in-memory list: if any new shadow files have
|
2001-05-23 15:26:42 +02:00
|
|
|
* been defined since the last time we looked, start
|
|
|
|
* shadowing to them; if any have been deleted, stop
|
|
|
|
* shadowing to them.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle;
|
2010-04-23 03:59:21 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE handle) X IN RDB$FILES
|
|
|
|
WITH X.RDB$SHADOW_NUMBER NOT MISSING
|
|
|
|
AND X.RDB$SHADOW_NUMBER NE 0
|
|
|
|
AND X.RDB$FILE_SEQUENCE EQ 0
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
if ((X.RDB$FILE_FLAGS & FILE_shadow) && !(X.RDB$FILE_FLAGS & FILE_inactive))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-12-22 11:00:59 +01:00
|
|
|
const USHORT file_flags = X.RDB$FILE_FLAGS;
|
2008-12-14 10:28:25 +01:00
|
|
|
SDW_start(tdbb, X.RDB$FILE_NAME, X.RDB$SHADOW_NUMBER, file_flags, delete_files);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// if the shadow exists, mark the appropriate shadow
|
|
|
|
// block as found for the purposes of this routine;
|
|
|
|
// if the shadow was conditional and is no longer, note it
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
for (Shadow* shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
if ((shadow->sdw_number == X.RDB$SHADOW_NUMBER) && !(shadow->sdw_flags & SDW_IGNORE))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
shadow->sdw_flags |= SDW_found;
|
2004-01-03 11:59:52 +01:00
|
|
|
if (!(file_flags & FILE_conditional)) {
|
2001-05-23 15:26:42 +02:00
|
|
|
shadow->sdw_flags &= ~SDW_conditional;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// if any current shadows were not defined in database, mark
|
|
|
|
// them to be shutdown since they don't exist anymore
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
for (Shadow* shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
|
|
|
|
{
|
2010-04-20 00:49:18 +02:00
|
|
|
if (!(shadow->sdw_flags & SDW_found))
|
2001-05-23 15:26:42 +02:00
|
|
|
shadow->sdw_flags |= SDW_shutdown;
|
2010-04-20 00:49:18 +02:00
|
|
|
else
|
2001-05-23 15:26:42 +02:00
|
|
|
shadow->sdw_flags &= ~SDW_found;
|
2003-12-22 11:00:59 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-14 10:28:25 +01:00
|
|
|
SDW_check(tdbb);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
void MET_load_db_triggers(thread_db* tdbb, int type)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2006-11-06 02:07:31 +01:00
|
|
|
* M E T _ l o a d _ d b _ t r i g g e r s
|
2006-11-05 19:30:36 +01:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Load database triggers from RDB$TRIGGERS.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2006-11-05 19:30:36 +01:00
|
|
|
CHECK_DBB(dbb);
|
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
if ((attachment->att_flags & ATT_no_db_triggers) ||
|
|
|
|
attachment->att_triggers[type] != NULL)
|
2006-11-05 19:30:36 +01:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->att_triggers[type] = FB_NEW(*attachment->att_pool)
|
|
|
|
trig_vec(*attachment->att_pool);
|
2006-11-05 19:30:36 +01:00
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest trigger_request;
|
2006-11-05 19:30:36 +01:00
|
|
|
int encoded_type = type | TRIGGER_TYPE_DB;
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE trigger_request)
|
|
|
|
TRG IN RDB$TRIGGERS
|
2008-12-14 10:28:25 +01:00
|
|
|
WITH TRG.RDB$RELATION_NAME MISSING AND
|
2006-11-05 19:30:36 +01:00
|
|
|
TRG.RDB$TRIGGER_TYPE EQ encoded_type AND
|
|
|
|
TRG.RDB$TRIGGER_INACTIVE EQ 0
|
|
|
|
SORTED BY TRG.RDB$TRIGGER_SEQUENCE
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2011-05-09 12:15:19 +02:00
|
|
|
MET_load_trigger(tdbb, NULL, TRG.RDB$TRIGGER_NAME, &attachment->att_triggers[type]);
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2006-11-05 19:30:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
// Load DDL triggers from RDB$TRIGGERS.
|
|
|
|
void MET_load_ddl_triggers(thread_db* tdbb)
|
|
|
|
{
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2009-10-21 02:42:38 +02:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
|
|
|
CHECK_DBB(dbb);
|
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
if ((attachment->att_flags & ATT_no_db_triggers) ||
|
|
|
|
attachment->att_ddl_triggers != NULL)
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->att_ddl_triggers = FB_NEW(*tdbb->getDatabase()->dbb_permanent)
|
2009-10-21 02:42:38 +02:00
|
|
|
trig_vec(*tdbb->getDatabase()->dbb_permanent);
|
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest trigger_request;
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE trigger_request)
|
|
|
|
TRG IN RDB$TRIGGERS
|
|
|
|
WITH TRG.RDB$RELATION_NAME MISSING AND
|
|
|
|
TRG.RDB$TRIGGER_INACTIVE EQ 0
|
|
|
|
SORTED BY TRG.RDB$TRIGGER_SEQUENCE
|
|
|
|
{
|
|
|
|
if ((TRG.RDB$TRIGGER_TYPE & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DDL)
|
|
|
|
{
|
|
|
|
MET_load_trigger(tdbb, NULL, TRG.RDB$TRIGGER_NAME,
|
2011-05-09 12:15:19 +02:00
|
|
|
&attachment->att_ddl_triggers);
|
2009-10-21 02:42:38 +02:00
|
|
|
}
|
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2009-10-21 02:42:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
void MET_load_trigger(thread_db* tdbb,
|
2005-05-28 00:45:31 +02:00
|
|
|
jrd_rel* relation,
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName& trigger_name,
|
2004-02-20 07:43:27 +01:00
|
|
|
trig_vec** triggers)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o a d _ t r i g g e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Load triggers from RDB$TRIGGERS. If a requested,
|
|
|
|
* also load triggers from RDB$RELATIONS.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
TEXT errmsg[MAX_ERRMSG_LEN + 1];
|
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
CHECK_DBB(dbb);
|
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
if (relation)
|
|
|
|
{
|
|
|
|
if (relation->rel_flags & REL_sys_trigs_being_loaded)
|
|
|
|
return;
|
2005-10-13 10:11:37 +02:00
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
// No need to load table triggers for ReadOnly databases,
|
|
|
|
// since INSERT/DELETE/UPDATE statements are not going to be allowed
|
2011-03-19 14:10:51 +01:00
|
|
|
// hvlad: GTT with ON COMMIT DELETE ROWS clause is writable
|
|
|
|
|
2012-04-12 11:02:13 +02:00
|
|
|
if (dbb->readOnly() && !(relation->rel_flags & REL_temp_tran))
|
2006-11-05 19:30:36 +01:00
|
|
|
return;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-10-13 10:11:37 +02:00
|
|
|
// Scan RDB$TRIGGERS next
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_s_triggers, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
FOR(REQUEST_HANDLE request)
|
2006-11-05 19:30:36 +01:00
|
|
|
TRG IN RDB$TRIGGERS
|
2011-03-31 00:51:35 +02:00
|
|
|
WITH TRG.RDB$TRIGGER_NAME EQ trigger_name.c_str() AND
|
2011-04-01 21:39:49 +02:00
|
|
|
(TRG.RDB$TRIGGER_INACTIVE MISSING OR TRG.RDB$TRIGGER_INACTIVE EQ 0)
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// check if the trigger is to be fired without any permissions
|
|
|
|
// checks. Verify such a claim
|
2006-11-05 19:30:36 +01:00
|
|
|
USHORT trig_flags = (USHORT) TRG.RDB$FLAGS;
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// if there is an ignore permission flag, see if it is legit
|
2008-12-18 11:57:12 +01:00
|
|
|
if ((TRG.RDB$FLAGS & TRG_ignore_perm) && !verify_TRG_ignore_perm(tdbb, trigger_name))
|
2002-06-14 14:09:37 +02:00
|
|
|
{
|
2007-03-28 06:20:36 +02:00
|
|
|
fb_msg_format(NULL, JRD_BUGCHK, 304, sizeof(errmsg),
|
|
|
|
errmsg, MsgFormat::SafeArg() << trigger_name.c_str());
|
2006-11-05 19:30:36 +01:00
|
|
|
ERR_log(JRD_BUGCHK, 304, errmsg);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
trig_flags &= ~TRG_ignore_perm;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
bid debug_blob_id;
|
|
|
|
debug_blob_id.clear();
|
|
|
|
|
|
|
|
bid extBodyId;
|
|
|
|
extBodyId.clear();
|
|
|
|
|
|
|
|
if (!TRG.RDB$DEBUG_INFO.NULL) // ODS_11_1
|
|
|
|
debug_blob_id = TRG.RDB$DEBUG_INFO;
|
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName engine;
|
|
|
|
string entryPoint;
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
if (!TRG.RDB$ENGINE_NAME.NULL) // ODS_12_0
|
|
|
|
{
|
|
|
|
engine = TRG.RDB$ENGINE_NAME;
|
|
|
|
extBodyId = TRG.RDB$TRIGGER_SOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TRG.RDB$ENTRYPOINT.NULL) // ODS_12_0
|
|
|
|
entryPoint = TRG.RDB$ENTRYPOINT;
|
|
|
|
|
2006-11-05 19:30:36 +01:00
|
|
|
if (TRG.RDB$RELATION_NAME.NULL)
|
|
|
|
{
|
2009-10-21 02:42:38 +02:00
|
|
|
if ((TRG.RDB$TRIGGER_TYPE & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DB ||
|
|
|
|
(TRG.RDB$TRIGGER_TYPE & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DDL)
|
2006-11-05 19:30:36 +01:00
|
|
|
{
|
|
|
|
// this is a database trigger
|
|
|
|
get_trigger(tdbb,
|
|
|
|
relation,
|
|
|
|
&TRG.RDB$TRIGGER_BLR,
|
|
|
|
&debug_blob_id,
|
|
|
|
triggers,
|
|
|
|
TRG.RDB$TRIGGER_NAME,
|
2009-10-21 02:42:38 +02:00
|
|
|
TRG.RDB$TRIGGER_TYPE & ~TRIGGER_TYPE_MASK,
|
2006-11-05 19:30:36 +01:00
|
|
|
(bool) TRG.RDB$SYSTEM_FLAG,
|
2009-10-21 02:42:38 +02:00
|
|
|
trig_flags,
|
|
|
|
engine,
|
|
|
|
entryPoint,
|
|
|
|
&extBodyId);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2006-11-05 19:30:36 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-06-14 14:09:37 +02:00
|
|
|
// dimitr: support for the universal triggers
|
|
|
|
int trigger_action, slot_index = 0;
|
|
|
|
while ((trigger_action = TRIGGER_ACTION_SLOT(TRG.RDB$TRIGGER_TYPE, ++slot_index)) > 0)
|
|
|
|
{
|
|
|
|
get_trigger(tdbb,
|
|
|
|
relation,
|
2004-01-21 08:18:30 +01:00
|
|
|
&TRG.RDB$TRIGGER_BLR,
|
2006-10-30 21:58:06 +01:00
|
|
|
&debug_blob_id,
|
2002-06-14 14:09:37 +02:00
|
|
|
triggers + trigger_action,
|
|
|
|
TRG.RDB$TRIGGER_NAME,
|
2005-03-28 23:52:55 +02:00
|
|
|
(UCHAR) trigger_action,
|
2003-12-03 09:19:24 +01:00
|
|
|
(bool) TRG.RDB$SYSTEM_FLAG,
|
2009-10-21 02:42:38 +02:00
|
|
|
trig_flags,
|
|
|
|
engine,
|
|
|
|
entryPoint,
|
|
|
|
&extBodyId);
|
2002-06-14 14:09:37 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
void MET_lookup_cnstrt_for_index(thread_db* tdbb,
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName& constraint_name,
|
|
|
|
const MetaName& index_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ c n s t r t _ f o r _ i n d e x
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup constraint name from index name, if one exists.
|
|
|
|
* Calling routine must pass a buffer of at least 32 bytes.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
constraint_name = "";
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_cnstrt, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
2005-05-12 20:28:04 +02:00
|
|
|
X IN RDB$RELATION_CONSTRAINTS WITH X.RDB$INDEX_NAME EQ index_name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
constraint_name = X.RDB$CONSTRAINT_NAME;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_lookup_cnstrt_for_trigger(thread_db* tdbb,
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName& constraint_name,
|
|
|
|
MetaName& relation_name,
|
|
|
|
const MetaName& trigger_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2005-05-28 00:45:31 +02:00
|
|
|
* M E T _ l o o k u p _ c n s t r t _ f o r _ t r i g g e r
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup constraint name from trigger name, if one exists.
|
|
|
|
* Calling routine must pass a buffer of at least 32 bytes.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
constraint_name = "";
|
|
|
|
relation_name = "";
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_check, IRQ_REQUESTS);
|
|
|
|
AutoCacheRequest request2(tdbb, irq_l_check2, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// utilize two requests rather than one so that we
|
|
|
|
// guarantee we always return the name of the relation
|
|
|
|
// that the trigger is defined on, even if we don't
|
|
|
|
// have a check constraint defined for that trigger
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
Y IN RDB$TRIGGERS WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
Y.RDB$TRIGGER_NAME EQ trigger_name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE request2)
|
|
|
|
X IN RDB$CHECK_CONSTRAINTS WITH
|
|
|
|
X.RDB$TRIGGER_NAME EQ Y.RDB$TRIGGER_NAME
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
constraint_name = X.RDB$CONSTRAINT_NAME;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
relation_name = Y.RDB$RELATION_NAME;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_lookup_exception(thread_db* tdbb,
|
|
|
|
SLONG number,
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName& name,
|
2009-12-05 15:21:52 +01:00
|
|
|
string* message)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ e x c e p t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup exception by number and return its name and message.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// We need to look up exception in RDB$EXCEPTIONS
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_exception, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
name = "";
|
2009-12-05 15:21:52 +01:00
|
|
|
if (message)
|
|
|
|
*message = "";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$EXCEPTIONS WITH X.RDB$EXCEPTION_NUMBER = number
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!X.RDB$EXCEPTION_NAME.NULL)
|
2005-05-12 20:28:04 +02:00
|
|
|
name = X.RDB$EXCEPTION_NAME;
|
2009-12-05 15:21:52 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (!X.RDB$MESSAGE.NULL && message)
|
2009-12-05 15:21:52 +01:00
|
|
|
*message = X.RDB$MESSAGE;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-07 14:59:03 +01:00
|
|
|
bool MET_load_exception(thread_db* tdbb, ExceptionItem& item)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2013-03-07 14:59:03 +01:00
|
|
|
* M E T _ l o a d _ e x c e p t i o n
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2013-03-07 14:59:03 +01:00
|
|
|
* Lookup exception by name and fill the passed instance.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// We need to look up exception in RDB$EXCEPTIONS
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_except_no, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
2013-03-07 14:59:03 +01:00
|
|
|
X IN RDB$EXCEPTIONS WITH X.RDB$EXCEPTION_NAME = item.name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2013-03-07 14:59:03 +01:00
|
|
|
item.type = ExceptionItem::XCP_CODE;
|
|
|
|
item.code = X.RDB$EXCEPTION_NUMBER;
|
|
|
|
item.secName = X.RDB$SECURITY_CLASS;
|
|
|
|
|
|
|
|
return true;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-03-07 14:59:03 +01:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-15 03:55:57 +02:00
|
|
|
int MET_lookup_field(thread_db* tdbb, jrd_rel* relation, const MetaName& name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ f i e l d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Look up a field name.
|
|
|
|
*
|
2003-02-20 01:10:25 +01:00
|
|
|
* if the field is not found return -1
|
|
|
|
*
|
|
|
|
*****************************************/
|
2001-05-23 15:26:42 +02:00
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Start by checking field names that we already know
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_fld*>* vector = relation->rel_fields;
|
2004-03-31 19:59:58 +02:00
|
|
|
|
|
|
|
if (vector)
|
2004-03-25 20:27:18 +01:00
|
|
|
{
|
2006-06-06 19:00:55 +02:00
|
|
|
int id = 0;
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_fld*>::iterator fieldIter = vector->begin();
|
2004-03-25 20:27:18 +01:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
for (const vec<jrd_fld*>::const_iterator end = vector->end(); fieldIter < end;
|
|
|
|
++fieldIter, ++id)
|
2003-12-22 11:00:59 +01:00
|
|
|
{
|
2005-05-28 00:45:31 +02:00
|
|
|
if (*fieldIter)
|
2004-03-31 19:59:58 +02:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
jrd_fld* field = *fieldIter;
|
2005-05-12 20:28:04 +02:00
|
|
|
if (field->fld_name == name)
|
2004-03-25 20:27:18 +01:00
|
|
|
{
|
2010-10-14 07:27:08 +02:00
|
|
|
return id;
|
2004-03-25 20:27:18 +01:00
|
|
|
}
|
2004-03-31 19:59:58 +02:00
|
|
|
}
|
2004-03-25 20:27:18 +01:00
|
|
|
}
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Not found. Next, try system relations directly
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2006-06-06 19:00:55 +02:00
|
|
|
int id = -1;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
if (relation->rel_flags & REL_deleted)
|
2005-05-16 11:13:18 +02:00
|
|
|
{
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_field, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$RELATION_FIELDS WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
X.RDB$RELATION_NAME EQ relation->rel_name.c_str() AND
|
2005-09-14 14:02:13 +02:00
|
|
|
X.RDB$FIELD_ID NOT MISSING AND
|
2005-05-28 00:45:31 +02:00
|
|
|
X.RDB$FIELD_NAME EQ name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-10-14 07:27:08 +02:00
|
|
|
id = X.RDB$FIELD_ID;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-19 07:14:53 +01:00
|
|
|
BlobFilter* MET_lookup_filter(thread_db* tdbb, SSHORT from, SSHORT to)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ f i l t e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-22 11:00:59 +01:00
|
|
|
FPTR_BFILTER_CALLBACK filter = NULL;
|
2004-03-19 07:14:53 +01:00
|
|
|
BlobFilter* blf = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_r_filters, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$FILTERS WITH X.RDB$INPUT_SUB_TYPE EQ from AND
|
2008-12-18 11:57:12 +01:00
|
|
|
X.RDB$OUTPUT_SUB_TYPE EQ to
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2003-12-11 11:33:30 +01:00
|
|
|
filter = (FPTR_BFILTER_CALLBACK)
|
2008-01-29 11:11:52 +01:00
|
|
|
Module::lookup(X.RDB$MODULE_NAME, X.RDB$ENTRYPOINT, dbb->dbb_modules);
|
2001-05-23 15:26:42 +02:00
|
|
|
if (filter)
|
|
|
|
{
|
2004-03-20 15:57:40 +01:00
|
|
|
blf = FB_NEW(*dbb->dbb_permanent) BlobFilter(*dbb->dbb_permanent);
|
2004-03-19 07:14:53 +01:00
|
|
|
blf->blf_next = NULL;
|
|
|
|
blf->blf_from = from;
|
|
|
|
blf->blf_to = to;
|
|
|
|
blf->blf_filter = filter;
|
2004-03-20 15:57:40 +01:00
|
|
|
blf->blf_exception_message.printf(EXCEPTION_MESSAGE,
|
2001-05-23 15:26:42 +02:00
|
|
|
X.RDB$FUNCTION_NAME, X.RDB$ENTRYPOINT, X.RDB$MODULE_NAME);
|
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-19 07:14:53 +01:00
|
|
|
return blf;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-07 14:59:03 +01:00
|
|
|
bool MET_load_generator(thread_db* tdbb, GeneratorItem& item)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o a d _ g e n e r a t o r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup generator ID by its name and load its metadata into the passed object.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
|
|
|
|
|
|
|
if (item.name == "RDB$GENERATORS")
|
|
|
|
{
|
|
|
|
item.id = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
AutoCacheRequest request(tdbb, irq_r_gen_id, IRQ_REQUESTS);
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$GENERATORS WITH X.RDB$GENERATOR_NAME EQ item.name.c_str()
|
|
|
|
{
|
|
|
|
item.id = X.RDB$GENERATOR_ID;
|
|
|
|
item.secName = X.RDB$SECURITY_CLASS;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
END_FOR
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SLONG MET_lookup_generator(thread_db* tdbb, const MetaName& name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ g e n e r a t o r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2011-02-17 07:05:16 +01:00
|
|
|
* Lookup generator ID by its name.
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-02-17 07:05:16 +01:00
|
|
|
if (name == "RDB$GENERATORS")
|
2001-05-23 15:26:42 +02:00
|
|
|
return 0;
|
|
|
|
|
2013-03-07 14:59:03 +01:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_gen_id, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
2011-02-17 07:05:16 +01:00
|
|
|
X IN RDB$GENERATORS WITH X.RDB$GENERATOR_NAME EQ name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2013-03-07 14:59:03 +01:00
|
|
|
return X.RDB$GENERATOR_ID;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2013-03-07 14:59:03 +01:00
|
|
|
return -1;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2013-03-07 14:59:03 +01:00
|
|
|
void MET_lookup_generator_id(thread_db* tdbb, SLONG gen_id, MetaName& name)
|
2002-07-01 18:59:09 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ g e n e r a t o r _ i d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup generator (aka gen_id) by ID. It will load
|
|
|
|
* the name in the third parameter.
|
|
|
|
*
|
|
|
|
**************************************/
|
2008-12-18 11:57:12 +01:00
|
|
|
SET_TDBB (tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (!gen_id)
|
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
name = "RDB$GENERATORS";
|
|
|
|
return;
|
|
|
|
}
|
2002-07-01 18:59:09 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
name = "";
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request (tdbb, irq_r_gen_id_num, IRQ_REQUESTS);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
FOR (REQUEST_HANDLE request)
|
|
|
|
X IN RDB$GENERATORS WITH X.RDB$GENERATOR_ID EQ gen_id
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
name = X.RDB$GENERATOR_NAME;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2002-07-01 18:59:09 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
void MET_lookup_index(thread_db* tdbb,
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName& index_name,
|
|
|
|
const MetaName& relation_name,
|
2003-10-03 03:53:34 +02:00
|
|
|
USHORT number)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ i n d e x
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup index name from relation and index number.
|
|
|
|
* Calling routine must pass a buffer of at least 32 bytes.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
index_name = "";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_index, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
2005-05-12 20:28:04 +02:00
|
|
|
X IN RDB$INDICES WITH X.RDB$RELATION_NAME EQ relation_name.c_str()
|
2005-05-28 00:45:31 +02:00
|
|
|
AND X.RDB$INDEX_ID EQ number
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
index_name = X.RDB$INDEX_NAME;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
SLONG MET_lookup_index_name(thread_db* tdbb,
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName& index_name,
|
2003-12-22 11:00:59 +01:00
|
|
|
SLONG* relation_id, SSHORT* status)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ i n d e x _ n a m e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup index id from index name.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SLONG id = -1;
|
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_index_name, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
*status = MET_object_unknown;
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$INDICES WITH
|
2004-03-31 19:59:58 +02:00
|
|
|
X.RDB$INDEX_NAME EQ index_name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
|
|
|
if (X.RDB$INDEX_INACTIVE == 0)
|
2001-05-23 15:26:42 +02:00
|
|
|
*status = MET_object_active;
|
2010-04-18 17:04:52 +02:00
|
|
|
else
|
2001-05-23 15:26:42 +02:00
|
|
|
*status = MET_object_inactive;
|
|
|
|
|
|
|
|
id = X.RDB$INDEX_ID - 1;
|
2003-12-22 11:00:59 +01:00
|
|
|
const jrd_rel* relation = MET_lookup_relation(tdbb, X.RDB$RELATION_NAME);
|
2001-05-23 15:26:42 +02:00
|
|
|
*relation_id = relation->rel_id;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-21 06:20:18 +01:00
|
|
|
bool MET_lookup_partner(thread_db* tdbb, jrd_rel* relation, index_desc* idx, const TEXT* index_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ p a r t n e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Find partner index participating in a
|
|
|
|
* foreign key relationship.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-01-19 19:33:03 +01:00
|
|
|
if (relation->rel_flags & REL_check_partners) {
|
|
|
|
scan_partners(tdbb, relation);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (idx->idx_flags & idx_foreign)
|
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
if (index_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// Since primary key index names aren't being cached, do a long
|
|
|
|
// hard lookup. This is only called during index create for foreign keys.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
bool found = false;
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest request;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
IDX IN RDB$INDICES CROSS
|
|
|
|
IND IN RDB$INDICES WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
IDX.RDB$RELATION_NAME EQ relation->rel_name.c_str() AND
|
2001-05-23 15:26:42 +02:00
|
|
|
(IDX.RDB$INDEX_ID EQ idx->idx_id + 1 OR
|
2002-12-22 14:08:50 +01:00
|
|
|
IDX.RDB$INDEX_NAME EQ index_name) AND
|
2001-05-23 15:26:42 +02:00
|
|
|
IND.RDB$INDEX_NAME EQ IDX.RDB$FOREIGN_KEY AND
|
2005-12-12 14:58:19 +01:00
|
|
|
IND.RDB$UNIQUE_FLAG = 1
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
const jrd_rel* partner_relation = MET_lookup_relation(tdbb, IND.RDB$RELATION_NAME);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
if (partner_relation && !IDX.RDB$INDEX_INACTIVE && !IND.RDB$INDEX_INACTIVE)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
idx->idx_primary_relation = partner_relation->rel_id;
|
|
|
|
idx->idx_primary_index = IND.RDB$INDEX_ID - 1;
|
2009-06-21 08:04:18 +02:00
|
|
|
fb_assert(idx->idx_primary_index != idx_invalid);
|
2004-01-03 11:59:52 +01:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
frgn* references = &relation->rel_foreign_refs;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (references->frgn_reference_ids)
|
|
|
|
{
|
2009-06-21 08:04:18 +02:00
|
|
|
for (unsigned int index_number = 0;
|
|
|
|
index_number < references->frgn_reference_ids->count();
|
2008-12-18 11:57:12 +01:00
|
|
|
index_number++)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
if (idx->idx_id == (*references->frgn_reference_ids)[index_number])
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
idx->idx_primary_relation = (*references->frgn_relations)[index_number];
|
|
|
|
idx->idx_primary_index = (*references->frgn_indexes)[index_number];
|
2004-01-03 11:59:52 +01:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-01-03 11:59:52 +01:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else if (idx->idx_flags & (idx_primary | idx_unique))
|
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
const prim* dependencies = &relation->rel_primary_dpnds;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (dependencies->prim_reference_ids)
|
|
|
|
{
|
2009-06-21 08:04:18 +02:00
|
|
|
for (unsigned int index_number = 0;
|
|
|
|
index_number < dependencies->prim_reference_ids->count();
|
2001-05-23 15:26:42 +02:00
|
|
|
index_number++)
|
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
if (idx->idx_id == (*dependencies->prim_reference_ids)[index_number])
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
idx->idx_foreign_primaries = relation->rel_primary_dpnds.prim_reference_ids;
|
|
|
|
idx->idx_foreign_relations = relation->rel_primary_dpnds.prim_relations;
|
|
|
|
idx->idx_foreign_indexes = relation->rel_primary_dpnds.prim_indexes;
|
2004-01-03 11:59:52 +01:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-01-03 11:59:52 +01:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
jrd_prc* MET_lookup_procedure(thread_db* tdbb, const QualifiedName& name, bool noscan)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ p r o c e d u r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup procedure by name. Name passed in is
|
|
|
|
* ASCIZ name.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2003-12-22 11:00:59 +01:00
|
|
|
jrd_prc* check_procedure = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// See if we already know the procedure by name
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_prc*>* procedures = attachment->att_procedures;
|
2009-11-07 12:58:54 +01:00
|
|
|
if (procedures)
|
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
vec<jrd_prc*>::iterator ptr = procedures->begin();
|
|
|
|
for (const vec<jrd_prc*>::const_iterator end = procedures->end(); ptr < end; ++ptr)
|
2002-11-16 21:20:44 +01:00
|
|
|
{
|
2005-12-02 08:35:34 +01:00
|
|
|
jrd_prc* procedure = *ptr;
|
2008-12-18 11:57:12 +01:00
|
|
|
if (procedure && !(procedure->prc_flags & PRC_obsolete) &&
|
|
|
|
((procedure->prc_flags & PRC_scanned) || noscan) &&
|
|
|
|
!(procedure->prc_flags & PRC_being_scanned) &&
|
|
|
|
!(procedure->prc_flags & PRC_being_altered))
|
2002-11-16 19:48:01 +01:00
|
|
|
{
|
2009-12-27 23:05:22 +01:00
|
|
|
if (procedure->getName() == name)
|
2002-11-16 21:20:44 +01:00
|
|
|
{
|
2005-05-28 00:45:31 +02:00
|
|
|
if (procedure->prc_flags & PRC_check_existence)
|
2004-03-31 19:59:58 +02:00
|
|
|
{
|
|
|
|
check_procedure = procedure;
|
2008-12-18 11:57:12 +01:00
|
|
|
LCK_lock(tdbb, check_procedure->prc_existence_lock, LCK_SR, LCK_WAIT);
|
2004-03-31 19:59:58 +02:00
|
|
|
break;
|
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
|
|
|
|
return procedure;
|
|
|
|
}
|
2002-11-16 19:48:01 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// We need to look up the procedure name in RDB$PROCEDURES
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_prc* procedure = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_procedure, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
2009-10-21 02:42:38 +02:00
|
|
|
P IN RDB$PROCEDURES
|
|
|
|
WITH P.RDB$PROCEDURE_NAME EQ name.identifier.c_str() AND
|
2010-01-27 05:32:27 +01:00
|
|
|
P.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
procedure = MET_procedure(tdbb, P.RDB$PROCEDURE_ID, noscan, 0);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_procedure)
|
|
|
|
{
|
2003-11-27 12:39:10 +01:00
|
|
|
check_procedure->prc_flags &= ~PRC_check_existence;
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_procedure != procedure)
|
|
|
|
{
|
2003-11-27 12:39:10 +01:00
|
|
|
LCK_release(tdbb, check_procedure->prc_existence_lock);
|
|
|
|
check_procedure->prc_flags |= PRC_obsolete;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
jrd_prc* MET_lookup_procedure_id(thread_db* tdbb, SSHORT id,
|
2009-11-21 06:20:18 +01:00
|
|
|
bool return_deleted, bool noscan, USHORT flags)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ p r o c e d u r e _ i d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup procedure by id.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2003-12-22 11:00:59 +01:00
|
|
|
jrd_prc* check_procedure = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_prc* procedure;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_prc*>* procedures = attachment->att_procedures;
|
2008-12-18 11:57:12 +01:00
|
|
|
if (procedures && id < (SSHORT) procedures->count() && (procedure = (*procedures)[id]) &&
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->getId() == id &&
|
2008-12-18 11:57:12 +01:00
|
|
|
!(procedure->prc_flags & PRC_being_scanned) &&
|
|
|
|
((procedure->prc_flags & PRC_scanned) || noscan) &&
|
|
|
|
!(procedure->prc_flags & PRC_being_altered) &&
|
|
|
|
(!(procedure->prc_flags & PRC_obsolete) || return_deleted))
|
2002-11-16 19:48:01 +01:00
|
|
|
{
|
2009-11-07 12:58:54 +01:00
|
|
|
if (procedure->prc_flags & PRC_check_existence)
|
|
|
|
{
|
2003-11-27 12:39:10 +01:00
|
|
|
check_procedure = procedure;
|
2004-10-07 11:15:32 +02:00
|
|
|
LCK_lock(tdbb, check_procedure->prc_existence_lock, LCK_SR, LCK_WAIT);
|
2003-11-27 12:39:10 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return procedure;
|
|
|
|
}
|
2002-11-16 19:48:01 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// We need to look up the procedure name in RDB$PROCEDURES
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
procedure = NULL;
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_proc_id, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
P IN RDB$PROCEDURES WITH P.RDB$PROCEDURE_ID EQ id
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2002-11-04 16:12:34 +01:00
|
|
|
procedure = MET_procedure(tdbb, P.RDB$PROCEDURE_ID, noscan, flags);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_procedure)
|
|
|
|
{
|
2003-11-27 12:39:10 +01:00
|
|
|
check_procedure->prc_flags &= ~PRC_check_existence;
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_procedure != procedure)
|
|
|
|
{
|
2003-11-27 12:39:10 +01:00
|
|
|
LCK_release(tdbb, check_procedure->prc_existence_lock);
|
|
|
|
check_procedure->prc_flags |= PRC_obsolete;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
jrd_rel* MET_lookup_relation(thread_db* tdbb, const MetaName& name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ r e l a t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup relation by name. Name passed in is
|
|
|
|
* ASCIZ name.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// See if we already know the relation by name
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_rel*>* relations = attachment->att_relations;
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_rel* check_relation = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_rel*>::iterator ptr = relations->begin();
|
2006-02-10 04:28:43 +01:00
|
|
|
for (const vec<jrd_rel*>::const_iterator end = relations->end(); ptr < end; ++ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-11-28 13:53:52 +01:00
|
|
|
jrd_rel* const relation = *ptr;
|
|
|
|
|
|
|
|
if (relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2011-05-11 03:18:28 +02:00
|
|
|
if (relation->rel_flags & REL_deleting)
|
2012-12-14 18:59:02 +01:00
|
|
|
Jrd::Attachment::CheckoutLockGuard guard(attachment, relation->rel_drop_mutex, FB_FUNCTION);
|
2003-02-24 16:19:20 +01:00
|
|
|
|
2009-11-28 13:53:52 +01:00
|
|
|
if (!(relation->rel_flags & REL_deleted))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-11-28 13:53:52 +01:00
|
|
|
// dimitr: for non-system relations we should also check
|
|
|
|
// REL_scanned and REL_being_scanned flags. Look
|
|
|
|
// at MET_lookup_procedure for example.
|
|
|
|
if (!(relation->rel_flags & REL_system) &&
|
|
|
|
(!(relation->rel_flags & REL_scanned) || (relation->rel_flags & REL_being_scanned)))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-11-28 13:53:52 +01:00
|
|
|
continue;
|
2005-05-12 20:28:04 +02:00
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2009-11-28 13:53:52 +01:00
|
|
|
if (relation->rel_name == name)
|
|
|
|
{
|
|
|
|
if (relation->rel_flags & REL_check_existence)
|
|
|
|
{
|
|
|
|
check_relation = relation;
|
|
|
|
LCK_lock(tdbb, check_relation->rel_existence_lock, LCK_SR, LCK_WAIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return relation;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// We need to look up the relation name in RDB$RELATIONS
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_rel* relation = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_relation, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
2005-05-12 20:28:04 +02:00
|
|
|
X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ name.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
relation = MET_relation(tdbb, X.RDB$RELATION_ID);
|
2008-06-26 17:22:01 +02:00
|
|
|
if (relation->rel_name.length() == 0) {
|
|
|
|
relation->rel_name = name;
|
|
|
|
}
|
2011-05-30 16:26:15 +02:00
|
|
|
|
|
|
|
relation->rel_flags |= get_rel_flags_from_FLAGS(X.RDB$FLAGS);
|
2011-06-04 04:18:55 +02:00
|
|
|
|
2011-05-30 16:26:15 +02:00
|
|
|
if (!X.RDB$RELATION_TYPE.NULL)
|
|
|
|
{
|
2011-05-31 16:18:27 +02:00
|
|
|
relation->rel_flags |= MET_get_rel_flags_from_TYPE(X.RDB$RELATION_TYPE);
|
2011-05-30 16:26:15 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_relation)
|
|
|
|
{
|
2008-01-31 14:36:11 +01:00
|
|
|
check_relation->rel_flags &= ~REL_check_existence;
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_relation != relation)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
LCK_release(tdbb, check_relation->rel_existence_lock);
|
2005-06-26 23:48:47 +02:00
|
|
|
LCK_release(tdbb, check_relation->rel_partners_lock);
|
2010-06-15 14:27:33 +02:00
|
|
|
LCK_release(tdbb, check_relation->rel_rescan_lock);
|
2008-01-31 14:36:11 +01:00
|
|
|
check_relation->rel_flags &= ~REL_check_partners;
|
2001-05-23 15:26:42 +02:00
|
|
|
check_relation->rel_flags |= REL_deleted;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return relation;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
jrd_rel* MET_lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ l o o k u p _ r e l a t i o n _ i d
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Lookup relation by id. Make sure it really exists.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// System relations are above suspicion
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (id < (int) rel_MAX)
|
|
|
|
{
|
2004-11-01 04:18:42 +01:00
|
|
|
fb_assert(id < MAX_USHORT);
|
2001-05-23 15:26:42 +02:00
|
|
|
return MET_relation(tdbb, (USHORT) id);
|
|
|
|
}
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
jrd_rel* check_relation = NULL;
|
|
|
|
jrd_rel* relation;
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_rel*>* vector = attachment->att_relations;
|
2008-12-18 11:57:12 +01:00
|
|
|
if (vector && (id < (SLONG) vector->count()) && (relation = (*vector)[id]))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2011-05-11 03:18:28 +02:00
|
|
|
if (relation->rel_flags & REL_deleting)
|
2012-12-14 18:59:02 +01:00
|
|
|
Jrd::Attachment::CheckoutLockGuard guard(attachment, relation->rel_drop_mutex, FB_FUNCTION);
|
2009-11-28 13:53:52 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (relation->rel_flags & REL_deleted)
|
2008-01-16 10:29:37 +01:00
|
|
|
return return_deleted ? relation : NULL;
|
|
|
|
|
|
|
|
if (relation->rel_flags & REL_check_existence)
|
|
|
|
{
|
|
|
|
check_relation = relation;
|
|
|
|
LCK_lock(tdbb, check_relation->rel_existence_lock, LCK_SR, LCK_WAIT);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2008-01-16 10:29:37 +01:00
|
|
|
return relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// We need to look up the relation id in RDB$RELATIONS
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
relation = NULL;
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_l_rel_id, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
X IN RDB$RELATIONS WITH X.RDB$RELATION_ID EQ id
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
relation = MET_relation(tdbb, X.RDB$RELATION_ID);
|
2008-06-26 17:22:01 +02:00
|
|
|
if (relation->rel_name.length() == 0) {
|
2008-07-01 03:12:02 +02:00
|
|
|
relation->rel_name = X.RDB$RELATION_NAME;
|
2008-06-26 17:22:01 +02:00
|
|
|
}
|
2011-05-30 16:26:15 +02:00
|
|
|
|
|
|
|
relation->rel_flags |= get_rel_flags_from_FLAGS(X.RDB$FLAGS);
|
2011-06-04 04:18:55 +02:00
|
|
|
|
2011-05-30 16:26:15 +02:00
|
|
|
if (!X.RDB$RELATION_TYPE.NULL)
|
|
|
|
{
|
2011-05-31 16:18:27 +02:00
|
|
|
relation->rel_flags |= MET_get_rel_flags_from_TYPE(X.RDB$RELATION_TYPE);
|
2011-05-30 16:26:15 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_relation)
|
|
|
|
{
|
2008-01-31 14:36:11 +01:00
|
|
|
check_relation->rel_flags &= ~REL_check_existence;
|
2009-11-07 12:58:54 +01:00
|
|
|
if (check_relation != relation)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
LCK_release(tdbb, check_relation->rel_existence_lock);
|
2005-06-26 23:48:47 +02:00
|
|
|
LCK_release(tdbb, check_relation->rel_partners_lock);
|
2010-06-15 14:27:33 +02:00
|
|
|
LCK_release(tdbb, check_relation->rel_rescan_lock);
|
2008-01-31 14:36:11 +01:00
|
|
|
check_relation->rel_flags &= ~REL_check_partners;
|
2001-05-23 15:26:42 +02:00
|
|
|
check_relation->rel_flags |= REL_deleted;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return relation;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
DmlNode* MET_parse_blob(thread_db* tdbb,
|
2003-12-22 11:00:59 +01:00
|
|
|
jrd_rel* relation,
|
2004-03-18 06:56:06 +01:00
|
|
|
bid* blob_id,
|
2004-03-28 11:10:30 +02:00
|
|
|
CompilerScratch** csb_ptr,
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement** statementPtr,
|
2010-10-12 13:36:51 +02:00
|
|
|
const bool trigger,
|
|
|
|
bool validationExpr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ p a r s e _ b l o b
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Parse blr, returning a compiler scratch block with the results.
|
|
|
|
*
|
|
|
|
* if ignore_perm is true then, the request generated must be set to
|
|
|
|
* ignore all permissions checks. In this case, we call PAR_blr
|
|
|
|
* passing it the csb_ignore_perm flag to generate a request
|
|
|
|
* which must go through without checking any permissions.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::open(tdbb, attachment->getSysTransaction(), blob_id);
|
2013-01-25 13:34:19 +01:00
|
|
|
ULONG length = blob->blb_length + 10;
|
2010-06-12 18:32:46 +02:00
|
|
|
HalfStaticArray<UCHAR, 512> tmp;
|
2005-05-12 20:28:04 +02:00
|
|
|
UCHAR* temp = tmp.getBuffer(length);
|
2012-02-07 04:17:52 +01:00
|
|
|
length = blob->BLB_get_data(tdbb, temp, length);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
DmlNode* node = NULL;
|
2010-10-12 13:36:51 +02:00
|
|
|
|
|
|
|
if (validationExpr)
|
|
|
|
{
|
|
|
|
// The set of MET parse functions needs a rework.
|
|
|
|
// For now, our caller chain is not interested in the returned node.
|
2013-03-31 20:23:54 +02:00
|
|
|
PAR_validation_blr(tdbb, relation, temp, length, NULL, csb_ptr, 0);
|
2010-10-12 13:36:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
node = PAR_blr(tdbb, relation, temp, length, NULL, csb_ptr, statementPtr, trigger, 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
void MET_parse_sys_trigger(thread_db* tdbb, jrd_rel* relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ p a r s e _ s y s _ t r i g g e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Parse the blr for a system relation's triggers.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
relation->rel_flags &= ~REL_sys_triggers;
|
|
|
|
|
2005-10-13 10:11:37 +02:00
|
|
|
// Release any triggers in case of a rescan
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (relation->rel_pre_store)
|
|
|
|
MET_release_triggers(tdbb, &relation->rel_pre_store);
|
|
|
|
if (relation->rel_post_store)
|
|
|
|
MET_release_triggers(tdbb, &relation->rel_post_store);
|
|
|
|
if (relation->rel_pre_erase)
|
|
|
|
MET_release_triggers(tdbb, &relation->rel_pre_erase);
|
|
|
|
if (relation->rel_post_erase)
|
|
|
|
MET_release_triggers(tdbb, &relation->rel_post_erase);
|
|
|
|
if (relation->rel_pre_modify)
|
|
|
|
MET_release_triggers(tdbb, &relation->rel_pre_modify);
|
|
|
|
if (relation->rel_post_modify)
|
|
|
|
MET_release_triggers(tdbb, &relation->rel_post_modify);
|
|
|
|
|
2005-10-13 10:11:37 +02:00
|
|
|
// No need to load triggers for ReadOnly databases, since
|
|
|
|
// INSERT/DELETE/UPDATE statements are not going to be allowed
|
2011-03-19 14:10:51 +01:00
|
|
|
// hvlad: GTT with ON COMMIT DELETE ROWS clause is writable
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2012-04-12 11:02:13 +02:00
|
|
|
if (dbb->readOnly() && !(relation->rel_flags & REL_temp_tran))
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
relation->rel_flags |= REL_sys_trigs_being_loaded;
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_s_triggers2, IRQ_REQUESTS);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
FOR (REQUEST_HANDLE request)
|
2008-12-18 11:57:12 +01:00
|
|
|
TRG IN RDB$TRIGGERS
|
|
|
|
WITH TRG.RDB$RELATION_NAME = relation->rel_name.c_str()
|
|
|
|
AND TRG.RDB$SYSTEM_FLAG = 1
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2009-10-21 02:42:38 +02:00
|
|
|
const FB_UINT64 type = TRG.RDB$TRIGGER_TYPE;
|
2005-10-13 10:11:37 +02:00
|
|
|
const USHORT trig_flags = TRG.RDB$FLAGS;
|
|
|
|
const TEXT* name = TRG.RDB$TRIGGER_NAME;
|
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
trig_vec** ptr;
|
2005-10-13 10:11:37 +02:00
|
|
|
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (type)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case 1:
|
|
|
|
ptr = &relation->rel_pre_store;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ptr = &relation->rel_post_store;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
ptr = &relation->rel_pre_modify;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
ptr = &relation->rel_post_modify;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
ptr = &relation->rel_pre_erase;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
ptr = &relation->rel_post_erase;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ptr = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ptr)
|
|
|
|
{
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::open(tdbb, attachment->getSysTransaction(), &TRG.RDB$TRIGGER_BLR);
|
2013-01-25 13:34:19 +01:00
|
|
|
ULONG length = blob->blb_length + 10;
|
2010-06-12 18:32:46 +02:00
|
|
|
HalfStaticArray<UCHAR, 128> blr;
|
2012-02-07 04:17:52 +01:00
|
|
|
length = blob->BLB_get_data(tdbb, blr.getBuffer(length), length);
|
2005-10-13 10:11:37 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
USHORT par_flags = (USHORT) ((trig_flags & TRG_ignore_perm) ? csb_ignore_perm : 0);
|
2005-03-28 23:52:55 +02:00
|
|
|
if (type & 1)
|
|
|
|
par_flags |= csb_pre_trigger;
|
|
|
|
else
|
|
|
|
par_flags |= csb_post_trigger;
|
2005-10-13 10:11:37 +02:00
|
|
|
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement* statement = NULL;
|
|
|
|
|
2004-08-30 20:11:08 +02:00
|
|
|
{
|
2011-05-09 12:15:19 +02:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
|
2010-04-19 00:19:11 +02:00
|
|
|
PAR_blr(tdbb, relation, blr.begin(), length, NULL, NULL, &statement, true, par_flags);
|
2004-08-30 20:11:08 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-19 00:19:11 +02:00
|
|
|
statement->triggerName = name;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-19 00:19:11 +02:00
|
|
|
statement->flags |= JrdStatement::FLAG_SYS_TRIGGER;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (trig_flags & TRG_ignore_perm)
|
2010-04-19 00:19:11 +02:00
|
|
|
statement->flags |= JrdStatement::FLAG_IGNORE_PERM;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-19 00:19:11 +02:00
|
|
|
save_trigger_data(tdbb, ptr, relation, statement, NULL, NULL, NULL, type, true, 0, "",
|
|
|
|
"", NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
relation->rel_flags &= ~REL_sys_trigs_being_loaded;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_post_existence(thread_db* tdbb, jrd_rel* relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ p o s t _ e x i s t e n c e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Post an interest in the existence of a relation.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2008-06-26 13:20:41 +02:00
|
|
|
relation->rel_use_count++;
|
|
|
|
|
|
|
|
if (!MET_lookup_relation_id(tdbb, relation->rel_id, false))
|
2004-01-03 11:59:52 +01:00
|
|
|
{
|
2008-06-26 13:20:41 +02:00
|
|
|
relation->rel_use_count--;
|
2008-08-27 14:20:47 +02:00
|
|
|
ERR_post(Arg::Gds(isc_relnotdef) << Arg::Str(relation->rel_name));
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_prepare(thread_db* tdbb, jrd_tra* transaction, USHORT length, const UCHAR* msg)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2005-05-28 00:45:31 +02:00
|
|
|
* M E T _ p r e p a r e
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Post a transaction description to RDB$TRANSACTIONS.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_s_trans, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
STORE(REQUEST_HANDLE request) X IN RDB$TRANSACTIONS
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
X.RDB$TRANSACTION_ID = transaction->tra_number;
|
2008-12-18 11:57:12 +01:00
|
|
|
X.RDB$TRANSACTION_STATE = RDB$TRANSACTIONS.RDB$TRANSACTION_STATE.LIMBO;
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::create(tdbb, attachment->getSysTransaction(), &X.RDB$TRANSACTION_DESCRIPTION);
|
2012-02-07 04:17:52 +01:00
|
|
|
blob->BLB_put_segment(tdbb, msg, length);
|
|
|
|
blob->BLB_close(tdbb);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_STORE
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ p r o c e d u r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Find or create a procedure block for a given procedure id.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_prc*>* vector = attachment->att_procedures;
|
2011-05-11 03:18:28 +02:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
if (!vector)
|
2011-05-09 12:15:19 +02:00
|
|
|
vector = attachment->att_procedures = vec<jrd_prc*>::newVector(*attachment->att_pool, id + 10);
|
2003-08-09 23:15:32 +02:00
|
|
|
else if (id >= (int) vector->count())
|
2001-12-24 03:51:06 +01:00
|
|
|
vector->resize(id + 10);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
jrd_prc* procedure = (*vector)[id];
|
2008-08-25 07:28:50 +02:00
|
|
|
|
|
|
|
if (procedure && !(procedure->prc_flags & PRC_obsolete))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2008-08-25 07:28:50 +02:00
|
|
|
// Make sure PRC_being_scanned and PRC_scanned are not set at the same time
|
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
fb_assert(!(procedure->prc_flags & PRC_being_scanned) || !(procedure->prc_flags & PRC_scanned));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* To avoid scanning recursive procedure's blr recursively let's
|
|
|
|
make use of PRC_being_scanned bit. Because this bit is set
|
|
|
|
later in the code, it is not set when we are here first time.
|
2005-05-28 00:45:31 +02:00
|
|
|
If (in case of rec. procedure) we get here second time it is
|
2001-05-23 15:26:42 +02:00
|
|
|
already set and we return half baked procedure.
|
|
|
|
In case of superserver this code is under the rec. mutex
|
|
|
|
protection, thus the only guy (thread) who can get here and see
|
|
|
|
PRC_being_scanned bit set is the guy which started procedure scan
|
|
|
|
and currently holds the mutex.
|
2005-05-28 00:45:31 +02:00
|
|
|
In case of classic, there is always only one guy and if it
|
2001-05-23 15:26:42 +02:00
|
|
|
sees PRC_being_scanned bit set it is safe to assume it is here
|
|
|
|
second time.
|
|
|
|
|
|
|
|
If procedure has already been scanned - return. This condition
|
2006-08-19 04:52:39 +02:00
|
|
|
is for those threads that did not find procedure in cache and
|
2001-05-23 15:26:42 +02:00
|
|
|
came here to get it from disk. But only one was able to lock
|
|
|
|
the mutex and do the scanning, others were waiting. As soon as
|
|
|
|
the first thread releases the mutex another thread gets in and
|
2008-08-25 07:28:50 +02:00
|
|
|
it would be just unfair to make it do the work again.
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
2008-08-25 07:28:50 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
if ((procedure->prc_flags & PRC_being_scanned) || (procedure->prc_flags & PRC_scanned))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-18 21:03:30 +01:00
|
|
|
if (!procedure)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
procedure = FB_NEW(*dbb->dbb_permanent) jrd_prc(*dbb->dbb_permanent);
|
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
|
|
|
procedure->prc_flags |= (PRC_being_scanned | flags);
|
2003-06-01 18:22:47 +02:00
|
|
|
procedure->prc_flags &= ~PRC_obsolete;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->setId(id);
|
2004-02-20 07:43:27 +01:00
|
|
|
(*vector)[id] = procedure;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (!procedure->prc_existence_lock)
|
|
|
|
{
|
2012-05-31 18:53:42 +02:00
|
|
|
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0)
|
2012-06-21 17:37:38 +02:00
|
|
|
Lock(tdbb, sizeof(SLONG), LCK_prc_exist, procedure, blocking_ast_procedure);
|
2004-01-03 11:59:52 +01:00
|
|
|
procedure->prc_existence_lock = lock;
|
2009-12-27 23:05:22 +01:00
|
|
|
lock->lck_key.lck_long = procedure->getId();
|
2002-11-04 16:12:34 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-08-25 07:28:50 +02:00
|
|
|
LCK_lock(tdbb, procedure->prc_existence_lock, LCK_SR, LCK_WAIT);
|
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
if (!noscan)
|
|
|
|
{
|
2009-12-25 08:09:02 +01:00
|
|
|
bool valid_blr = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_r_procedure, IRQ_REQUESTS);
|
2007-07-04 18:07:55 +02:00
|
|
|
|
2004-01-04 05:41:56 +01:00
|
|
|
FOR(REQUEST_HANDLE request)
|
2009-12-27 23:05:22 +01:00
|
|
|
P IN RDB$PROCEDURES WITH P.RDB$PROCEDURE_ID EQ procedure->getId()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2009-12-27 23:05:22 +01:00
|
|
|
if (procedure->getName().toString().length() == 0)
|
2004-01-04 05:41:56 +01:00
|
|
|
{
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->setName(QualifiedName(P.RDB$PROCEDURE_NAME,
|
|
|
|
(P.RDB$PACKAGE_NAME.NULL ? "" : P.RDB$PACKAGE_NAME)));
|
2004-01-04 05:41:56 +01:00
|
|
|
}
|
2009-12-31 12:24:28 +01:00
|
|
|
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->setId(P.RDB$PROCEDURE_ID);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2004-01-04 05:41:56 +01:00
|
|
|
if (!P.RDB$SECURITY_CLASS.NULL)
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->setSecurityName(P.RDB$SECURITY_CLASS);
|
2009-10-21 02:42:38 +02:00
|
|
|
else if (!P.RDB$PACKAGE_NAME.NULL)
|
|
|
|
{
|
|
|
|
AutoCacheRequest requestHandle(tdbb, irq_l_procedure_pkg_class, IRQ_REQUESTS);
|
|
|
|
|
|
|
|
FOR (REQUEST_HANDLE requestHandle)
|
|
|
|
PKG IN RDB$PACKAGES
|
|
|
|
WITH PKG.RDB$PACKAGE_NAME EQ P.RDB$PACKAGE_NAME
|
|
|
|
{
|
|
|
|
if (!PKG.RDB$SECURITY_CLASS.NULL)
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->setSecurityName(PKG.RDB$SECURITY_CLASS);
|
2009-10-21 02:42:38 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
|
|
|
}
|
|
|
|
|
2011-11-10 15:35:40 +01:00
|
|
|
procedure->setImplemented(true);
|
2011-10-16 22:36:07 +02:00
|
|
|
procedure->getInputFields().resize(P.RDB$PROCEDURE_INPUTS);
|
|
|
|
procedure->getOutputFields().resize(P.RDB$PROCEDURE_OUTPUTS);
|
|
|
|
procedure->setDefaultCount(0);
|
2007-07-04 18:07:55 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request2(tdbb, irq_r_params, IRQ_REQUESTS);
|
2007-07-04 18:07:55 +02:00
|
|
|
|
2009-10-30 11:50:59 +01:00
|
|
|
const MetaName packageName(P.RDB$PACKAGE_NAME.NULL ? NULL : P.RDB$PACKAGE_NAME);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
FOR (REQUEST_HANDLE request2)
|
|
|
|
PA IN RDB$PROCEDURE_PARAMETERS
|
|
|
|
CROSS F IN RDB$FIELDS
|
|
|
|
WITH F.RDB$FIELD_NAME = PA.RDB$FIELD_SOURCE AND
|
|
|
|
PA.RDB$PROCEDURE_NAME = P.RDB$PROCEDURE_NAME AND
|
2009-10-30 11:50:59 +01:00
|
|
|
PA.RDB$PACKAGE_NAME EQUIV NULLIF(packageName.c_str(), '')
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2009-11-27 07:59:21 +01:00
|
|
|
const SSHORT pa_collation_id_null = PA.RDB$COLLATION_ID.NULL;
|
|
|
|
const SSHORT pa_collation_id = PA.RDB$COLLATION_ID;
|
|
|
|
const SSHORT pa_default_value_null = PA.RDB$DEFAULT_VALUE.NULL;
|
2010-04-12 23:19:55 +02:00
|
|
|
bid pa_default_value = pa_default_value_null ? F.RDB$DEFAULT_VALUE : PA.RDB$DEFAULT_VALUE;
|
2006-08-19 04:52:39 +02:00
|
|
|
|
2010-10-12 13:36:51 +02:00
|
|
|
Array<NestConst<Parameter> >& paramArray = PA.RDB$PARAMETER_TYPE ?
|
2011-10-16 22:36:07 +02:00
|
|
|
procedure->getOutputFields() : procedure->getInputFields();
|
2004-01-04 05:41:56 +01:00
|
|
|
|
2008-08-25 07:28:50 +02:00
|
|
|
// should be error if field already exists
|
2008-12-18 11:57:12 +01:00
|
|
|
Parameter* parameter = FB_NEW(*dbb->dbb_permanent) Parameter(*dbb->dbb_permanent);
|
2004-01-04 05:41:56 +01:00
|
|
|
parameter->prm_number = PA.RDB$PARAMETER_NUMBER;
|
2009-12-27 23:05:22 +01:00
|
|
|
paramArray[parameter->prm_number] = parameter;
|
2005-05-12 20:28:04 +02:00
|
|
|
parameter->prm_name = PA.RDB$PARAMETER_NAME;
|
2009-10-21 02:42:38 +02:00
|
|
|
parameter->prm_nullable = PA.RDB$NULL_FLAG.NULL || PA.RDB$NULL_FLAG == 0; // ODS_11_1
|
|
|
|
parameter->prm_mechanism = PA.RDB$PARAMETER_MECHANISM.NULL ? // ODS_11_1
|
|
|
|
prm_mech_normal : (prm_mech_t) PA.RDB$PARAMETER_MECHANISM;
|
|
|
|
|
|
|
|
if (!PA.RDB$FIELD_SOURCE.NULL)
|
|
|
|
parameter->prm_field_source = PA.RDB$FIELD_SOURCE;
|
2007-01-17 02:19:01 +01:00
|
|
|
|
2004-01-04 05:41:56 +01:00
|
|
|
DSC_make_descriptor(¶meter->prm_desc, F.RDB$FIELD_TYPE,
|
|
|
|
F.RDB$FIELD_SCALE, F.RDB$FIELD_LENGTH,
|
|
|
|
F.RDB$FIELD_SUB_TYPE, F.RDB$CHARACTER_SET_ID,
|
2006-08-19 04:52:39 +02:00
|
|
|
(pa_collation_id_null ? F.RDB$COLLATION_ID : pa_collation_id));
|
2004-01-16 13:59:16 +01:00
|
|
|
|
2006-08-19 04:52:39 +02:00
|
|
|
if (PA.RDB$PARAMETER_TYPE == 0 &&
|
|
|
|
(!pa_default_value_null ||
|
2006-09-01 03:40:22 +02:00
|
|
|
(fb_utils::implicit_domain(F.RDB$FIELD_NAME) && !F.RDB$DEFAULT_VALUE.NULL)))
|
2004-08-30 20:11:08 +02:00
|
|
|
{
|
2011-10-16 22:36:07 +02:00
|
|
|
procedure->setDefaultCount(procedure->getDefaultCount() + 1);
|
2011-05-09 12:15:19 +02:00
|
|
|
MemoryPool* pool = attachment->createPool();
|
2010-04-12 23:19:55 +02:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, pool);
|
2006-08-19 04:52:39 +02:00
|
|
|
|
2010-04-12 23:19:55 +02:00
|
|
|
try
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
2010-12-04 23:15:03 +01:00
|
|
|
parameter->prm_default_value = static_cast<ValueExprNode*>(
|
|
|
|
MET_parse_blob(tdbb, NULL, &pa_default_value, NULL, NULL, false, false));
|
2006-08-19 04:52:39 +02:00
|
|
|
}
|
2010-04-14 00:50:15 +02:00
|
|
|
catch (const Exception&)
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
2010-04-14 11:47:51 +02:00
|
|
|
// Here we lose pools created for previous defaults.
|
2010-04-12 23:19:55 +02:00
|
|
|
// Probably we should use common pool for defaults and procedure itself.
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->deletePool(pool);
|
2010-04-12 23:19:55 +02:00
|
|
|
throw;
|
|
|
|
}
|
2004-01-16 13:59:16 +01:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2004-01-04 05:41:56 +01:00
|
|
|
|
2011-07-10 03:23:53 +02:00
|
|
|
const bool external = !P.RDB$ENGINE_NAME.NULL; // ODS_12_0
|
|
|
|
|
|
|
|
if (external)
|
|
|
|
{
|
|
|
|
HalfStaticArray<char, 512> body;
|
|
|
|
|
|
|
|
if (!P.RDB$PROCEDURE_SOURCE.NULL)
|
|
|
|
{
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::open(tdbb, attachment->getSysTransaction(),
|
2011-07-10 03:23:53 +02:00
|
|
|
&P.RDB$PROCEDURE_SOURCE);
|
2012-02-07 04:17:52 +01:00
|
|
|
ULONG len = blob->BLB_get_data(tdbb,
|
2011-07-10 03:23:53 +02:00
|
|
|
(UCHAR*) body.getBuffer(blob->blb_length + 1), blob->blb_length + 1);
|
|
|
|
body.begin()[MIN(blob->blb_length, len)] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
body.getBuffer(1)[0] = '\0';
|
|
|
|
|
2013-03-04 02:42:58 +01:00
|
|
|
dbb->dbb_extManager.makeProcedure(tdbb, procedure, P.RDB$ENGINE_NAME,
|
|
|
|
(P.RDB$ENTRYPOINT.NULL ? "" : P.RDB$ENTRYPOINT), body.begin());
|
2011-07-10 03:23:53 +02:00
|
|
|
}
|
|
|
|
|
2011-10-16 22:36:07 +02:00
|
|
|
Array<NestConst<Parameter> >& paramArray = procedure->getOutputFields();
|
2009-12-27 23:05:22 +01:00
|
|
|
|
|
|
|
if (paramArray.hasData() && paramArray[0])
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-10-12 13:36:51 +02:00
|
|
|
Format* format = Format::newFormat(
|
2011-10-16 22:36:07 +02:00
|
|
|
*dbb->dbb_permanent, procedure->getOutputFields().getCount());
|
2013-03-04 02:42:58 +01:00
|
|
|
procedure->prc_record_format = format;
|
2005-12-02 08:35:34 +01:00
|
|
|
ULONG length = FLAG_BYTES(format->fmt_count);
|
|
|
|
Format::fmt_desc_iterator desc = format->fmt_desc.begin();
|
2010-10-12 13:36:51 +02:00
|
|
|
Array<NestConst<Parameter> >::iterator ptr, end;
|
2009-12-27 23:05:22 +01:00
|
|
|
for (ptr = paramArray.begin(), end = paramArray.end(); ptr < end; ++ptr, ++desc)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-10-12 13:36:51 +02:00
|
|
|
const Parameter* parameter = *ptr;
|
2008-08-25 07:28:50 +02:00
|
|
|
// check for parameter to be null, this can only happen if the
|
|
|
|
// parameter numbers get out of sync. This was added to fix bug
|
|
|
|
// 10534. -Shaunak Mistry 12-May-99
|
2004-01-04 05:41:56 +01:00
|
|
|
if (parameter)
|
|
|
|
{
|
|
|
|
*desc = parameter->prm_desc;
|
2009-11-27 07:59:21 +01:00
|
|
|
length = MET_align(&(*desc), length);
|
2004-01-21 08:18:30 +01:00
|
|
|
desc->dsc_address = (UCHAR *) (IPTR) length;
|
2004-01-04 05:41:56 +01:00
|
|
|
length += desc->dsc_length;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2011-01-29 18:24:29 +01:00
|
|
|
|
2011-01-28 19:50:27 +01:00
|
|
|
format->fmt_length = length;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2013-03-04 02:42:58 +01:00
|
|
|
procedure->prc_type = P.RDB$PROCEDURE_TYPE.NULL ?
|
|
|
|
prc_legacy : (prc_t) P.RDB$PROCEDURE_TYPE;
|
2006-07-19 16:50:33 +02:00
|
|
|
|
2013-03-04 02:42:58 +01:00
|
|
|
if (!external)
|
|
|
|
{
|
2013-03-27 02:34:44 +01:00
|
|
|
if (!P.RDB$PROCEDURE_BLR.NULL)
|
|
|
|
{
|
|
|
|
MemoryPool* csb_pool = attachment->createPool();
|
2006-10-30 21:58:06 +01:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, csb_pool);
|
|
|
|
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5);
|
2006-07-19 16:50:33 +02:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
if (!P.RDB$DEBUG_INFO.NULL)
|
|
|
|
DBG_parse_debug_info(tdbb, &P.RDB$DEBUG_INFO, *csb->csb_dbg_info);
|
2007-01-20 15:18:18 +01:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
try
|
|
|
|
{
|
2013-03-31 17:55:01 +02:00
|
|
|
procedure->parseBlr(tdbb, csb, &P.RDB$PROCEDURE_BLR);
|
2013-03-27 02:34:44 +01:00
|
|
|
}
|
|
|
|
catch (const Exception&)
|
|
|
|
{
|
|
|
|
delete csb;
|
2008-12-14 10:28:25 +01:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
if (procedure->getStatement())
|
|
|
|
procedure->releaseStatement(tdbb);
|
|
|
|
else
|
|
|
|
attachment->deletePool(csb_pool);
|
2006-11-03 10:42:42 +01:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
ERR_post(Arg::Gds(isc_bad_proc_BLR) << Arg::Str(procedure->getName().toString()));
|
|
|
|
}
|
2010-12-04 23:15:03 +01:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
procedure->getStatement()->procedure = procedure;
|
2013-03-30 03:31:03 +01:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
for (size_t i = 0; i < csb->csb_rpt.getCount(); i++)
|
2004-01-04 05:41:56 +01:00
|
|
|
{
|
2013-03-27 02:34:44 +01:00
|
|
|
MessageNode* node = csb->csb_rpt[i].csb_message;
|
|
|
|
|
|
|
|
/***
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
if (node->messageNumber == 1)
|
|
|
|
procedure->prc_output_msg = node;
|
|
|
|
}
|
|
|
|
***/
|
2004-01-04 05:41:56 +01:00
|
|
|
}
|
2013-03-30 03:31:03 +01:00
|
|
|
|
2013-03-27 02:34:44 +01:00
|
|
|
delete csb;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RefPtr<MsgMetadata> inputMetadata(
|
|
|
|
Routine::createMetadata(procedure->getInputFields()));
|
|
|
|
inputMetadata->release();
|
|
|
|
procedure->setInputFormat(
|
|
|
|
Routine::createFormat(procedure->getPool(), inputMetadata, false));
|
|
|
|
|
|
|
|
RefPtr<MsgMetadata> outputMetadata(
|
|
|
|
Routine::createMetadata(procedure->getOutputFields()));
|
|
|
|
outputMetadata->release();
|
|
|
|
procedure->setOutputFormat(
|
|
|
|
Routine::createFormat(procedure->getPool(), outputMetadata, true));
|
|
|
|
|
|
|
|
procedure->setImplemented(false);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2013-03-04 02:42:58 +01:00
|
|
|
}
|
2004-01-04 05:41:56 +01:00
|
|
|
|
2009-12-25 08:09:02 +01:00
|
|
|
if (P.RDB$VALID_BLR.NULL || P.RDB$VALID_BLR == FALSE)
|
|
|
|
valid_blr = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-04 05:41:56 +01:00
|
|
|
procedure->prc_flags |= PRC_scanned;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2012-04-12 11:02:13 +02:00
|
|
|
if (!dbb->readOnly() && !valid_blr)
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
|
|
|
// if the BLR was marked as invalid but the procedure was compiled,
|
|
|
|
// mark the BLR as valid
|
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest request5;
|
2006-08-19 04:52:39 +02:00
|
|
|
|
2006-08-30 06:54:44 +02:00
|
|
|
FOR(REQUEST_HANDLE request5)
|
2009-12-27 23:05:22 +01:00
|
|
|
P IN RDB$PROCEDURES WITH P.RDB$PROCEDURE_ID EQ procedure->getId()
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2006-08-19 04:52:39 +02:00
|
|
|
MODIFY P USING
|
|
|
|
P.RDB$VALID_BLR = TRUE;
|
|
|
|
P.RDB$VALID_BLR.NULL = FALSE;
|
2010-04-18 17:04:52 +02:00
|
|
|
END_MODIFY
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2006-08-19 04:52:39 +02:00
|
|
|
}
|
2008-08-25 07:28:50 +02:00
|
|
|
} // if !noscan
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2008-08-25 07:28:50 +02:00
|
|
|
// Make sure that it is really being scanned
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(procedure->prc_flags & PRC_being_scanned);
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
procedure->prc_flags &= ~PRC_being_scanned;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
|
|
|
} // try
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2009-11-07 12:58:54 +01:00
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
procedure->prc_flags &= ~(PRC_being_scanned | PRC_scanned);
|
2011-07-10 03:23:53 +02:00
|
|
|
|
|
|
|
if (procedure->getExternal())
|
|
|
|
{
|
|
|
|
delete procedure->getExternal();
|
|
|
|
procedure->setExternal(NULL);
|
|
|
|
}
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
if (procedure->prc_existence_lock)
|
|
|
|
{
|
|
|
|
LCK_release(tdbb, procedure->prc_existence_lock);
|
2012-07-10 18:08:01 +02:00
|
|
|
delete procedure->prc_existence_lock;
|
2002-11-04 16:12:34 +01:00
|
|
|
procedure->prc_existence_lock = NULL;
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2011-07-10 03:23:53 +02:00
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
throw;
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
return procedure;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
jrd_rel* MET_relation(thread_db* tdbb, USHORT id)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ r e l a t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Find or create a relation block for a given relation id.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
CHECK_DBB(dbb);
|
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
|
|
|
vec<jrd_rel*>* vector = attachment->att_relations;
|
|
|
|
MemoryPool* pool = attachment->att_pool;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
|
|
|
if (!vector)
|
2011-05-09 12:15:19 +02:00
|
|
|
vector = attachment->att_relations = vec<jrd_rel*>::newVector(*pool, id + 10);
|
2001-12-24 03:51:06 +01:00
|
|
|
else if (id >= vector->count())
|
|
|
|
vector->resize(id + 10);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-12-02 08:35:34 +01:00
|
|
|
jrd_rel* relation = (*vector)[id];
|
2011-05-11 03:18:28 +02:00
|
|
|
if (relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
return relation;
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// From ODS 9 onwards, the first 128 relation IDS have been
|
|
|
|
// reserved for system relations
|
2009-11-24 12:42:56 +01:00
|
|
|
const USHORT max_sys_rel = USER_DEF_REL_INIT_ID - 1;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
relation = FB_NEW(*pool) jrd_rel(*pool);
|
2004-02-20 07:43:27 +01:00
|
|
|
(*vector)[id] = relation;
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_id = id;
|
|
|
|
|
2005-07-08 05:25:31 +02:00
|
|
|
{ // Scope block.
|
2012-05-31 18:53:42 +02:00
|
|
|
Lock* lock = FB_NEW_RPT(*pool, 0)
|
2012-06-21 17:37:38 +02:00
|
|
|
Lock(tdbb, sizeof(SLONG), LCK_rel_partners, relation, partners_ast_relation);
|
2005-07-08 05:25:31 +02:00
|
|
|
relation->rel_partners_lock = lock;
|
|
|
|
lock->lck_key.lck_long = relation->rel_id;
|
2005-06-26 23:48:47 +02:00
|
|
|
}
|
|
|
|
|
2010-06-15 14:27:33 +02:00
|
|
|
{ // Scope block.
|
2012-05-31 18:53:42 +02:00
|
|
|
Lock* lock = FB_NEW_RPT(*pool, 0)
|
2012-06-21 17:37:38 +02:00
|
|
|
Lock(tdbb, sizeof(SLONG), LCK_rel_rescan, relation, rescan_ast_relation);
|
2010-06-15 14:27:33 +02:00
|
|
|
relation->rel_rescan_lock = lock;
|
|
|
|
lock->lck_key.lck_long = relation->rel_id;
|
|
|
|
}
|
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
// This should check system flag instead.
|
|
|
|
if (relation->rel_id <= max_sys_rel) {
|
2001-05-23 15:26:42 +02:00
|
|
|
return relation;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-07-08 05:25:31 +02:00
|
|
|
{ // Scope block.
|
2012-05-31 18:53:42 +02:00
|
|
|
Lock* lock = FB_NEW_RPT(*pool, 0)
|
2012-06-21 17:37:38 +02:00
|
|
|
Lock(tdbb, sizeof(SLONG), LCK_rel_exist, relation, blocking_ast_relation);
|
2005-07-08 05:25:31 +02:00
|
|
|
relation->rel_existence_lock = lock;
|
|
|
|
lock->lck_key.lck_long = relation->rel_id;
|
2005-06-26 23:48:47 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-03-04 14:13:19 +01:00
|
|
|
relation->rel_flags |= (REL_check_existence | REL_check_partners);
|
2001-05-23 15:26:42 +02:00
|
|
|
return relation;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-26 14:17:19 +01:00
|
|
|
void MET_release_existence(thread_db* tdbb, jrd_rel* relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ r e l e a s e _ e x i s t e n c e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Release interest in relation. If no remaining interest
|
|
|
|
* and we're blocking the drop of the relation then release
|
|
|
|
* existence lock and mark deleted.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-01-03 11:59:52 +01:00
|
|
|
if (relation->rel_use_count) {
|
|
|
|
relation->rel_use_count--;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (!relation->rel_use_count)
|
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
if (relation->rel_flags & REL_blocking) {
|
2008-01-26 14:17:19 +01:00
|
|
|
LCK_re_post(tdbb, relation->rel_existence_lock);
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2008-12-14 10:28:25 +01:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (relation->rel_file)
|
|
|
|
{
|
2007-03-19 22:34:52 +01:00
|
|
|
// close external file
|
|
|
|
EXT_fini(relation, true);
|
|
|
|
}
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_remove_procedure(thread_db* tdbb, int id, jrd_prc* procedure)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ r e m o v e _ p r o c e d u r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Remove a procedure from cache
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2011-05-09 12:15:19 +02:00
|
|
|
Jrd::Attachment* att = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_prc*>* pvector = att->att_procedures;
|
2011-05-11 03:18:28 +02:00
|
|
|
if (!pvector)
|
2002-09-28 22:58:40 +02:00
|
|
|
return;
|
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (!procedure)
|
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// If we are in here then dfw.epp/modify_procedure() called us
|
2005-12-02 08:35:34 +01:00
|
|
|
if (!(procedure = (*pvector)[id]))
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// MET_procedure locks it. Lets unlock it now to avoid troubles later
|
2002-09-30 20:24:56 +02:00
|
|
|
if (procedure->prc_existence_lock)
|
|
|
|
LCK_release(tdbb, procedure->prc_existence_lock);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Procedure that is being altered may have references
|
|
|
|
// to it by other procedures via pointer to current meta
|
|
|
|
// data structure, so don't loose the structure or the pointer.
|
2008-12-18 11:57:12 +01:00
|
|
|
if ((procedure == (*pvector)[id]) && !(procedure->prc_flags & PRC_being_altered))
|
2005-12-02 08:35:34 +01:00
|
|
|
(*pvector)[id] = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// deallocate all structure which were allocated. The procedure
|
|
|
|
// blr is originally read into a new pool from which all request
|
|
|
|
// are allocated. That will not be freed up.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (procedure->prc_existence_lock)
|
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
delete procedure->prc_existence_lock;
|
2004-04-10 21:03:42 +02:00
|
|
|
procedure->prc_existence_lock = NULL;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// deallocate input param structures
|
2009-12-27 23:05:22 +01:00
|
|
|
|
2011-10-16 22:36:07 +02:00
|
|
|
for (Array<NestConst<Parameter> >::iterator i = procedure->getInputFields().begin();
|
|
|
|
i != procedure->getInputFields().end(); ++i)
|
2009-11-07 12:58:54 +01:00
|
|
|
{
|
2009-12-27 23:05:22 +01:00
|
|
|
if (*i)
|
2010-10-12 13:36:51 +02:00
|
|
|
delete i->getObject();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2011-10-16 22:36:07 +02:00
|
|
|
procedure->getInputFields().clear();
|
2009-12-27 23:05:22 +01:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// deallocate output param structures
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-10-16 22:36:07 +02:00
|
|
|
for (Array<NestConst<Parameter> >::iterator i = procedure->getOutputFields().begin();
|
|
|
|
i != procedure->getOutputFields().end(); ++i)
|
2009-11-07 12:58:54 +01:00
|
|
|
{
|
2009-12-27 23:05:22 +01:00
|
|
|
if (*i)
|
2010-10-12 13:36:51 +02:00
|
|
|
delete i->getObject();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2011-10-16 22:36:07 +02:00
|
|
|
procedure->getOutputFields().clear();
|
2009-12-27 23:05:22 +01:00
|
|
|
|
2006-08-19 04:52:39 +02:00
|
|
|
if (!procedure->prc_use_count)
|
|
|
|
{
|
2013-03-04 02:42:58 +01:00
|
|
|
if (procedure->prc_record_format)
|
2006-08-19 04:52:39 +02:00
|
|
|
{
|
2013-03-04 02:42:58 +01:00
|
|
|
delete procedure->prc_record_format;
|
|
|
|
procedure->prc_record_format = NULL;
|
2006-08-19 04:52:39 +02:00
|
|
|
}
|
2004-04-10 21:03:42 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-06-01 18:22:47 +02:00
|
|
|
if (!(procedure->prc_flags & PRC_being_altered) && !procedure->prc_use_count)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
delete procedure;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-05-28 00:45:31 +02:00
|
|
|
// Fully clear procedure block. Some pieces of code check for empty
|
2004-04-10 21:03:42 +02:00
|
|
|
// procedure name and ID, this is why we do it.
|
2009-12-27 23:05:22 +01:00
|
|
|
procedure->setName(QualifiedName());
|
|
|
|
procedure->setSecurityName("");
|
|
|
|
procedure->setId(0);
|
2011-10-16 22:36:07 +02:00
|
|
|
procedure->setDefaultCount(0);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-09 01:08:58 +01:00
|
|
|
void MET_revoke(thread_db* tdbb, jrd_tra* transaction, const MetaName& relation,
|
|
|
|
const MetaName& revokee, const string& privilege)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ r e v o k e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Execute a recursive revoke. This is called only when
|
|
|
|
* a revoked privilege had the grant option.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// See if the revokee still has the privilege. If so, there's nothing to do
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
USHORT count = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_revoke1, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
|
|
|
FIRST 1 P IN RDB$USER_PRIVILEGES WITH
|
2012-01-08 15:05:29 +01:00
|
|
|
P.RDB$RELATION_NAME EQ relation.c_str() AND
|
|
|
|
P.RDB$PRIVILEGE EQ privilege.c_str() AND
|
|
|
|
P.RDB$USER EQ revokee.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
++count;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (count)
|
|
|
|
return;
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
request.reset(tdbb, irq_revoke2, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// User lost privilege. Take it away from anybody he/she gave it to.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
|
|
|
P IN RDB$USER_PRIVILEGES WITH
|
2012-01-08 15:05:29 +01:00
|
|
|
P.RDB$RELATION_NAME EQ relation.c_str() AND
|
|
|
|
P.RDB$PRIVILEGE EQ privilege.c_str() AND
|
|
|
|
P.RDB$GRANTOR EQ revokee.c_str()
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
ERASE P;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-19 19:33:03 +01:00
|
|
|
void MET_scan_partners(thread_db* tdbb, jrd_rel* relation)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ s c a n _ p a r t n e r s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2010-01-21 03:51:32 +01:00
|
|
|
* Scan of foreign references on other relations' primary keys and
|
2010-01-19 19:33:03 +01:00
|
|
|
* scan of primary dependencies on relation's primary key.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2010-01-21 03:51:32 +01:00
|
|
|
if (relation->rel_flags & REL_check_partners)
|
2010-01-19 19:33:03 +01:00
|
|
|
{
|
|
|
|
scan_partners(tdbb, relation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ s c a n _ r e l a t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2004-03-28 11:10:30 +02:00
|
|
|
* Scan a relation for view RecordSelExpr, computed by expressions, missing
|
2001-05-23 15:26:42 +02:00
|
|
|
* expressions, and validation expressions.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2008-02-05 09:21:18 +01:00
|
|
|
trig_vec* triggers[TRIGGER_MAX];
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2008-02-05 09:21:18 +01:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, dbb->dbb_permanent);
|
|
|
|
bool dependencies = false;
|
|
|
|
bool sys_triggers = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-02-05 09:21:18 +01:00
|
|
|
blb* blob = NULL;
|
|
|
|
|
2010-04-02 23:48:15 +02:00
|
|
|
jrd_tra* depTrans = tdbb->getTransaction() ?
|
|
|
|
tdbb->getTransaction() : attachment->getSysTransaction();
|
2008-07-21 17:49:24 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// If anything errors, catch it to reset the scan flag. This will
|
|
|
|
// make sure that the error will be caught if the operation is tried again.
|
2008-02-05 09:21:18 +01:00
|
|
|
|
|
|
|
try {
|
|
|
|
|
2008-02-06 01:43:54 +01:00
|
|
|
if (relation->rel_flags & REL_scanned || relation->rel_flags & REL_deleted)
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
relation->rel_flags |= REL_being_scanned;
|
2008-02-05 09:21:18 +01:00
|
|
|
dependencies = (relation->rel_flags & REL_get_dependencies) ? true : false;
|
|
|
|
sys_triggers = (relation->rel_flags & REL_sys_triggers) ? true : false;
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_flags &= ~(REL_get_dependencies | REL_sys_triggers);
|
2008-02-06 01:43:54 +01:00
|
|
|
|
2011-05-11 03:18:28 +02:00
|
|
|
for (USHORT itr = 0; itr < TRIGGER_MAX; ++itr)
|
2004-01-03 11:59:52 +01:00
|
|
|
triggers[itr] = NULL;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Since this can be called recursively, find an inactive clone of the request
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_r_fields, IRQ_REQUESTS);
|
2004-03-28 11:10:30 +02:00
|
|
|
CompilerScratch* csb = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
REL IN RDB$RELATIONS WITH REL.RDB$RELATION_ID EQ relation->rel_id
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// Pick up relation level stuff
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_current_fmt = REL.RDB$FORMAT;
|
2005-12-02 08:35:34 +01:00
|
|
|
vec<jrd_fld*>* vector = relation->rel_fields =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<jrd_fld*>::newVector(*relation->rel_pool, relation->rel_fields, REL.RDB$FIELD_ID + 1);
|
2001-12-24 03:51:06 +01:00
|
|
|
if (!REL.RDB$SECURITY_CLASS.NULL) {
|
2005-05-12 20:28:04 +02:00
|
|
|
relation->rel_security_name = REL.RDB$SECURITY_CLASS;
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2008-06-26 12:48:28 +02:00
|
|
|
|
|
|
|
relation->rel_name = REL.RDB$RELATION_NAME;
|
|
|
|
relation->rel_owner_name = REL.RDB$OWNER_NAME;
|
|
|
|
|
2004-01-21 08:18:30 +01:00
|
|
|
if (!REL.RDB$VIEW_BLR.isEmpty())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// parse the view blr, getting dependencies on relations, etc. at the same time
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
DmlNode* rseNode;
|
2010-10-12 13:36:51 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
if (dependencies)
|
|
|
|
{
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName depName(REL.RDB$RELATION_NAME);
|
2010-10-12 13:36:51 +02:00
|
|
|
rseNode = MET_get_dependencies(tdbb, relation, NULL, 0, NULL, &REL.RDB$VIEW_BLR,
|
|
|
|
NULL, &csb, depName, obj_view, 0, depTrans);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
2010-10-12 13:36:51 +02:00
|
|
|
rseNode = MET_parse_blob(tdbb, relation, &REL.RDB$VIEW_BLR, &csb, NULL, false, false);
|
|
|
|
|
|
|
|
if (rseNode)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-12-04 23:15:03 +01:00
|
|
|
fb_assert(rseNode->kind == DmlNode::KIND_REC_SOURCE);
|
|
|
|
relation->rel_view_rse = static_cast<RseNode*>(rseNode);
|
2010-10-12 13:36:51 +02:00
|
|
|
fb_assert(relation->rel_view_rse->type == RseNode::TYPE);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-10-12 13:36:51 +02:00
|
|
|
else
|
|
|
|
relation->rel_view_rse = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// retrieve the view context names
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
lookup_view_contexts(tdbb, relation);
|
|
|
|
}
|
|
|
|
|
|
|
|
relation->rel_flags |= REL_scanned;
|
|
|
|
if (REL.RDB$EXTERNAL_FILE[0])
|
|
|
|
{
|
2009-04-28 15:08:04 +02:00
|
|
|
EXT_file(relation, REL.RDB$EXTERNAL_FILE); //, &REL.RDB$EXTERNAL_DESCRIPTION);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-11-27 07:59:21 +01:00
|
|
|
if (!REL.RDB$RELATION_TYPE.NULL)
|
|
|
|
{
|
|
|
|
switch (REL.RDB$RELATION_TYPE)
|
|
|
|
{
|
|
|
|
case rel_persistent:
|
|
|
|
break;
|
|
|
|
case rel_external:
|
|
|
|
fb_assert(relation->rel_file);
|
|
|
|
break;
|
|
|
|
case rel_view:
|
|
|
|
fb_assert(relation->rel_view_rse);
|
2011-05-31 16:18:27 +02:00
|
|
|
fb_assert(relation->rel_flags & REL_jrd_view);
|
|
|
|
relation->rel_flags |= REL_jrd_view;
|
2009-11-27 07:59:21 +01:00
|
|
|
break;
|
|
|
|
case rel_virtual:
|
2011-05-30 16:26:15 +02:00
|
|
|
fb_assert(relation->rel_flags & REL_virtual);
|
2011-05-31 16:18:27 +02:00
|
|
|
relation->rel_flags |= REL_virtual;
|
2009-11-27 07:59:21 +01:00
|
|
|
break;
|
|
|
|
case rel_global_temp_preserve:
|
2011-05-30 16:26:15 +02:00
|
|
|
fb_assert(relation->rel_flags & REL_temp_conn);
|
2011-05-31 16:18:27 +02:00
|
|
|
relation->rel_flags |= REL_temp_conn;
|
2009-11-27 07:59:21 +01:00
|
|
|
break;
|
|
|
|
case rel_global_temp_delete:
|
2011-05-30 16:26:15 +02:00
|
|
|
fb_assert(relation->rel_flags & REL_temp_tran);
|
2011-05-31 16:18:27 +02:00
|
|
|
relation->rel_flags |= REL_temp_tran;
|
2009-11-27 07:59:21 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Pick up field specific stuff
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2012-02-15 04:34:21 +01:00
|
|
|
blob = blb::open(tdbb, attachment->getSysTransaction(), &REL.RDB$RUNTIME);
|
2010-06-12 18:32:46 +02:00
|
|
|
HalfStaticArray<UCHAR, 256> temp;
|
2012-02-15 08:13:41 +01:00
|
|
|
UCHAR* const buffer = temp.getBuffer(blob->getMaxSegment() + 1U);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-01-25 07:41:50 +01:00
|
|
|
jrd_fld* field = NULL;
|
|
|
|
ArrayField* array = 0;
|
|
|
|
USHORT view_context = 0;
|
|
|
|
USHORT field_id = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (;;)
|
|
|
|
{
|
2012-02-15 08:13:41 +01:00
|
|
|
USHORT length = blob->BLB_get_segment(tdbb, buffer, blob->getMaxSegment());
|
2001-05-23 15:26:42 +02:00
|
|
|
if (blob->blb_flags & BLB_eof)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2004-01-03 11:59:52 +01:00
|
|
|
USHORT n;
|
2001-05-23 15:26:42 +02:00
|
|
|
buffer[length] = 0;
|
2004-01-03 11:59:52 +01:00
|
|
|
UCHAR* p = (UCHAR*) &n;
|
|
|
|
const UCHAR* q = buffer + 1;
|
2001-05-23 15:26:42 +02:00
|
|
|
while (q < buffer + 1 + sizeof(SSHORT))
|
|
|
|
{
|
|
|
|
*p++ = *q++;
|
|
|
|
}
|
|
|
|
p = buffer + 1;
|
|
|
|
--length;
|
2009-04-03 12:07:55 +02:00
|
|
|
switch ((rsr_t) buffer[0])
|
2009-01-20 09:33:59 +01:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
case RSR_field_id:
|
2008-12-18 11:57:12 +01:00
|
|
|
if (field && field->fld_security_name.length() == 0 && !REL.RDB$DEFAULT_CLASS.NULL)
|
2004-02-20 07:43:27 +01:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
field->fld_security_name = REL.RDB$DEFAULT_CLASS;
|
2004-02-20 07:43:27 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
field_id = n;
|
2005-12-02 08:35:34 +01:00
|
|
|
field = (*vector)[field_id];
|
2005-11-21 18:55:04 +01:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (field)
|
|
|
|
{
|
2006-07-23 13:01:20 +02:00
|
|
|
field->fld_computation = NULL;
|
|
|
|
field->fld_missing_value = NULL;
|
|
|
|
field->fld_default_value = NULL;
|
|
|
|
field->fld_validation = NULL;
|
|
|
|
field->fld_not_null = NULL;
|
2005-11-21 18:55:04 +01:00
|
|
|
}
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
array = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_field_name:
|
2009-11-07 12:58:54 +01:00
|
|
|
if (field)
|
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// The field exists. If its name hasn't changed, then
|
|
|
|
// there's no need to copy anything.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
if (field->fld_name == reinterpret_cast<char*>(p))
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
field->fld_name = reinterpret_cast<char*>(p);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-11-07 12:58:54 +01:00
|
|
|
else
|
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
field = FB_NEW(*dbb->dbb_permanent) jrd_fld(*dbb->dbb_permanent);
|
2004-02-20 07:43:27 +01:00
|
|
|
(*vector)[field_id] = field;
|
2005-05-12 20:28:04 +02:00
|
|
|
field->fld_name = reinterpret_cast<char*>(p);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2002-07-01 18:59:09 +02:00
|
|
|
|
2004-03-31 19:59:58 +02:00
|
|
|
// CVC: Be paranoid and allow the possible trigger(s) to have a
|
|
|
|
// not null security class to work on, even if we only take it
|
|
|
|
// from the relation itself.
|
2008-12-18 11:57:12 +01:00
|
|
|
if (field->fld_security_name.length() == 0 && !REL.RDB$DEFAULT_CLASS.NULL)
|
2005-05-22 05:11:41 +02:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
field->fld_security_name = REL.RDB$DEFAULT_CLASS;
|
2004-03-31 19:59:58 +02:00
|
|
|
}
|
2002-07-01 18:59:09 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_view_context:
|
|
|
|
view_context = n;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_base_field:
|
2009-11-07 12:58:54 +01:00
|
|
|
if (dependencies)
|
|
|
|
{
|
2006-01-13 10:33:40 +01:00
|
|
|
csb->csb_g_flags |= csb_get_dependencies;
|
2010-12-04 23:15:03 +01:00
|
|
|
field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p);
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName depName(REL.RDB$RELATION_NAME);
|
2008-12-14 10:28:25 +01:00
|
|
|
store_dependencies(tdbb, csb, 0, depName, obj_view, depTrans);
|
2006-01-13 10:33:40 +01:00
|
|
|
}
|
2010-11-21 04:47:29 +01:00
|
|
|
else
|
2010-12-04 23:15:03 +01:00
|
|
|
field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_computed_blr:
|
2010-11-21 04:47:29 +01:00
|
|
|
{
|
2010-12-04 23:15:03 +01:00
|
|
|
DmlNode* nod = dependencies ?
|
2010-11-21 04:47:29 +01:00
|
|
|
MET_get_dependencies(tdbb, relation, p, length, csb, NULL, NULL, NULL,
|
|
|
|
field->fld_name, obj_computed, 0, depTrans) :
|
|
|
|
PAR_blr(tdbb, relation, p, length, csb, NULL, NULL, false, 0);
|
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
field->fld_computation = static_cast<ValueExprNode*>(nod);
|
2010-11-21 04:47:29 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_missing_value:
|
2010-12-04 23:15:03 +01:00
|
|
|
field->fld_missing_value = static_cast<ValueExprNode*>(
|
|
|
|
PAR_blr(tdbb, relation, p, length, csb, NULL, NULL, false, 0));
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_default_value:
|
2010-12-04 23:15:03 +01:00
|
|
|
field->fld_default_value = static_cast<ValueExprNode*>(
|
|
|
|
PAR_blr(tdbb, relation, p, length, csb, NULL, NULL, false, 0));
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_validation_blr:
|
2005-04-25 08:54:45 +02:00
|
|
|
// AB: 2005-04-25 bug SF#1168898
|
|
|
|
// Ignore validation for VIEWs, because fields (domains) which are
|
|
|
|
// defined with CHECK constraints and have sub-selects should at least
|
2005-05-28 00:45:31 +02:00
|
|
|
// be parsed without view-context information. With view-context
|
2005-04-25 08:54:45 +02:00
|
|
|
// information the context-numbers are wrong.
|
|
|
|
// Because a VIEW can't have a validation section i ignored the whole call.
|
2005-05-28 00:45:31 +02:00
|
|
|
if (!csb)
|
2005-04-24 20:32:16 +02:00
|
|
|
{
|
2013-03-31 20:23:54 +02:00
|
|
|
field->fld_validation = PAR_validation_blr(tdbb, relation, p, length, csb,
|
|
|
|
NULL, csb_validation);
|
2005-04-24 20:32:16 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_field_not_null:
|
2013-03-31 20:23:54 +02:00
|
|
|
field->fld_not_null = PAR_validation_blr(tdbb, relation, p, length, csb,
|
|
|
|
NULL, csb_validation);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_security_class:
|
2005-05-12 20:28:04 +02:00
|
|
|
field->fld_security_name = (const TEXT*) p;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_trigger_name:
|
2004-03-11 06:04:26 +01:00
|
|
|
MET_load_trigger(tdbb, relation, (const TEXT*) p, triggers);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_dimensions:
|
2004-03-19 07:14:53 +01:00
|
|
|
field->fld_array = array = FB_NEW_RPT(*dbb->dbb_permanent, n) ArrayField();
|
|
|
|
array->arr_desc.iad_dimensions = n;
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RSR_array_desc:
|
|
|
|
if (array)
|
2008-02-03 11:41:44 +01:00
|
|
|
memcpy(&array->arr_desc, p, length);
|
2001-05-23 15:26:42 +02:00
|
|
|
break;
|
2004-03-11 06:04:26 +01:00
|
|
|
|
2010-01-13 20:14:15 +01:00
|
|
|
case RSR_field_generator_name:
|
|
|
|
field->fld_generator_name = (const TEXT*) p;
|
|
|
|
break;
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
default: // Shut up compiler warning
|
2004-03-11 06:04:26 +01:00
|
|
|
break;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
2012-02-07 04:17:52 +01:00
|
|
|
blob->BLB_close(tdbb);
|
2005-01-25 07:41:50 +01:00
|
|
|
blob = 0;
|
2009-11-27 07:59:21 +01:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
if (field && field->fld_security_name.length() == 0 && !REL.RDB$DEFAULT_CLASS.NULL)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
field->fld_security_name = REL.RDB$DEFAULT_CLASS;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2005-04-28 08:12:08 +02:00
|
|
|
|
|
|
|
delete csb;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// release any triggers in case of a rescan, but not if the rescan
|
|
|
|
// hapenned while system triggers were being loaded.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-07 12:58:54 +01:00
|
|
|
if (!(relation->rel_flags & REL_sys_trigs_being_loaded))
|
|
|
|
{
|
2009-11-21 04:23:47 +01:00
|
|
|
// if we are scanning a system relation during loading the system
|
|
|
|
// triggers, (during parsing its blr actually), we must not release the
|
|
|
|
// existing system triggers; because we have already set the
|
|
|
|
// relation->rel_flag to not have REL_sys_trig, so these
|
|
|
|
// system triggers will not get loaded again. This fixes bug 8149.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// We have just loaded the triggers onto the local vector triggers.
|
|
|
|
// Its now time to place them at their rightful place ie the relation block.
|
2009-11-19 10:52:30 +01:00
|
|
|
|
2004-01-03 11:59:52 +01:00
|
|
|
trig_vec* tmp_vector;
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
tmp_vector = relation->rel_pre_store;
|
|
|
|
relation->rel_pre_store = triggers[TRIGGER_PRE_STORE];
|
|
|
|
MET_release_triggers(tdbb, &tmp_vector);
|
|
|
|
|
|
|
|
tmp_vector = relation->rel_post_store;
|
|
|
|
relation->rel_post_store = triggers[TRIGGER_POST_STORE];
|
|
|
|
MET_release_triggers(tdbb, &tmp_vector);
|
|
|
|
|
|
|
|
tmp_vector = relation->rel_pre_erase;
|
|
|
|
relation->rel_pre_erase = triggers[TRIGGER_PRE_ERASE];
|
|
|
|
MET_release_triggers(tdbb, &tmp_vector);
|
|
|
|
|
|
|
|
tmp_vector = relation->rel_post_erase;
|
|
|
|
relation->rel_post_erase = triggers[TRIGGER_POST_ERASE];
|
|
|
|
MET_release_triggers(tdbb, &tmp_vector);
|
|
|
|
|
|
|
|
tmp_vector = relation->rel_pre_modify;
|
|
|
|
relation->rel_pre_modify = triggers[TRIGGER_PRE_MODIFY];
|
|
|
|
MET_release_triggers(tdbb, &tmp_vector);
|
|
|
|
|
|
|
|
tmp_vector = relation->rel_post_modify;
|
|
|
|
relation->rel_post_modify = triggers[TRIGGER_POST_MODIFY];
|
|
|
|
MET_release_triggers(tdbb, &tmp_vector);
|
|
|
|
}
|
|
|
|
|
2010-06-15 14:27:33 +02:00
|
|
|
LCK_lock(tdbb, relation->rel_rescan_lock, LCK_SR, LCK_WAIT);
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_flags &= ~REL_being_scanned;
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
relation->rel_current_format = NULL;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
|
|
|
} // try
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2009-11-07 12:58:54 +01:00
|
|
|
{
|
2001-12-24 03:51:06 +01:00
|
|
|
relation->rel_flags &= ~(REL_being_scanned | REL_scanned);
|
|
|
|
if (dependencies) {
|
|
|
|
relation->rel_flags |= REL_get_dependencies;
|
|
|
|
}
|
|
|
|
if (sys_triggers) {
|
|
|
|
relation->rel_flags |= REL_sys_triggers;
|
|
|
|
}
|
2005-01-25 07:41:50 +01:00
|
|
|
if (blob)
|
2012-02-07 04:17:52 +01:00
|
|
|
blob->BLB_close(tdbb);
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
throw;
|
2001-12-24 03:51:06 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
void MET_trigger_msg(thread_db* tdbb, string& msg, const MetaName& name,
|
2009-11-21 06:20:18 +01:00
|
|
|
USHORT number)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ t r i g g e r _ m s g
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Look up trigger message using trigger and abort code.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_s_msgs, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
MSG IN RDB$TRIGGER_MESSAGES WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
MSG.RDB$TRIGGER_NAME EQ name.c_str() AND
|
2005-05-28 00:45:31 +02:00
|
|
|
MSG.RDB$MESSAGE_NUMBER EQ number
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2008-08-27 14:20:47 +02:00
|
|
|
msg = MSG.RDB$MESSAGE;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-09-03 13:23:00 +02:00
|
|
|
msg.rtrim();
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_update_shadow(thread_db* tdbb, Shadow* shadow, USHORT file_flags)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ u p d a t e _ s h a d o w
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Update the stored file flags for the specified shadow.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle;
|
2010-04-23 03:59:21 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
FIL IN RDB$FILES WITH FIL.RDB$SHADOW_NUMBER EQ shadow->sdw_number
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
MODIFY FIL USING
|
|
|
|
FIL.RDB$FILE_FLAGS = file_flags;
|
2010-04-18 17:04:52 +02:00
|
|
|
END_MODIFY
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 12:48:28 +02:00
|
|
|
void MET_update_transaction(thread_db* tdbb, jrd_tra* transaction, const bool do_commit)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* M E T _ u p d a t e _ t r a n s a c t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2003-12-22 11:00:59 +01:00
|
|
|
* Update a record in RDB$TRANSACTIONS. If do_commit is true, this is a
|
2001-05-23 15:26:42 +02:00
|
|
|
* commit; otherwise it is a ROLLBACK.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_m_trans, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
2005-05-28 00:45:31 +02:00
|
|
|
X IN RDB$TRANSACTIONS
|
2008-12-18 11:57:12 +01:00
|
|
|
WITH X.RDB$TRANSACTION_ID EQ transaction->tra_number
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2003-12-22 11:00:59 +01:00
|
|
|
if (do_commit && (transaction->tra_flags & TRA_prepare2))
|
2001-05-23 15:26:42 +02:00
|
|
|
ERASE X
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MODIFY X
|
2009-02-28 12:57:40 +01:00
|
|
|
X.RDB$TRANSACTION_STATE = do_commit ?
|
2001-05-23 15:26:42 +02:00
|
|
|
RDB$TRANSACTIONS.RDB$TRANSACTION_STATE.COMMITTED :
|
|
|
|
RDB$TRANSACTIONS.RDB$TRANSACTION_STATE.ROLLED_BACK;
|
2010-04-18 17:04:52 +02:00
|
|
|
END_MODIFY
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-01 20:14:46 +01:00
|
|
|
static int blocking_ast_dsql_cache(void* ast_object)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* b l o c k i n g _ a s t _ d s q l _ c a c h e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2008-03-02 08:35:37 +01:00
|
|
|
* Someone is trying to drop an item from the DSQL cache.
|
2008-03-01 20:14:46 +01:00
|
|
|
* Mark the symbol as obsolete and release the lock.
|
|
|
|
*
|
|
|
|
**************************************/
|
2011-10-18 20:02:57 +02:00
|
|
|
DSqlCacheItem* const item = static_cast<DSqlCacheItem*>(ast_object);
|
2008-03-01 20:14:46 +01:00
|
|
|
|
2008-03-12 17:53:57 +01:00
|
|
|
try
|
|
|
|
{
|
2011-10-18 20:02:57 +02:00
|
|
|
Database* const dbb = item->lock->lck_dbb;
|
2008-03-01 20:14:46 +01:00
|
|
|
|
2012-12-20 13:18:52 +01:00
|
|
|
AsyncContextHolder tdbb(dbb, FB_FUNCTION, item->lock);
|
2008-03-12 17:53:57 +01:00
|
|
|
|
|
|
|
item->obsolete = true;
|
|
|
|
item->locked = false;
|
|
|
|
LCK_release(tdbb, item->lock);
|
|
|
|
}
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2008-03-12 17:53:57 +01:00
|
|
|
{} // no-op
|
2008-03-01 20:14:46 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
static DSqlCacheItem* get_dsql_cache_item(thread_db* tdbb, int type, const QualifiedName& name)
|
2008-03-01 20:14:46 +01:00
|
|
|
{
|
|
|
|
Database* dbb = tdbb->getDatabase();
|
2009-10-21 02:42:38 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2008-03-01 20:14:46 +01:00
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
string key((char*) &type, sizeof(type));
|
2009-10-21 02:42:38 +02:00
|
|
|
int len = name.identifier.length();
|
|
|
|
key.append((char*) &len, sizeof(len));
|
2010-01-30 10:58:01 +01:00
|
|
|
key.append(name.identifier.c_str(), len);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2010-01-27 05:32:27 +01:00
|
|
|
len = name.package.length();
|
2009-10-21 02:42:38 +02:00
|
|
|
key.append((char*) &len, sizeof(len));
|
2010-01-30 10:58:01 +01:00
|
|
|
key.append(name.package.c_str(), len);
|
2008-03-01 20:14:46 +01:00
|
|
|
|
|
|
|
DSqlCacheItem* item = attachment->att_dsql_cache.put(key);
|
|
|
|
if (item)
|
|
|
|
{
|
|
|
|
item->obsolete = false;
|
|
|
|
item->locked = false;
|
2012-05-31 18:53:42 +02:00
|
|
|
item->lock = FB_NEW_RPT(*dbb->dbb_permanent, key.length())
|
2012-06-21 17:37:38 +02:00
|
|
|
Lock(tdbb, key.length(), LCK_dsql_cache, item, blocking_ast_dsql_cache);
|
2008-03-01 20:14:46 +01:00
|
|
|
memcpy(item->lock->lck_key.lck_string, key.c_str(), key.length());
|
|
|
|
}
|
|
|
|
else
|
2008-12-19 15:57:01 +01:00
|
|
|
{
|
|
|
|
item = attachment->att_dsql_cache.get(key);
|
|
|
|
}
|
2008-03-01 20:14:46 +01:00
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-31 06:36:12 +01:00
|
|
|
static int blocking_ast_procedure(void* ast_object)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* b l o c k i n g _ a s t _ p r o c e d u r e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Someone is trying to drop a proceedure. If there
|
|
|
|
* are outstanding interests in the existence of
|
|
|
|
* the relation then just mark as blocking and return.
|
|
|
|
* Otherwise, mark the procedure block as questionable
|
|
|
|
* and release the procedure existence lock.
|
|
|
|
*
|
|
|
|
**************************************/
|
2011-10-18 20:02:57 +02:00
|
|
|
jrd_prc* const procedure = static_cast<jrd_prc*>(ast_object);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-03-12 17:53:57 +01:00
|
|
|
try
|
|
|
|
{
|
2011-10-18 20:02:57 +02:00
|
|
|
Database* const dbb = procedure->prc_existence_lock->lck_dbb;
|
2008-12-14 10:28:25 +01:00
|
|
|
|
2012-12-20 13:18:52 +01:00
|
|
|
AsyncContextHolder tdbb(dbb, FB_FUNCTION, procedure->prc_existence_lock);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-05-11 03:18:28 +02:00
|
|
|
if (procedure->prc_existence_lock)
|
2008-03-12 17:53:57 +01:00
|
|
|
LCK_release(tdbb, procedure->prc_existence_lock);
|
2011-05-11 03:18:28 +02:00
|
|
|
|
2008-03-12 17:53:57 +01:00
|
|
|
procedure->prc_flags |= PRC_obsolete;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2008-03-12 17:53:57 +01:00
|
|
|
{} // no-op
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-05-19 08:57:08 +02:00
|
|
|
return 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-16 22:35:19 +02:00
|
|
|
static int blocking_ast_relation(void* ast_object)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* b l o c k i n g _ a s t _ r e l a t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Someone is trying to drop a relation. If there
|
|
|
|
* are outstanding interests in the existence of
|
|
|
|
* the relation then just mark as blocking and return.
|
|
|
|
* Otherwise, mark the relation block as questionable
|
|
|
|
* and release the relation existence lock.
|
|
|
|
*
|
|
|
|
**************************************/
|
2011-10-18 20:02:57 +02:00
|
|
|
jrd_rel* const relation = static_cast<jrd_rel*>(ast_object);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-03-12 17:53:57 +01:00
|
|
|
try
|
|
|
|
{
|
2011-10-18 20:02:57 +02:00
|
|
|
Database* const dbb = relation->rel_existence_lock->lck_dbb;
|
2008-12-14 10:28:25 +01:00
|
|
|
|
2012-12-20 13:18:52 +01:00
|
|
|
AsyncContextHolder tdbb(dbb, FB_FUNCTION, relation->rel_existence_lock);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-05-11 03:18:28 +02:00
|
|
|
if (relation->rel_use_count)
|
2008-03-12 17:53:57 +01:00
|
|
|
relation->rel_flags |= REL_blocking;
|
2009-11-07 12:58:54 +01:00
|
|
|
else
|
|
|
|
{
|
2008-03-12 17:53:57 +01:00
|
|
|
relation->rel_flags &= ~REL_blocking;
|
|
|
|
relation->rel_flags |= REL_check_existence;
|
|
|
|
if (relation->rel_existence_lock)
|
|
|
|
LCK_release(tdbb, relation->rel_existence_lock);
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2008-03-12 17:53:57 +01:00
|
|
|
{} // no-op
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-28 00:45:31 +02:00
|
|
|
return 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-26 23:48:47 +02:00
|
|
|
static int partners_ast_relation(void* ast_object)
|
|
|
|
{
|
2011-10-18 20:02:57 +02:00
|
|
|
jrd_rel* const relation = static_cast<jrd_rel*>(ast_object);
|
2005-06-26 23:48:47 +02:00
|
|
|
|
2008-03-12 17:53:57 +01:00
|
|
|
try
|
|
|
|
{
|
2011-10-18 20:02:57 +02:00
|
|
|
Database* const dbb = relation->rel_partners_lock->lck_dbb;
|
2005-06-26 23:48:47 +02:00
|
|
|
|
2012-12-20 13:18:52 +01:00
|
|
|
AsyncContextHolder tdbb(dbb, FB_FUNCTION, relation->rel_partners_lock);
|
2005-06-26 23:48:47 +02:00
|
|
|
|
2008-03-12 17:53:57 +01:00
|
|
|
LCK_release(tdbb, relation->rel_partners_lock);
|
|
|
|
relation->rel_flags |= REL_check_partners;
|
|
|
|
}
|
2010-06-12 18:32:46 +02:00
|
|
|
catch (const Exception&)
|
2008-03-12 17:53:57 +01:00
|
|
|
{} // no-op
|
2005-06-26 23:48:47 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-15 14:27:33 +02:00
|
|
|
static int rescan_ast_relation(void* ast_object)
|
|
|
|
{
|
2011-10-18 20:02:57 +02:00
|
|
|
jrd_rel* const relation = static_cast<jrd_rel*>(ast_object);
|
2010-06-15 14:27:33 +02:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2011-10-18 20:02:57 +02:00
|
|
|
Database* const dbb = relation->rel_rescan_lock->lck_dbb;
|
2010-06-15 14:27:33 +02:00
|
|
|
|
2012-12-20 13:18:52 +01:00
|
|
|
AsyncContextHolder tdbb(dbb, FB_FUNCTION, relation->rel_rescan_lock);
|
2010-06-15 14:27:33 +02:00
|
|
|
|
|
|
|
LCK_release(tdbb, relation->rel_rescan_lock);
|
|
|
|
relation->rel_flags &= ~REL_scanned;
|
|
|
|
}
|
|
|
|
catch (const Firebird::Exception&)
|
|
|
|
{} // no-op
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-30 16:26:15 +02:00
|
|
|
static ULONG get_rel_flags_from_FLAGS(USHORT flags)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g e t _ r e l _ f l a g s _ f r o m _ F L A G S
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get rel_flags from RDB$FLAGS
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
ULONG ret = 0;
|
|
|
|
|
|
|
|
if (flags & REL_sql) {
|
|
|
|
ret |= REL_sql_relation;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-31 16:18:27 +02:00
|
|
|
ULONG MET_get_rel_flags_from_TYPE(USHORT type)
|
2011-05-30 16:26:15 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2011-05-31 16:18:27 +02:00
|
|
|
* M E T _g e t _ r e l _ f l a g s _ f r o m _ T Y P E
|
2011-05-30 16:26:15 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get rel_flags from RDB$RELATION_TYPE
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
ULONG ret = 0;
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case rel_persistent:
|
|
|
|
break;
|
|
|
|
case rel_external:
|
|
|
|
break;
|
|
|
|
case rel_view:
|
|
|
|
ret |= REL_jrd_view;
|
|
|
|
break;
|
|
|
|
case rel_virtual:
|
|
|
|
ret |= REL_virtual;
|
|
|
|
break;
|
|
|
|
case rel_global_temp_preserve:
|
|
|
|
ret |= REL_temp_conn;
|
|
|
|
break;
|
|
|
|
case rel_global_temp_delete:
|
|
|
|
ret |= REL_temp_tran;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fb_assert(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-28 23:52:55 +02:00
|
|
|
static void get_trigger(thread_db* tdbb, jrd_rel* relation,
|
2006-10-30 21:58:06 +01:00
|
|
|
bid* blob_id, bid* debug_blob_id, trig_vec** ptr,
|
2009-10-21 02:42:38 +02:00
|
|
|
const TEXT* name, FB_UINT64 type,
|
|
|
|
bool sys_trigger, USHORT flags,
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName& engine, const string& entryPoint,
|
2009-10-21 02:42:38 +02:00
|
|
|
const bid* body)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g e t _ t r i g g e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Get trigger.
|
|
|
|
*
|
|
|
|
**************************************/
|
2002-09-19 18:02:58 +02:00
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2004-01-03 11:59:52 +01:00
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
if (blob_id->isEmpty() && (engine.isEmpty() || entryPoint.isEmpty()))
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
blb* blrBlob = NULL;
|
|
|
|
|
|
|
|
if (!blob_id->isEmpty())
|
2012-02-15 04:34:21 +01:00
|
|
|
blrBlob = blb::open(tdbb, attachment->getSysTransaction(), blob_id);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2006-10-30 21:58:06 +01:00
|
|
|
save_trigger_data(tdbb, ptr, relation, NULL, blrBlob, debug_blob_id,
|
2009-10-21 02:42:38 +02:00
|
|
|
name, type, sys_trigger, flags, engine, entryPoint, body);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-05 18:34:18 +02:00
|
|
|
static bool get_type(thread_db* tdbb, USHORT* id, const UCHAR* name, const TEXT* field)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* g e t _ t y p e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Resoved a symbolic name in RDB$TYPES. Returned the value
|
|
|
|
* defined for the name in (*id). Don't touch (*id) if you
|
|
|
|
* don't find the name.
|
|
|
|
*
|
|
|
|
* Return (1) if found, (0) otherwise.
|
|
|
|
*
|
|
|
|
**************************************/
|
2009-11-19 10:52:30 +01:00
|
|
|
UCHAR buffer[MAX_SQL_IDENTIFIER_SIZE]; // BASED ON RDB$TYPE_NAME
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(id != NULL);
|
|
|
|
fb_assert(name != NULL);
|
|
|
|
fb_assert(field != NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Force key to uppercase, following C locale rules for uppercase
|
2003-12-11 11:33:30 +01:00
|
|
|
UCHAR* p;
|
2001-05-23 15:26:42 +02:00
|
|
|
for (p = buffer; *name && p < buffer + sizeof(buffer) - 1; p++, name++)
|
|
|
|
{
|
|
|
|
*p = UPPER7(*name);
|
|
|
|
}
|
|
|
|
*p = 0;
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Try for exact name match
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-11 11:33:30 +01:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle;
|
2010-04-23 03:59:21 +02:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
FIRST 1 T IN RDB$TYPES WITH
|
2002-12-22 14:08:50 +01:00
|
|
|
T.RDB$FIELD_NAME EQ field AND
|
|
|
|
T.RDB$TYPE_NAME EQ buffer
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
found = true;
|
2001-05-23 15:26:42 +02:00
|
|
|
*id = T.RDB$TYPE;
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static void lookup_view_contexts( thread_db* tdbb, jrd_rel* view)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* l o o k u p _ v i e w _ c o n t e x t s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2005-05-28 00:45:31 +02:00
|
|
|
* Lookup view contexts and store in a linked
|
2001-05-23 15:26:42 +02:00
|
|
|
* list on the relation block.
|
2005-05-28 00:45:31 +02:00
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2007-12-03 16:46:39 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_view_context, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
V IN RDB$VIEW_RELATIONS WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
V.RDB$VIEW_NAME EQ view->rel_name.c_str()
|
2005-05-28 00:45:31 +02:00
|
|
|
SORTED BY V.RDB$VIEW_CONTEXT
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2008-12-14 10:28:25 +01:00
|
|
|
// trim trailing spaces
|
2008-12-18 11:57:12 +01:00
|
|
|
fb_utils::exact_name_limit(V.RDB$CONTEXT_NAME, sizeof(V.RDB$CONTEXT_NAME));
|
2008-05-11 23:27:21 +02:00
|
|
|
|
2008-05-13 03:29:38 +02:00
|
|
|
ViewContext* view_context = FB_NEW(*dbb->dbb_permanent)
|
|
|
|
ViewContext(*dbb->dbb_permanent,
|
2009-12-17 16:07:02 +01:00
|
|
|
V.RDB$CONTEXT_NAME, V.RDB$RELATION_NAME, V.RDB$VIEW_CONTEXT,
|
|
|
|
(V.RDB$CONTEXT_TYPE.NULL ? VCT_TABLE : ViewContextType(V.RDB$CONTEXT_TYPE)));
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
view->rel_view_contexts.add(view_context);
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-21 06:20:18 +01:00
|
|
|
static void make_relation_scope_name(const TEXT* rel_name, const USHORT rel_flags,
|
2010-06-12 18:32:46 +02:00
|
|
|
string& str)
|
2006-05-24 22:43:07 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* m a k e _ r e l a t i o n _ s c o p e _ n a m e
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2008-12-14 10:28:25 +01:00
|
|
|
* Make string with relation name and type
|
2006-05-24 22:43:07 +02:00
|
|
|
* of its temporary scope
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
const char *scope = NULL;
|
|
|
|
if (rel_flags & REL_temp_conn)
|
|
|
|
scope = REL_SCOPE_GTT_PRESERVE;
|
|
|
|
else if (rel_flags & REL_temp_tran)
|
|
|
|
scope = REL_SCOPE_GTT_DELETE;
|
|
|
|
else
|
|
|
|
scope = REL_SCOPE_PERSISTENT;
|
|
|
|
|
|
|
|
str.printf(scope, rel_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-07 21:26:11 +01:00
|
|
|
// Parses default BLR for a field.
|
2010-12-04 23:15:03 +01:00
|
|
|
static ValueExprNode* parse_field_default_blr(thread_db* tdbb, bid* blob_id)
|
2008-01-16 10:29:37 +01:00
|
|
|
{
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2010-11-07 21:26:11 +01:00
|
|
|
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5);
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::open(tdbb, attachment->getSysTransaction(), blob_id);
|
2013-01-25 13:34:19 +01:00
|
|
|
ULONG length = blob->blb_length + 10;
|
2010-06-12 18:32:46 +02:00
|
|
|
HalfStaticArray<UCHAR, 512> temp;
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2012-02-07 04:17:52 +01:00
|
|
|
length = blob->BLB_get_data(tdbb, temp.getBuffer(length), length);
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
DmlNode* node = PAR_blr(tdbb, NULL, temp.begin(), length, NULL, &csb, NULL, false, 0);
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2009-08-02 06:10:07 +02:00
|
|
|
csb->csb_blr_reader = BlrReader();
|
2008-01-16 10:29:37 +01:00
|
|
|
delete csb;
|
|
|
|
|
2010-12-04 23:15:03 +01:00
|
|
|
return static_cast<ValueExprNode*>(node);
|
2008-01-16 10:29:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-07 21:26:11 +01:00
|
|
|
// Parses validation BLR for a field.
|
2013-03-31 20:23:54 +02:00
|
|
|
static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, const MetaName name)
|
2010-11-07 21:26:11 +01:00
|
|
|
{
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
|
|
|
|
|
|
|
CompilerScratch* csb = CompilerScratch::newCsb(*tdbb->getDefaultPool(), 5, name);
|
|
|
|
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* blob = blb::open(tdbb, attachment->getSysTransaction(), blob_id);
|
2013-01-25 13:34:19 +01:00
|
|
|
ULONG length = blob->blb_length + 10;
|
2010-11-07 21:26:11 +01:00
|
|
|
HalfStaticArray<UCHAR, 512> temp;
|
|
|
|
|
2012-02-07 04:17:52 +01:00
|
|
|
length = blob->BLB_get_data(tdbb, temp.getBuffer(length), length);
|
2010-11-07 21:26:11 +01:00
|
|
|
|
2013-03-31 20:23:54 +02:00
|
|
|
BoolExprNode* expr = PAR_validation_blr(tdbb, NULL,
|
|
|
|
temp.begin(), length, NULL, &csb, 0);
|
2010-11-07 21:26:11 +01:00
|
|
|
|
|
|
|
csb->csb_blr_reader = BlrReader();
|
|
|
|
delete csb;
|
2013-03-31 20:23:54 +02:00
|
|
|
|
|
|
|
return expr;
|
2010-11-07 21:26:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
void MET_release_trigger(thread_db* tdbb, trig_vec** vector_ptr, const MetaName& name)
|
2006-11-05 19:30:36 +01:00
|
|
|
{
|
|
|
|
/***********************************************
|
|
|
|
*
|
|
|
|
* M E T _ r e l e a s e _ t r i g g e r
|
|
|
|
*
|
|
|
|
***********************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Release a specified trigger.
|
|
|
|
* If trigger are still active let someone
|
|
|
|
* else do the work.
|
|
|
|
*
|
|
|
|
**************************************/
|
2006-11-11 01:52:31 +01:00
|
|
|
if (!*vector_ptr)
|
2006-11-05 19:30:36 +01:00
|
|
|
return;
|
|
|
|
|
2006-11-11 01:52:31 +01:00
|
|
|
trig_vec& vector = **vector_ptr;
|
2006-11-05 19:30:36 +01:00
|
|
|
|
2006-11-11 01:52:31 +01:00
|
|
|
SET_TDBB(tdbb);
|
2006-11-05 19:30:36 +01:00
|
|
|
|
2006-11-11 01:52:31 +01:00
|
|
|
for (size_t i = 0; i < vector.getCount(); ++i)
|
2006-11-05 19:30:36 +01:00
|
|
|
{
|
2006-11-11 01:52:31 +01:00
|
|
|
if (vector[i].name == name)
|
2006-11-05 19:30:36 +01:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement* stmt = vector[i].statement;
|
|
|
|
if (stmt)
|
2006-11-11 01:52:31 +01:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
if (stmt->isActive())
|
2006-11-11 01:52:31 +01:00
|
|
|
break;
|
2010-04-19 00:19:11 +02:00
|
|
|
stmt->release(tdbb);
|
2006-11-11 01:52:31 +01:00
|
|
|
}
|
|
|
|
vector.remove(i);
|
2006-11-05 19:30:36 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
void MET_release_triggers( thread_db* tdbb, trig_vec** vector_ptr)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/***********************************************
|
|
|
|
*
|
|
|
|
* M E T _ r e l e a s e _ t r i g g e r s
|
|
|
|
*
|
|
|
|
***********************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Release a possibly null vector of triggers.
|
|
|
|
* If triggers are still active let someone
|
|
|
|
* else do the work.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-12-22 11:00:59 +01:00
|
|
|
trig_vec* vector = *vector_ptr;
|
2005-05-28 00:45:31 +02:00
|
|
|
if (!vector)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
|
|
|
*vector_ptr = NULL;
|
|
|
|
|
2009-06-27 08:23:36 +02:00
|
|
|
for (size_t i = 0; i < vector->getCount(); i++)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement* stmt = (*vector)[i].statement;
|
|
|
|
if (stmt && stmt->isActive())
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-06-27 08:23:36 +02:00
|
|
|
for (size_t i = 0; i < vector->getCount(); i++)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement* stmt = (*vector)[i].statement;
|
|
|
|
if (stmt)
|
|
|
|
stmt->release(tdbb);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
delete (*vector)[i].extTrigger;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
delete vector;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
static bool resolve_charset_and_collation(thread_db* tdbb,
|
|
|
|
USHORT* id,
|
|
|
|
const UCHAR* charset,
|
|
|
|
const UCHAR* collation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* r e s o l v e _ c h a r s e t _ a n d _ c o l l a t i o n
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Given ASCII7 name of charset & collation
|
|
|
|
* resolve the specification to a Character set id.
|
|
|
|
* This character set id is also the id of the text_object
|
|
|
|
* that implements the C locale for the Character set.
|
|
|
|
*
|
|
|
|
* Inputs:
|
|
|
|
* (charset)
|
|
|
|
* ASCII7z name of character set.
|
|
|
|
* NULL (implying unspecified) means use the character set
|
|
|
|
* for defined for (collation).
|
|
|
|
*
|
|
|
|
* (collation)
|
|
|
|
* ASCII7z name of collation.
|
|
|
|
* NULL means use the default collation for (charset).
|
|
|
|
*
|
|
|
|
* Outputs:
|
2005-05-28 00:45:31 +02:00
|
|
|
* (*id)
|
2005-06-06 10:30:03 +02:00
|
|
|
* Set to character set specified by this name (low byte)
|
|
|
|
* Set to collation specified by this name (high byte).
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
* Return:
|
2005-06-06 10:30:03 +02:00
|
|
|
* true if no errors (and *id is set).
|
|
|
|
* false if either name not found.
|
2001-05-23 15:26:42 +02:00
|
|
|
* or if names found, but the collation isn't for the specified
|
|
|
|
* character set.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-03-11 06:04:26 +01:00
|
|
|
bool found = false;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(id != NULL);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-20 00:49:18 +02:00
|
|
|
AutoRequest handle;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-23 03:59:21 +02:00
|
|
|
if (!collation)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
if (charset == NULL)
|
2003-12-11 11:33:30 +01:00
|
|
|
charset = (const UCHAR*) DEFAULT_CHARACTER_SET_NAME;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2011-05-09 12:15:19 +02:00
|
|
|
if (attachment->att_charset_ids.get((const TEXT*) charset, *id))
|
2009-10-21 02:42:38 +02:00
|
|
|
return true;
|
|
|
|
|
2006-04-05 18:34:18 +02:00
|
|
|
USHORT charset_id = 0;
|
2003-12-11 11:33:30 +01:00
|
|
|
if (get_type(tdbb, &charset_id, charset, "RDB$CHARACTER_SET_NAME"))
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->att_charset_ids.put((const TEXT*) charset, charset_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
*id = charset_id;
|
2004-03-11 06:04:26 +01:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2009-11-21 04:23:47 +01:00
|
|
|
// Charset name not found in the alias table - before giving up
|
|
|
|
// try the character_set table
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
FIRST 1 CS IN RDB$CHARACTER_SETS
|
2002-12-22 14:08:50 +01:00
|
|
|
WITH CS.RDB$CHARACTER_SET_NAME EQ charset
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2009-10-21 02:42:38 +02:00
|
|
|
found = true;
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->att_charset_ids.put((const TEXT*) charset, CS.RDB$CHARACTER_SET_ID);
|
2001-05-23 15:26:42 +02:00
|
|
|
*id = CS.RDB$CHARACTER_SET_ID;
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
2008-01-16 10:29:37 +01:00
|
|
|
|
2010-04-23 03:59:21 +02:00
|
|
|
if (!charset)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
FIRST 1 COL IN RDB$COLLATIONS
|
2002-12-22 14:08:50 +01:00
|
|
|
WITH COL.RDB$COLLATION_NAME EQ collation
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
found = true;
|
2005-05-28 00:45:31 +02:00
|
|
|
*id = COL.RDB$CHARACTER_SET_ID | (COL.RDB$COLLATION_ID << 8);
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE handle)
|
|
|
|
FIRST 1 CS IN RDB$CHARACTER_SETS CROSS
|
|
|
|
COL IN RDB$COLLATIONS OVER RDB$CHARACTER_SET_ID CROSS
|
|
|
|
AL1 IN RDB$TYPES
|
|
|
|
WITH AL1.RDB$FIELD_NAME EQ "RDB$CHARACTER_SET_NAME"
|
2002-12-22 14:08:50 +01:00
|
|
|
AND AL1.RDB$TYPE_NAME EQ charset
|
|
|
|
AND COL.RDB$COLLATION_NAME EQ collation
|
2005-05-28 00:45:31 +02:00
|
|
|
AND AL1.RDB$TYPE EQ CS.RDB$CHARACTER_SET_ID
|
2010-04-23 03:59:21 +02:00
|
|
|
{
|
2009-10-21 02:42:38 +02:00
|
|
|
found = true;
|
2011-05-09 12:15:19 +02:00
|
|
|
attachment->att_charset_ids.put((const TEXT*) charset, CS.RDB$CHARACTER_SET_ID);
|
2005-05-28 00:45:31 +02:00
|
|
|
*id = CS.RDB$CHARACTER_SET_ID | (COL.RDB$COLLATION_ID << 8);
|
2010-04-23 03:59:21 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-11 06:04:26 +01:00
|
|
|
static void save_trigger_data(thread_db* tdbb, trig_vec** ptr, jrd_rel* relation,
|
2010-04-19 00:19:11 +02:00
|
|
|
JrdStatement* statement, blb* blrBlob, bid* dbgBlobID,
|
2009-10-21 02:42:38 +02:00
|
|
|
const TEXT* name, FB_UINT64 type,
|
|
|
|
bool sys_trigger, USHORT flags,
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName& engine, const string& entryPoint,
|
2009-10-21 02:42:38 +02:00
|
|
|
const bid* body)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2002-09-19 18:02:58 +02:00
|
|
|
* s a v e _ t r i g g e r _ d a t a
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2002-09-19 18:02:58 +02:00
|
|
|
* Save trigger data to passed vector
|
2001-05-23 15:26:42 +02:00
|
|
|
*
|
|
|
|
**************************************/
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2004-02-20 07:43:27 +01:00
|
|
|
trig_vec* vector = *ptr;
|
2001-12-24 03:51:06 +01:00
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
if (!vector)
|
|
|
|
{
|
2011-06-03 19:39:22 +02:00
|
|
|
MemoryPool* pool = relation ? relation->rel_pool : attachment->att_pool;
|
|
|
|
vector = FB_NEW(*pool) trig_vec(*pool);
|
2001-12-24 03:51:06 +01:00
|
|
|
*ptr = vector;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-04-19 17:29:29 +02:00
|
|
|
Trigger& t = vector->add();
|
2005-05-28 00:45:31 +02:00
|
|
|
if (blrBlob)
|
2004-04-19 17:29:29 +02:00
|
|
|
{
|
2013-01-25 13:34:19 +01:00
|
|
|
const ULONG length = blrBlob->blb_length + 10;
|
2004-05-12 21:39:17 +02:00
|
|
|
UCHAR* ptr2 = t.blr.getBuffer(length);
|
2012-02-07 04:17:52 +01:00
|
|
|
t.blr.resize(blrBlob->BLB_get_data(tdbb, ptr2, length));
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2006-10-30 21:58:06 +01:00
|
|
|
if (dbgBlobID)
|
|
|
|
t.dbg_blob_id = *dbgBlobID;
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
if (name)
|
2004-04-19 17:29:29 +02:00
|
|
|
t.name = name;
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
if (body)
|
|
|
|
{
|
2012-02-15 04:34:21 +01:00
|
|
|
blb* bodyBlob = blb::open(tdbb, attachment->getSysTransaction(), body);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
HalfStaticArray<char, 512> temp;
|
2012-02-07 04:17:52 +01:00
|
|
|
ULONG length = bodyBlob->BLB_get_data(tdbb, (UCHAR*) temp.getBuffer(bodyBlob->blb_length),
|
2009-10-21 02:42:38 +02:00
|
|
|
bodyBlob->blb_length);
|
|
|
|
|
2012-02-15 04:43:06 +01:00
|
|
|
t.extBody.assign(temp.begin(), length);
|
2003-12-03 09:19:24 +01:00
|
|
|
}
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2005-03-28 23:52:55 +02:00
|
|
|
t.type = type;
|
2002-09-19 18:02:58 +02:00
|
|
|
t.flags = flags;
|
2004-01-03 11:59:52 +01:00
|
|
|
t.compile_in_progress = false;
|
2004-02-20 07:43:27 +01:00
|
|
|
t.sys_trigger = sys_trigger;
|
2010-04-19 00:19:11 +02:00
|
|
|
t.statement = statement;
|
2002-09-19 18:02:58 +02:00
|
|
|
t.relation = relation;
|
2009-10-21 02:42:38 +02:00
|
|
|
t.engine = engine;
|
|
|
|
t.entryPoint = entryPoint;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
const Trigger* findTrigger(trig_vec* triggers, const MetaName& trig_name)
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
|
|
|
if (triggers)
|
|
|
|
{
|
2008-12-18 11:57:12 +01:00
|
|
|
for (trig_vec::iterator t = triggers->begin(); t != triggers->end(); ++t)
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
|
|
|
if (t->name.compare(trig_name) == 0)
|
|
|
|
return &(*t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-19 19:33:03 +01:00
|
|
|
void scan_partners(thread_db* tdbb, jrd_rel* relation)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s c a n _ p a r t n e r s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2010-01-21 03:51:32 +01:00
|
|
|
* Scan of foreign references on other relations' primary keys and
|
2010-01-19 19:33:03 +01:00
|
|
|
* scan of primary dependencies on relation's primary key.
|
|
|
|
*
|
|
|
|
**************************************/
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2010-01-19 19:33:03 +01:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_foreign1, IRQ_REQUESTS);
|
2010-01-19 19:33:03 +01:00
|
|
|
frgn* references = &relation->rel_foreign_refs;
|
|
|
|
int index_number = 0;
|
|
|
|
|
|
|
|
if (references->frgn_reference_ids)
|
|
|
|
{
|
|
|
|
delete references->frgn_reference_ids;
|
|
|
|
references->frgn_reference_ids = NULL;
|
|
|
|
}
|
|
|
|
if (references->frgn_relations)
|
|
|
|
{
|
|
|
|
delete references->frgn_relations;
|
|
|
|
references->frgn_relations = NULL;
|
|
|
|
}
|
|
|
|
if (references->frgn_indexes)
|
|
|
|
{
|
|
|
|
delete references->frgn_indexes;
|
|
|
|
references->frgn_indexes = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
IDX IN RDB$INDICES CROSS
|
|
|
|
RC IN RDB$RELATION_CONSTRAINTS
|
|
|
|
OVER RDB$INDEX_NAME CROSS
|
|
|
|
IND IN RDB$INDICES WITH
|
|
|
|
RC.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY AND
|
|
|
|
IDX.RDB$RELATION_NAME EQ relation->rel_name.c_str() AND
|
|
|
|
IND.RDB$INDEX_NAME EQ IDX.RDB$FOREIGN_KEY AND
|
|
|
|
IND.RDB$UNIQUE_FLAG = 1
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-01-19 19:33:03 +01:00
|
|
|
const jrd_rel* partner_relation = MET_lookup_relation(tdbb, IND.RDB$RELATION_NAME);
|
|
|
|
|
|
|
|
if (partner_relation && !IDX.RDB$INDEX_INACTIVE && !IND.RDB$INDEX_INACTIVE)
|
|
|
|
{
|
|
|
|
// This seems a good candidate for vcl.
|
|
|
|
references->frgn_reference_ids =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<int>::newVector(*relation->rel_pool, references->frgn_reference_ids,
|
2010-01-19 19:33:03 +01:00
|
|
|
index_number + 1);
|
|
|
|
|
|
|
|
(*references->frgn_reference_ids)[index_number] = IDX.RDB$INDEX_ID - 1;
|
|
|
|
|
|
|
|
references->frgn_relations =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<int>::newVector(*relation->rel_pool, references->frgn_relations,
|
2010-01-19 19:33:03 +01:00
|
|
|
index_number + 1);
|
|
|
|
|
|
|
|
(*references->frgn_relations)[index_number] = partner_relation->rel_id;
|
|
|
|
|
|
|
|
references->frgn_indexes =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<int>::newVector(*relation->rel_pool, references->frgn_indexes,
|
2010-01-19 19:33:03 +01:00
|
|
|
index_number + 1);
|
|
|
|
|
|
|
|
(*references->frgn_indexes)[index_number] = IND.RDB$INDEX_ID - 1;
|
|
|
|
|
|
|
|
index_number++;
|
|
|
|
}
|
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2010-01-19 19:33:03 +01:00
|
|
|
|
|
|
|
// Prepare for rescan of primary dependencies on relation's primary key and stale vectors.
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
request.reset(tdbb, irq_foreign2, IRQ_REQUESTS);
|
2010-01-19 19:33:03 +01:00
|
|
|
prim* dependencies = &relation->rel_primary_dpnds;
|
|
|
|
index_number = 0;
|
|
|
|
|
|
|
|
if (dependencies->prim_reference_ids)
|
|
|
|
{
|
|
|
|
delete dependencies->prim_reference_ids;
|
|
|
|
dependencies->prim_reference_ids = NULL;
|
|
|
|
}
|
|
|
|
if (dependencies->prim_relations)
|
|
|
|
{
|
|
|
|
delete dependencies->prim_relations;
|
|
|
|
dependencies->prim_relations = NULL;
|
|
|
|
}
|
|
|
|
if (dependencies->prim_indexes)
|
|
|
|
{
|
|
|
|
delete dependencies->prim_indexes;
|
|
|
|
dependencies->prim_indexes = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
IDX IN RDB$INDICES CROSS
|
|
|
|
IND IN RDB$INDICES WITH
|
|
|
|
IDX.RDB$UNIQUE_FLAG = 1 AND
|
|
|
|
IDX.RDB$RELATION_NAME EQ relation->rel_name.c_str() AND
|
|
|
|
IND.RDB$FOREIGN_KEY EQ IDX.RDB$INDEX_NAME
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2010-01-19 19:33:03 +01:00
|
|
|
const jrd_rel* partner_relation = MET_lookup_relation(tdbb, IND.RDB$RELATION_NAME);
|
|
|
|
|
|
|
|
if (partner_relation && !IDX.RDB$INDEX_INACTIVE && !IND.RDB$INDEX_INACTIVE)
|
|
|
|
{
|
|
|
|
dependencies->prim_reference_ids =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<int>::newVector(*relation->rel_pool, dependencies->prim_reference_ids,
|
2010-01-19 19:33:03 +01:00
|
|
|
index_number + 1);
|
|
|
|
|
|
|
|
(*dependencies->prim_reference_ids)[index_number] = IDX.RDB$INDEX_ID - 1;
|
|
|
|
|
|
|
|
dependencies->prim_relations =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<int>::newVector(*relation->rel_pool, dependencies->prim_relations,
|
2010-01-19 19:33:03 +01:00
|
|
|
index_number + 1);
|
|
|
|
|
|
|
|
(*dependencies->prim_relations)[index_number] = partner_relation->rel_id;
|
|
|
|
|
|
|
|
dependencies->prim_indexes =
|
2011-05-09 12:15:19 +02:00
|
|
|
vec<int>::newVector(*relation->rel_pool, dependencies->prim_indexes,
|
2010-01-19 19:33:03 +01:00
|
|
|
index_number + 1);
|
|
|
|
|
|
|
|
(*dependencies->prim_indexes)[index_number] = IND.RDB$INDEX_ID - 1;
|
|
|
|
|
|
|
|
index_number++;
|
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2010-01-19 19:33:03 +01:00
|
|
|
|
|
|
|
LCK_lock(tdbb, relation->rel_partners_lock, LCK_SR, LCK_WAIT);
|
|
|
|
relation->rel_flags &= ~REL_check_partners;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-21 17:49:24 +02:00
|
|
|
static void store_dependencies(thread_db* tdbb,
|
|
|
|
CompilerScratch* csb,
|
|
|
|
const jrd_rel* dep_rel,
|
2010-06-12 18:32:46 +02:00
|
|
|
const MetaName& object_name,
|
2008-07-21 17:49:24 +02:00
|
|
|
int dependency_type,
|
|
|
|
jrd_tra* transaction)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* s t o r e _ d e p e n d e n c i e s
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Store records in RDB$DEPENDENCIES
|
2005-05-28 00:45:31 +02:00
|
|
|
* corresponding to the objects found during
|
2001-05-23 15:26:42 +02:00
|
|
|
* compilation of blr for a trigger, view, etc.
|
|
|
|
*
|
|
|
|
**************************************/
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName name;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
|
|
|
|
2006-05-25 10:40:23 +02:00
|
|
|
const Trigger* t = 0;
|
2008-12-14 10:28:25 +01:00
|
|
|
const bool checkTableScope =
|
2006-05-22 00:07:35 +02:00
|
|
|
(dependency_type == obj_computed) ||
|
2008-12-18 11:57:12 +01:00
|
|
|
(dependency_type == obj_trigger) && (dep_rel != 0) &&
|
|
|
|
(
|
2006-05-22 00:07:35 +02:00
|
|
|
(t = findTrigger(dep_rel->rel_pre_erase, object_name)) ||
|
|
|
|
(t = findTrigger(dep_rel->rel_pre_modify, object_name)) ||
|
|
|
|
(t = findTrigger(dep_rel->rel_pre_store, object_name)) ||
|
|
|
|
(t = findTrigger(dep_rel->rel_post_erase, object_name)) ||
|
|
|
|
(t = findTrigger(dep_rel->rel_post_modify, object_name)) ||
|
2008-12-14 10:28:25 +01:00
|
|
|
(t = findTrigger(dep_rel->rel_post_store, object_name))
|
2006-05-22 00:07:35 +02:00
|
|
|
) && t && (t->sys_trigger);
|
|
|
|
|
2004-05-27 18:26:52 +02:00
|
|
|
while (csb->csb_dependencies.hasData())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-08-11 04:59:33 +02:00
|
|
|
CompilerScratch::Dependency dependency = csb->csb_dependencies.pop();
|
|
|
|
|
|
|
|
if (!dependency.relation && !dependency.function && !dependency.procedure &&
|
|
|
|
!dependency.name && !dependency.number)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
2010-08-11 04:59:33 +02:00
|
|
|
}
|
2005-05-28 00:45:31 +02:00
|
|
|
|
2010-08-11 04:59:33 +02:00
|
|
|
int dpdo_type = dependency.objType;
|
2006-08-07 18:39:21 +02:00
|
|
|
jrd_rel* relation = NULL;
|
2010-08-11 04:59:33 +02:00
|
|
|
const jrd_prc* procedure = NULL;
|
2010-06-22 02:53:35 +02:00
|
|
|
const MetaName* dpdo_name = NULL;
|
2009-10-21 02:42:38 +02:00
|
|
|
MetaName packageName;
|
2006-08-07 18:39:21 +02:00
|
|
|
SubtypeInfo info;
|
2008-12-14 10:28:25 +01:00
|
|
|
|
2009-01-20 09:33:59 +01:00
|
|
|
switch (dpdo_type)
|
|
|
|
{
|
2006-08-07 18:39:21 +02:00
|
|
|
case obj_relation:
|
2010-08-11 04:59:33 +02:00
|
|
|
relation = dependency.relation;
|
2005-05-12 20:28:04 +02:00
|
|
|
dpdo_name = &relation->rel_name;
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2008-12-18 11:57:12 +01:00
|
|
|
fb_assert(dep_rel || !checkTableScope);
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2008-12-14 10:28:25 +01:00
|
|
|
if (checkTableScope &&
|
2006-06-01 06:45:48 +02:00
|
|
|
( (dep_rel->rel_flags & (REL_temp_tran | REL_temp_conn)) !=
|
|
|
|
(relation->rel_flags & (REL_temp_tran | REL_temp_conn)) ))
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
2008-10-09 22:07:37 +02:00
|
|
|
if ( !( // master is ON COMMIT PRESERVE, detail is ON COMMIT DELETE
|
|
|
|
(dep_rel->rel_flags & REL_temp_tran) && (relation->rel_flags & REL_temp_conn) ||
|
2008-12-14 10:28:25 +01:00
|
|
|
// computed field of a view
|
|
|
|
(dependency_type == obj_computed) && (dep_rel->rel_view_rse != NULL)
|
2008-10-09 22:07:37 +02:00
|
|
|
))
|
2006-05-22 00:07:35 +02:00
|
|
|
{
|
2010-06-12 18:32:46 +02:00
|
|
|
string sMaster, sChild;
|
2006-05-24 22:43:07 +02:00
|
|
|
|
2008-12-14 10:28:25 +01:00
|
|
|
make_relation_scope_name(relation->rel_name.c_str(),
|
2006-05-24 22:43:07 +02:00
|
|
|
relation->rel_flags, sMaster);
|
2008-12-14 10:28:25 +01:00
|
|
|
make_relation_scope_name(dep_rel->rel_name.c_str(),
|
2006-05-24 22:43:07 +02:00
|
|
|
dep_rel->rel_flags, sChild);
|
2006-05-22 00:07:35 +02:00
|
|
|
|
2008-08-27 14:20:47 +02:00
|
|
|
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
2008-12-14 10:28:25 +01:00
|
|
|
Arg::Gds(isc_met_wrong_gtt_scope) << Arg::Str(sChild) <<
|
2008-08-27 14:20:47 +02:00
|
|
|
Arg::Str(sMaster));
|
2006-05-22 00:07:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-26 14:44:16 +01:00
|
|
|
MET_scan_relation(tdbb, relation);
|
|
|
|
if (relation->rel_view_rse) {
|
|
|
|
dpdo_type = obj_view;
|
|
|
|
}
|
2008-12-18 11:57:12 +01:00
|
|
|
break;
|
|
|
|
case obj_procedure:
|
2010-08-11 04:59:33 +02:00
|
|
|
procedure = dependency.procedure;
|
2009-12-27 23:05:22 +01:00
|
|
|
dpdo_name = &procedure->getName().identifier;
|
2010-01-27 05:32:27 +01:00
|
|
|
packageName = procedure->getName().package;
|
2008-12-18 11:57:12 +01:00
|
|
|
break;
|
2006-08-07 18:39:21 +02:00
|
|
|
case obj_collation:
|
|
|
|
{
|
2010-08-11 04:59:33 +02:00
|
|
|
const USHORT number = dependency.number;
|
2006-08-07 18:39:21 +02:00
|
|
|
MET_get_char_coll_subtype_info(tdbb, number, &info);
|
|
|
|
dpdo_name = &info.collationName;
|
|
|
|
}
|
2006-08-13 08:46:16 +02:00
|
|
|
break;
|
2008-12-18 11:57:12 +01:00
|
|
|
case obj_exception:
|
2004-01-03 11:59:52 +01:00
|
|
|
{
|
2010-08-11 04:59:33 +02:00
|
|
|
const SLONG number = dependency.number;
|
2009-12-05 15:21:52 +01:00
|
|
|
MET_lookup_exception(tdbb, number, name, NULL);
|
2005-05-12 20:28:04 +02:00
|
|
|
dpdo_name = &name;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2005-05-26 06:00:45 +02:00
|
|
|
break;
|
2008-12-18 11:57:12 +01:00
|
|
|
case obj_field:
|
2010-08-11 04:59:33 +02:00
|
|
|
dpdo_name = dependency.name;
|
2006-08-19 04:52:39 +02:00
|
|
|
break;
|
2008-12-18 11:57:12 +01:00
|
|
|
// CVC: Here I'm going to track those pesky things named generators and UDFs.
|
2004-01-03 11:59:52 +01:00
|
|
|
case obj_generator:
|
|
|
|
{
|
2010-08-11 04:59:33 +02:00
|
|
|
const SLONG number = dependency.number;
|
2004-01-03 11:59:52 +01:00
|
|
|
MET_lookup_generator_id (tdbb, number, name);
|
2005-05-12 20:28:04 +02:00
|
|
|
dpdo_name = &name;
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2005-05-26 06:00:45 +02:00
|
|
|
break;
|
2008-12-18 11:57:12 +01:00
|
|
|
case obj_udf:
|
2004-01-03 11:59:52 +01:00
|
|
|
{
|
2010-08-11 04:59:33 +02:00
|
|
|
const Function* const udf = dependency.function;
|
2009-12-27 23:05:22 +01:00
|
|
|
dpdo_name = &udf->getName().identifier;
|
2010-01-27 05:32:27 +01:00
|
|
|
packageName = udf->getName().package;
|
2004-03-31 19:59:58 +02:00
|
|
|
}
|
|
|
|
break;
|
2005-05-26 06:00:45 +02:00
|
|
|
case obj_index:
|
2010-08-11 04:59:33 +02:00
|
|
|
name = *dependency.name;
|
2005-05-26 06:00:45 +02:00
|
|
|
dpdo_name = &name;
|
|
|
|
break;
|
2004-03-31 19:59:58 +02:00
|
|
|
}
|
2002-07-01 18:59:09 +02:00
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
MetaName field_name;
|
2010-08-11 04:59:33 +02:00
|
|
|
|
|
|
|
if (dependency.subNumber || dependency.subName)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-08-11 04:59:33 +02:00
|
|
|
if (dependency.subNumber)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-08-11 04:59:33 +02:00
|
|
|
const SSHORT fld_id = (SSHORT) dependency.subNumber;
|
2001-05-23 15:26:42 +02:00
|
|
|
if (relation)
|
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
const jrd_fld* field = MET_get_field(relation, fld_id);
|
|
|
|
if (field)
|
2001-05-23 15:26:42 +02:00
|
|
|
field_name = field->fld_name;
|
2004-02-20 07:43:27 +01:00
|
|
|
}
|
|
|
|
else if (procedure)
|
|
|
|
{
|
2011-10-16 22:36:07 +02:00
|
|
|
const Parameter* param = procedure->getOutputFields()[fld_id];
|
2004-02-20 07:43:27 +01:00
|
|
|
// CVC: Setting the field var here didn't make sense alone,
|
|
|
|
// so I thought the missing code was to try to extract
|
|
|
|
// the field name that's in this case an output var from a proc.
|
2005-12-02 08:35:34 +01:00
|
|
|
if (param)
|
|
|
|
field_name = param->prm_name;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-08-11 04:59:33 +02:00
|
|
|
field_name = *dependency.subName;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2010-08-11 04:59:33 +02:00
|
|
|
if (field_name.hasData())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_c_deps_f, IRQ_REQUESTS);
|
2004-01-03 11:59:52 +01:00
|
|
|
bool found = false;
|
2005-05-12 20:28:04 +02:00
|
|
|
fb_assert(dpdo_name);
|
2010-04-18 17:04:52 +02:00
|
|
|
|
2008-07-21 17:49:24 +02:00
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) X IN RDB$DEPENDENCIES WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
X.RDB$DEPENDENT_NAME = object_name.c_str() AND
|
|
|
|
X.RDB$DEPENDED_ON_NAME = dpdo_name->c_str() AND
|
2001-05-23 15:26:42 +02:00
|
|
|
X.RDB$DEPENDED_ON_TYPE = dpdo_type AND
|
2005-05-12 20:28:04 +02:00
|
|
|
X.RDB$FIELD_NAME = field_name.c_str() AND
|
2001-05-23 15:26:42 +02:00
|
|
|
X.RDB$DEPENDENT_TYPE = dependency_type
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
found = true;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2006-07-09 07:08:23 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
if (found)
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_c_deps, IRQ_REQUESTS);
|
2004-01-03 11:59:52 +01:00
|
|
|
bool found = false;
|
2010-04-18 17:04:52 +02:00
|
|
|
|
2008-07-21 17:49:24 +02:00
|
|
|
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) X IN RDB$DEPENDENCIES WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
X.RDB$DEPENDENT_NAME = object_name.c_str() AND
|
|
|
|
X.RDB$DEPENDED_ON_NAME = dpdo_name->c_str() AND
|
2001-05-23 15:26:42 +02:00
|
|
|
X.RDB$DEPENDED_ON_TYPE = dpdo_type AND
|
|
|
|
X.RDB$FIELD_NAME MISSING AND
|
2009-10-21 02:42:38 +02:00
|
|
|
X.RDB$DEPENDENT_TYPE = dependency_type AND
|
|
|
|
X.RDB$PACKAGE_NAME EQUIV NULLIF(packageName.c_str(), '')
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2004-01-03 11:59:52 +01:00
|
|
|
found = true;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
if (found)
|
2001-05-23 15:26:42 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_s_deps, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-05-12 20:28:04 +02:00
|
|
|
fb_assert(dpdo_name);
|
2010-04-18 17:04:52 +02:00
|
|
|
|
2008-07-21 17:49:24 +02:00
|
|
|
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) DEP IN RDB$DEPENDENCIES
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2005-05-12 20:28:04 +02:00
|
|
|
strcpy(DEP.RDB$DEPENDENT_NAME, object_name.c_str());
|
2001-05-23 15:26:42 +02:00
|
|
|
DEP.RDB$DEPENDED_ON_TYPE = dpdo_type;
|
2005-05-12 20:28:04 +02:00
|
|
|
strcpy(DEP.RDB$DEPENDED_ON_NAME, dpdo_name->c_str());
|
2009-10-21 02:42:38 +02:00
|
|
|
|
2010-08-11 04:59:33 +02:00
|
|
|
if (field_name.hasData())
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
DEP.RDB$FIELD_NAME.NULL = FALSE;
|
2005-05-12 20:28:04 +02:00
|
|
|
strcpy(DEP.RDB$FIELD_NAME, field_name.c_str());
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2009-10-21 02:42:38 +02:00
|
|
|
else
|
2001-05-23 15:26:42 +02:00
|
|
|
DEP.RDB$FIELD_NAME.NULL = TRUE;
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
if (packageName.hasData())
|
|
|
|
{
|
|
|
|
DEP.RDB$PACKAGE_NAME.NULL = FALSE;
|
|
|
|
strcpy(DEP.RDB$PACKAGE_NAME, packageName.c_str());
|
2004-01-03 11:59:52 +01:00
|
|
|
}
|
2009-10-21 02:42:38 +02:00
|
|
|
else
|
|
|
|
DEP.RDB$PACKAGE_NAME.NULL = TRUE;
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
DEP.RDB$DEPENDENT_TYPE = dependency_type;
|
2010-04-18 17:04:52 +02:00
|
|
|
}
|
|
|
|
END_STORE
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-12 18:32:46 +02:00
|
|
|
static bool verify_TRG_ignore_perm(thread_db* tdbb, const MetaName& trig_name)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
/*****************************************************
|
|
|
|
*
|
|
|
|
* v e r i f y _ T R G _ i g n o r e _ p e r m
|
|
|
|
*
|
|
|
|
*****************************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
2004-01-03 11:59:52 +01:00
|
|
|
* Return true if this trigger can go through without any permission
|
2001-05-23 15:26:42 +02:00
|
|
|
* checks. Currently, the only class of triggers that can go
|
2005-05-28 00:45:31 +02:00
|
|
|
* through without permission checks are
|
2001-05-23 15:26:42 +02:00
|
|
|
* (a) two system triggers (RDB$TRIGGERS_34 and RDB$TRIGGERS_35)
|
2005-05-28 00:45:31 +02:00
|
|
|
* (b) those defined for referential integrity actions such as,
|
2001-05-23 15:26:42 +02:00
|
|
|
* set null, set default, and cascade.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2005-10-13 10:11:37 +02:00
|
|
|
// See if this is a system trigger, with the flag set as TRG_ignore_perm
|
|
|
|
|
|
|
|
if (INI_get_trig_flags(trig_name.c_str()) & TRG_ignore_perm)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2003-12-11 11:33:30 +01:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2005-10-13 10:11:37 +02:00
|
|
|
// See if this is a RI trigger
|
|
|
|
|
2010-04-18 17:04:52 +02:00
|
|
|
AutoCacheRequest request(tdbb, irq_c_trg_perm, IRQ_REQUESTS);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
CHK IN RDB$CHECK_CONSTRAINTS CROSS
|
|
|
|
REF IN RDB$REF_CONSTRAINTS WITH
|
2005-05-12 20:28:04 +02:00
|
|
|
CHK.RDB$TRIGGER_NAME EQ trig_name.c_str() AND
|
2001-05-23 15:26:42 +02:00
|
|
|
REF.RDB$CONSTRAINT_NAME = CHK.RDB$CONSTRAINT_NAME
|
2010-04-18 17:04:52 +02:00
|
|
|
{
|
2004-09-26 03:49:52 +02:00
|
|
|
fb_utils::exact_name_limit(REF.RDB$UPDATE_RULE, sizeof(REF.RDB$UPDATE_RULE));
|
|
|
|
fb_utils::exact_name_limit(REF.RDB$DELETE_RULE, sizeof(REF.RDB$DELETE_RULE));
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!strcmp(REF.RDB$UPDATE_RULE, RI_ACTION_CASCADE) ||
|
|
|
|
!strcmp(REF.RDB$UPDATE_RULE, RI_ACTION_NULL) ||
|
|
|
|
!strcmp(REF.RDB$UPDATE_RULE, RI_ACTION_DEFAULT) ||
|
|
|
|
!strcmp(REF.RDB$DELETE_RULE, RI_ACTION_CASCADE) ||
|
|
|
|
!strcmp(REF.RDB$DELETE_RULE, RI_ACTION_NULL) ||
|
|
|
|
!strcmp(REF.RDB$DELETE_RULE, RI_ACTION_DEFAULT))
|
|
|
|
{
|
2003-12-11 11:33:30 +01:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2007-03-28 06:20:36 +02:00
|
|
|
|
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2010-04-18 17:04:52 +02:00
|
|
|
END_FOR
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-12-11 11:33:30 +01:00
|
|
|
return false;
|
2001-07-12 08:32:05 +02:00
|
|
|
}
|