mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 15:23:02 +01:00
Ported fix for CORE-2634: Performance regression when restoring database with big metadata
This commit is contained in:
parent
13ee7923d3
commit
b19dacee16
310
src/common/classes/Hash.h
Normal file
310
src/common/classes/Hash.h
Normal file
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: Hash.h
|
||||
* DESCRIPTION: Hash of objects
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's 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.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* 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 Alexander Peshkoff
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2009 Alexander Peshkoff <peshkoff@mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CLASSES_HASH_H
|
||||
#define CLASSES_HASH_H
|
||||
|
||||
#include "../common/classes/vector.h"
|
||||
|
||||
namespace Firebird {
|
||||
template <typename K>
|
||||
class DefaultHash
|
||||
{
|
||||
public:
|
||||
static size_t hash(const void* value, size_t length, size_t hashSize)
|
||||
{
|
||||
size_t sum = 0;
|
||||
size_t val;
|
||||
|
||||
const char* data = static_cast<const char*>(value);
|
||||
|
||||
while (length >= sizeof(size_t))
|
||||
{
|
||||
memcpy(&val, data, sizeof(size_t));
|
||||
sum += val;
|
||||
data += sizeof(size_t);
|
||||
length -= sizeof(size_t);
|
||||
}
|
||||
|
||||
if (length)
|
||||
{
|
||||
val = 0;
|
||||
memcpy(&val, data, length);
|
||||
sum += val;
|
||||
}
|
||||
|
||||
size_t rc = 0;
|
||||
while (sum)
|
||||
{
|
||||
rc += (sum % hashSize);
|
||||
sum /= hashSize;
|
||||
}
|
||||
|
||||
return rc % hashSize;
|
||||
}
|
||||
|
||||
static size_t hash(const K& value, size_t hashSize)
|
||||
{
|
||||
return hash(&value, sizeof value, hashSize);
|
||||
}
|
||||
|
||||
const static size_t DEFAULT_SIZE = 97; // largest prime number < 100
|
||||
};
|
||||
|
||||
template <typename C,
|
||||
size_t HASHSIZE = DefaultHash<C>::DEFAULT_SIZE,
|
||||
typename K = C, // default key
|
||||
typename KeyOfValue = DefaultKeyValue<C>, // default keygen
|
||||
typename F = DefaultHash<K> > // hash function definition
|
||||
class Hash
|
||||
{
|
||||
public:
|
||||
class iterator;
|
||||
friend class iterator;
|
||||
class Entry;
|
||||
friend class Entry;
|
||||
|
||||
class Entry
|
||||
{
|
||||
// This class is supposed to be used as a BASE class for class to be hashed
|
||||
private:
|
||||
Entry** previousElement;
|
||||
Entry* nextElement;
|
||||
|
||||
public:
|
||||
Entry() : previousElement(NULL) { }
|
||||
|
||||
virtual ~Entry()
|
||||
{
|
||||
unLink();
|
||||
}
|
||||
|
||||
void link(Entry** where)
|
||||
{
|
||||
unLink();
|
||||
|
||||
// set our pointers
|
||||
previousElement = where;
|
||||
nextElement = previousElement ? *previousElement : NULL;
|
||||
|
||||
// make next element (if present) to point to us
|
||||
if (nextElement)
|
||||
{
|
||||
nextElement->previousElement = &nextElement;
|
||||
}
|
||||
|
||||
// make previous element point to us
|
||||
*previousElement = this;
|
||||
}
|
||||
|
||||
void unLink()
|
||||
{
|
||||
// if we are linked
|
||||
if (previousElement)
|
||||
{
|
||||
if (nextElement)
|
||||
{
|
||||
// adjust previous pointer in next element ...
|
||||
nextElement->previousElement = previousElement;
|
||||
}
|
||||
// ... and next pointer in previous element
|
||||
*previousElement = nextElement;
|
||||
// finally mark ourselves not linked
|
||||
previousElement = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Entry** nextPtr()
|
||||
{
|
||||
return &nextElement;
|
||||
}
|
||||
|
||||
Entry* next() const
|
||||
{
|
||||
return nextElement;
|
||||
}
|
||||
|
||||
virtual bool isEqual(const K&) const = 0;
|
||||
virtual C* get() = 0;
|
||||
}; // class Entry
|
||||
|
||||
private:
|
||||
Hash(const Hash&); // not implemented
|
||||
|
||||
public:
|
||||
explicit Hash(MemoryPool&)
|
||||
{
|
||||
memset(data, 0, sizeof data);
|
||||
}
|
||||
|
||||
Hash()
|
||||
{
|
||||
memset(data, 0, sizeof data);
|
||||
}
|
||||
|
||||
~Hash()
|
||||
{
|
||||
for (size_t n = 0; n < HASHSIZE; ++n)
|
||||
{
|
||||
while (data[n])
|
||||
{
|
||||
data[n]->unLink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Entry* data[HASHSIZE];
|
||||
|
||||
Entry** locate(const K& key, size_t h)
|
||||
{
|
||||
Entry** pointer = &data[h];
|
||||
while (*pointer)
|
||||
{
|
||||
if ((*pointer)->isEqual(key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
pointer = (*pointer)->nextPtr();
|
||||
}
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
Entry** locate(const K& key)
|
||||
{
|
||||
return locate(key, F::hash(key, HASHSIZE) % HASHSIZE);
|
||||
}
|
||||
|
||||
public:
|
||||
bool add(C* value)
|
||||
{
|
||||
Entry** e = locate(KeyOfValue::generate(this, *value));
|
||||
if (*e)
|
||||
{
|
||||
return false; // sorry, duplicate
|
||||
}
|
||||
value->link(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
C* lookup(const K& key)
|
||||
{
|
||||
Entry** e = locate(key);
|
||||
return (*e) ? (*e)->get() : NULL;
|
||||
}
|
||||
|
||||
C* remove(const K& key)
|
||||
{
|
||||
Entry** e = locate(key);
|
||||
if (*e)
|
||||
{
|
||||
Entry* entry = *e;
|
||||
entry->unLink();
|
||||
return entry->get();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
// disable use of default operator=
|
||||
Hash& operator= (const Hash&);
|
||||
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
private:
|
||||
const Hash* hash;
|
||||
size_t elem;
|
||||
Entry* current;
|
||||
|
||||
iterator(const iterator& i);
|
||||
iterator& operator= (const iterator& i);
|
||||
|
||||
void next()
|
||||
{
|
||||
while(!current)
|
||||
{
|
||||
if (++elem >= HASHSIZE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
current = hash->data[elem];
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit iterator(const Hash& h)
|
||||
: hash(&h), elem(0), current(hash->data[elem])
|
||||
{
|
||||
next();
|
||||
}
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
if (hasData())
|
||||
{
|
||||
current = current->next();
|
||||
next();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool hasData() const
|
||||
{
|
||||
return current ? true : false;
|
||||
}
|
||||
|
||||
operator C*() const
|
||||
{
|
||||
fb_assert(hasData());
|
||||
return current->get();
|
||||
}
|
||||
|
||||
C* operator ->() const
|
||||
{
|
||||
fb_assert(hasData());
|
||||
return current->get();
|
||||
}
|
||||
|
||||
bool operator== (const iterator& h) const
|
||||
{
|
||||
return (hash == h.hash) && (elem == h.elem) && (current == h.current);
|
||||
}
|
||||
|
||||
bool operator!= (const iterator& h) const
|
||||
{
|
||||
return !(*this == h);
|
||||
}
|
||||
}; // class iterator
|
||||
|
||||
}; // class Hash
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#endif // CLASSES_HASH_H
|
||||
|
739
src/jrd/dfw.epp
739
src/jrd/dfw.epp
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@ namespace Jrd
|
||||
enum dfw_t;
|
||||
}
|
||||
|
||||
USHORT DFW_assign_index_type(Jrd::thread_db*, Jrd::DeferredWork*, SSHORT, SSHORT);
|
||||
USHORT DFW_assign_index_type(Jrd::thread_db*, const Firebird::string&, SSHORT, SSHORT);
|
||||
void DFW_delete_deferred(Jrd::jrd_tra*, SLONG);
|
||||
void DFW_merge_work(Jrd::jrd_tra*, SLONG, SLONG);
|
||||
void DFW_perform_system_work(Jrd::thread_db*);
|
||||
@ -40,6 +40,7 @@ void DFW_perform_post_commit_work(Jrd::jrd_tra*);
|
||||
Jrd::DeferredWork* DFW_post_system_work(Jrd::thread_db*, Jrd::dfw_t, const dsc*, USHORT);
|
||||
Jrd::DeferredWork* DFW_post_work(Jrd::jrd_tra*, Jrd::dfw_t, const dsc*, USHORT);
|
||||
Jrd::DeferredWork* DFW_post_work_arg(Jrd::jrd_tra*, Jrd::DeferredWork*, const dsc*, USHORT);
|
||||
Jrd::DeferredWork* DFW_post_work_arg(Jrd::jrd_tra*, Jrd::DeferredWork*, const dsc*, USHORT, Jrd::dfw_t);
|
||||
void DFW_update_index(const TEXT*, USHORT, const Jrd::SelectivityList&, Jrd::jrd_tra*);
|
||||
|
||||
#endif // JRD_DFW_PROTO_H
|
||||
|
@ -93,7 +93,7 @@ static SecurityClass::flags_t squeeze_acl(Acl&, const Firebird::MetaName&, SSHOR
|
||||
static bool check_string(const UCHAR*, const Firebird::MetaName&);
|
||||
|
||||
|
||||
bool GRANT_privileges(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
|
||||
void GRANT_privileges(thread_db* tdbb, const Firebird::string& name, USHORT id, jrd_tra* transaction)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -108,14 +108,6 @@ bool GRANT_privileges(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra
|
||||
* the order of operations lightly.
|
||||
*
|
||||
**************************************/
|
||||
switch (phase)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
return true;
|
||||
|
||||
case 3:
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
bool restrct = false;
|
||||
@ -123,11 +115,10 @@ bool GRANT_privileges(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra
|
||||
//Database* dbb = tdbb->getDatabase();
|
||||
Firebird::MetaName s_class, owner, default_class;
|
||||
bool view; // unused after being retrieved.
|
||||
get_object_info(tdbb, work->dfw_name.c_str(), work->dfw_id, owner,
|
||||
s_class, default_class, view);
|
||||
get_object_info(tdbb, name.c_str(), id, owner, s_class, default_class, view);
|
||||
|
||||
if (s_class.length() == 0) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* start the acl off by giving the owner all privileges */
|
||||
@ -135,15 +126,14 @@ bool GRANT_privileges(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra
|
||||
|
||||
CHECK_AND_MOVE(acl, ACL_version);
|
||||
grant_user(acl, owner, obj_user,
|
||||
((work->dfw_id == obj_procedure) ? (SCL_execute | OWNER_PRIVS) : OWNER_PRIVS));
|
||||
(id == obj_procedure ? SCL_execute | OWNER_PRIVS : OWNER_PRIVS));
|
||||
|
||||
/* Pick up any relation-level privileges */
|
||||
|
||||
const SecurityClass::flags_t public_priv =
|
||||
get_public_privs(tdbb, work->dfw_name.c_str(), work->dfw_id);
|
||||
get_user_privs(tdbb, acl, work->dfw_name.c_str(), work->dfw_id, owner, public_priv);
|
||||
const SecurityClass::flags_t public_priv = get_public_privs(tdbb, name.c_str(), id);
|
||||
get_user_privs(tdbb, acl, name.c_str(), id, owner, public_priv);
|
||||
|
||||
if (work->dfw_id == obj_relation)
|
||||
if (id == obj_relation)
|
||||
{
|
||||
/* Now handle field-level privileges. This might require adding
|
||||
UPDATE privilege to the relation-level acl, Therefore, save
|
||||
@ -153,7 +143,7 @@ bool GRANT_privileges(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra
|
||||
default_acl.assign(acl);
|
||||
|
||||
const SecurityClass::flags_t aggregate_public =
|
||||
save_field_privileges(tdbb, acl, work->dfw_name.c_str(), owner, public_priv,
|
||||
save_field_privileges(tdbb, acl, name.c_str(), owner, public_priv,
|
||||
transaction);
|
||||
|
||||
/* SQL tables don't need the 'all priviliges to all views' acl anymore.
|
||||
@ -178,7 +168,7 @@ bool GRANT_privileges(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra
|
||||
if (restrct)
|
||||
{
|
||||
finish_security_class(default_acl, public_priv);
|
||||
define_default_class(tdbb, work->dfw_name.c_str(), default_class, default_acl,
|
||||
define_default_class(tdbb, name.c_str(), default_class, default_acl,
|
||||
transaction);
|
||||
}
|
||||
}
|
||||
@ -186,16 +176,6 @@ bool GRANT_privileges(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra
|
||||
finish_security_class(acl, public_priv);
|
||||
save_security_class(tdbb, s_class, acl, transaction);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
SET_TDBB(tdbb);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,14 +24,14 @@
|
||||
#ifndef JRD_GRANT_PROTO_H
|
||||
#define JRD_GRANT_PROTO_H
|
||||
|
||||
#include "../common/classes/array.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
|
||||
namespace Jrd
|
||||
{
|
||||
class DeferredWork;
|
||||
}
|
||||
|
||||
bool GRANT_privileges(Jrd::thread_db*, SSHORT, Jrd::DeferredWork*, Jrd::jrd_tra*);
|
||||
void GRANT_privileges(Jrd::thread_db*, const Firebird::string&, USHORT, Jrd::jrd_tra*);
|
||||
|
||||
#endif // JRD_GRANT_PROTO_H
|
||||
|
||||
|
@ -846,7 +846,7 @@ DeferredWork* MET_change_fields(thread_db* tdbb, jrd_tra* transaction, const dsc
|
||||
|
||||
DeferredWork* dw2 =
|
||||
DFW_post_work(transaction, dfw_modify_procedure, &desc, PRC.RDB$PROCEDURE_ID);
|
||||
DFW_post_work_arg(transaction, dw2, NULL, 0)->dfw_type = dfw_arg_check_blr;
|
||||
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
||||
END_FOR;
|
||||
|
||||
if (!REQUEST(irq_m_fields2))
|
||||
@ -875,12 +875,11 @@ DeferredWork* MET_change_fields(thread_db* tdbb, jrd_tra* transaction, const dsc
|
||||
desc.dsc_address = (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_type = dfw_arg_trg_type;
|
||||
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_type = dfw_arg_check_blr;
|
||||
DFW_post_work_arg(transaction, dw2, &desc, 0, dfw_arg_check_blr);
|
||||
END_FOR;
|
||||
|
||||
if (!REQUEST(irq_m_fields3))
|
||||
@ -912,7 +911,7 @@ DeferredWork* MET_change_fields(thread_db* tdbb, jrd_tra* transaction, const dsc
|
||||
|
||||
DeferredWork* dw2 =
|
||||
DFW_post_work(transaction, dfw_modify_procedure, &desc, PRC.RDB$PROCEDURE_ID);
|
||||
DFW_post_work_arg(transaction, dw2, NULL, 0)->dfw_type = dfw_arg_check_blr;
|
||||
DFW_post_work_arg(transaction, dw2, NULL, 0, dfw_arg_check_blr);
|
||||
END_FOR;
|
||||
|
||||
if (!REQUEST(irq_m_fields4))
|
||||
@ -944,12 +943,11 @@ DeferredWork* MET_change_fields(thread_db* tdbb, jrd_tra* transaction, const dsc
|
||||
desc.dsc_address = (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_type = dfw_arg_trg_type;
|
||||
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_type = dfw_arg_check_blr;
|
||||
DFW_post_work_arg(transaction, dw2, &desc, 0, dfw_arg_check_blr);
|
||||
END_FOR;
|
||||
|
||||
if (!REQUEST(irq_m_fields5))
|
||||
|
@ -54,7 +54,7 @@ using namespace Firebird;
|
||||
DATABASE DB = FILENAME "ODS.RDB";
|
||||
|
||||
|
||||
bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
|
||||
void PCMET_expression_index(thread_db* tdbb, const string& name, USHORT id, jrd_tra* transaction)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -75,18 +75,6 @@ bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
SET_TDBB(tdbb);
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
case 0:
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, obj_expression_index, transaction);
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
return true;
|
||||
|
||||
case 3:
|
||||
|
||||
relation = NULL;
|
||||
MOVE_CLEAR(&idx, sizeof(index_desc));
|
||||
|
||||
@ -101,7 +89,7 @@ bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
IDX IN RDB$INDICES CROSS
|
||||
REL IN RDB$RELATIONS OVER RDB$RELATION_NAME WITH
|
||||
IDX.RDB$EXPRESSION_BLR NOT MISSING AND
|
||||
IDX.RDB$INDEX_NAME EQ work->dfw_name.c_str()
|
||||
IDX.RDB$INDEX_NAME EQ name.c_str()
|
||||
|
||||
if (!REQUEST(irq_c_exp_index))
|
||||
{
|
||||
@ -120,16 +108,16 @@ bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
SelectivityList selectivity(*tdbb->getDefaultPool());
|
||||
const USHORT id = IDX.RDB$INDEX_ID - 1;
|
||||
IDX_statistics(tdbb, relation, id, selectivity);
|
||||
DFW_update_index(work->dfw_name.c_str(), id, selectivity, transaction);
|
||||
DFW_update_index(name.c_str(), id, selectivity, transaction);
|
||||
|
||||
EXE_unwind(tdbb, request);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IDX.RDB$INDEX_ID)
|
||||
{
|
||||
IDX_delete_index(tdbb, relation, IDX.RDB$INDEX_ID - 1);
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, obj_expression_index, transaction);
|
||||
MET_delete_dependencies(tdbb, name, obj_expression_index, transaction);
|
||||
MODIFY IDX
|
||||
IDX.RDB$INDEX_ID.NULL = TRUE;
|
||||
END_MODIFY;
|
||||
@ -138,14 +126,14 @@ bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
if (IDX.RDB$INDEX_INACTIVE)
|
||||
{
|
||||
EXE_unwind(tdbb, request);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IDX.RDB$SEGMENT_COUNT)
|
||||
{
|
||||
/* Msg359: segments not allowed in expression index %s */
|
||||
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
||||
Arg::Gds(isc_no_segments_err) << Arg::Str(work->dfw_name));
|
||||
Arg::Gds(isc_no_segments_err) << Arg::Str(name));
|
||||
}
|
||||
if (IDX.RDB$UNIQUE_FLAG)
|
||||
idx.idx_flags |= idx_unique;
|
||||
@ -179,7 +167,7 @@ bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
idx.idx_flags |= idx_expressn;
|
||||
CMP_get_desc(tdbb, csb, idx.idx_expression, &idx.idx_expression_desc);
|
||||
idx.idx_rpt[0].idx_itype =
|
||||
DFW_assign_index_type(tdbb, work,
|
||||
DFW_assign_index_type(tdbb, name,
|
||||
idx.idx_expression_desc.dsc_dtype,
|
||||
idx.idx_expression_desc.dsc_sub_type);
|
||||
idx.idx_rpt[0].idx_selectivity = 0;
|
||||
@ -198,7 +186,7 @@ bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
{
|
||||
// Msg308: can't create index %s
|
||||
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
||||
Arg::Gds(isc_idx_create_err) << Arg::Str(work->dfw_name));
|
||||
Arg::Gds(isc_idx_create_err) << Arg::Str(name));
|
||||
}
|
||||
|
||||
// Actually create the index
|
||||
@ -210,25 +198,21 @@ bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
TRA_attach_request(transaction, idx.idx_expression_request);
|
||||
tdbb->setRequest(idx.idx_expression_request);
|
||||
|
||||
fb_assert(work->dfw_id <= dbb->dbb_max_idx);
|
||||
idx.idx_id = work->dfw_id;
|
||||
IDX_create_index(tdbb, relation, &idx, work->dfw_name.c_str(), &work->dfw_id,
|
||||
fb_assert(id <= dbb->dbb_max_idx);
|
||||
idx.idx_id = id;
|
||||
IDX_create_index(tdbb, relation, &idx, name.c_str(), &id,
|
||||
transaction, selectivity);
|
||||
fb_assert(work->dfw_id == idx.idx_id);
|
||||
fb_assert(id == idx.idx_id);
|
||||
|
||||
TRA_detach_request(idx.idx_expression_request);
|
||||
tdbb->setRequest(current_request);
|
||||
tdbb->setTransaction(current_transaction);
|
||||
|
||||
DFW_update_index(work->dfw_name.c_str(), idx.idx_id, selectivity, transaction);
|
||||
DFW_update_index(name.c_str(), idx.idx_id, selectivity, transaction);
|
||||
|
||||
// Get rid of the pool containing the expression tree
|
||||
|
||||
dbb->deletePool(new_pool);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifndef JRD_PCMET_PROTO_H
|
||||
#define JRD_PCMET_PROTO_H
|
||||
|
||||
#include "../common/classes/fb_string.h"
|
||||
|
||||
namespace Jrd {
|
||||
class DeferredWork;
|
||||
class jrd_tra;
|
||||
@ -31,7 +33,7 @@ namespace Jrd {
|
||||
struct index_desc;
|
||||
}
|
||||
|
||||
bool PCMET_expression_index(Jrd::thread_db*, SSHORT, Jrd::DeferredWork*, Jrd::jrd_tra*);
|
||||
void PCMET_expression_index(Jrd::thread_db*, const Firebird::string&, USHORT, Jrd::jrd_tra*);
|
||||
void PCMET_lookup_index(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*);
|
||||
|
||||
#endif // JRD_PCMET_PROTO_H
|
||||
|
@ -416,7 +416,7 @@ void TRA_commit(thread_db* tdbb, jrd_tra* transaction, const bool retaining_flag
|
||||
// and no events have been posted (via stored procedures etc)
|
||||
// no-op the operation.
|
||||
|
||||
if (retaining_flag && !(transaction->tra_flags & TRA_write || transaction->tra_deferred_work))
|
||||
if (retaining_flag && !(transaction->tra_flags & TRA_write || transaction->tra_deferred_job))
|
||||
{
|
||||
transaction->tra_flags &= ~TRA_prepared;
|
||||
// Get rid of all user savepoints
|
||||
|
@ -60,6 +60,7 @@ class VerbAction;
|
||||
class ArrayField;
|
||||
class Attachment;
|
||||
class DeferredWork;
|
||||
class DeferredJob;
|
||||
class dsql_opn;
|
||||
class UserManagement;
|
||||
class thread_db;
|
||||
@ -115,7 +116,7 @@ public:
|
||||
tra_memory_stats(parent_stats),
|
||||
tra_blobs_tree(p),
|
||||
tra_blobs(&tra_blobs_tree),
|
||||
tra_deferred_work(NULL),
|
||||
tra_deferred_job(NULL),
|
||||
tra_resources(*p),
|
||||
tra_context_vars(*p),
|
||||
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT),
|
||||
@ -195,7 +196,7 @@ public:
|
||||
Savepoint* tra_save_free; // free savepoints
|
||||
SLONG tra_save_point_number; // next save point number to use
|
||||
ULONG tra_flags;
|
||||
DeferredWork* tra_deferred_work; // work deferred to commit time
|
||||
DeferredJob* tra_deferred_job; // work deferred to commit time
|
||||
ResourceList tra_resources; // resource existence list
|
||||
Firebird::StringMap tra_context_vars; // Context variables for the transaction
|
||||
traRpbList* tra_rpblist; // active record_param's of given transaction
|
||||
@ -407,31 +408,6 @@ enum dfw_t {
|
||||
dfw_arg_new_name // new name
|
||||
};
|
||||
|
||||
class DeferredWork : public pool_alloc<type_dfw>
|
||||
{
|
||||
public:
|
||||
enum dfw_t dfw_type; // type of work deferred
|
||||
DeferredWork* dfw_next; // next block in transaction
|
||||
Lock* dfw_lock; // relation creation lock
|
||||
DeferredWork* dfw_args; // arguments
|
||||
SLONG dfw_sav_number; // save point number
|
||||
USHORT dfw_id; // object id, if appropriate
|
||||
USHORT dfw_count; // count of block posts
|
||||
Firebird::string dfw_name; // name of object
|
||||
|
||||
public:
|
||||
DeferredWork(MemoryPool& p, enum dfw_t t, USHORT id, SLONG sn, const char* string, USHORT length)
|
||||
: dfw_type(t), dfw_next(NULL), dfw_lock(NULL), dfw_args(NULL),
|
||||
dfw_sav_number(sn), dfw_id(id), dfw_count(1), dfw_name(p)
|
||||
{
|
||||
if (string)
|
||||
{
|
||||
dfw_name.assign(string, length);
|
||||
}
|
||||
}
|
||||
~DeferredWork();
|
||||
};
|
||||
|
||||
// Verb actions
|
||||
|
||||
class UndoItem
|
||||
|
@ -1300,8 +1300,7 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
}
|
||||
|
||||
// add index id and name (the latter is required to delete dependencies correctly)
|
||||
DeferredWork* arg = DFW_post_work_arg(transaction, work, &idx_name, id);
|
||||
arg->dfw_type = dfw_arg_index_name;
|
||||
DFW_post_work_arg(transaction, work, &idx_name, id, dfw_arg_index_name);
|
||||
|
||||
// get partner relation for FK index
|
||||
if (EVL_field(0, rpb->rpb_record, f_idx_foreign, &desc2))
|
||||
@ -1319,15 +1318,14 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
MET_lookup_partner(tdbb, r2, &idx, index_name) &&
|
||||
(partner = MET_lookup_relation_id(tdbb, idx.idx_primary_relation, false)) )
|
||||
{
|
||||
DeferredWork* arg2 = DFW_post_work_arg(transaction, work, 0, partner->rel_id);
|
||||
arg2->dfw_type = dfw_arg_partner_rel_id;
|
||||
DFW_post_work_arg(transaction, work, 0, partner->rel_id,
|
||||
dfw_arg_partner_rel_id);
|
||||
}
|
||||
else
|
||||
{ // can't find partner relation - impossible ?
|
||||
// add empty argument to let DFW know dropping
|
||||
// index was bound with FK
|
||||
DeferredWork* arg2 = DFW_post_work_arg(transaction, work, 0, 0);
|
||||
arg2->dfw_type = dfw_arg_partner_rel_id;
|
||||
DFW_post_work_arg(transaction, work, 0, 0, dfw_arg_partner_rel_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1357,8 +1355,7 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
work = DFW_post_work(transaction, dfw_delete_prm, &desc2, procedure->prc_id);
|
||||
|
||||
// procedure name to track parameter dependencies
|
||||
DeferredWork* arg = DFW_post_work_arg(transaction, work, &desc, procedure->prc_id);
|
||||
arg->dfw_type = dfw_arg_proc_name;
|
||||
DFW_post_work_arg(transaction, work, &desc, procedure->prc_id, dfw_arg_proc_name);
|
||||
}
|
||||
EVL_field(0, rpb->rpb_record, f_prm_sname, &desc2);
|
||||
DFW_post_work(transaction, dfw_delete_global, &desc2, 0);
|
||||
@ -1412,12 +1409,12 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
work = DFW_post_work(transaction, dfw_delete_trigger, &desc, 0);
|
||||
|
||||
if (!(desc2.dsc_flags & DSC_null))
|
||||
DFW_post_work_arg(transaction, work, &desc2, 0)->dfw_type = dfw_arg_rel_name;
|
||||
DFW_post_work_arg(transaction, work, &desc2, 0, dfw_arg_rel_name);
|
||||
|
||||
if (EVL_field(0, rpb->rpb_record, f_trg_type, &desc2))
|
||||
{
|
||||
DFW_post_work_arg(transaction, work, &desc2,
|
||||
MOV_get_long(&desc2, 0))->dfw_type = dfw_arg_trg_type;
|
||||
MOV_get_long(&desc2, 0), dfw_arg_trg_type);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -2246,13 +2243,12 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb,
|
||||
bool rc1 = EVL_field(0, org_rpb->rpb_record, f_fld_computed, &desc3);
|
||||
bool rc2 = EVL_field(0, new_rpb->rpb_record, f_fld_computed, &desc4);
|
||||
if (rc1 != rc2 || rc1 && MOV_compare(&desc3, &desc4)) {
|
||||
dw = DFW_post_work_arg(transaction, dw, &desc1, 0);
|
||||
dw->dfw_type = dfw_arg_force_computed;
|
||||
DFW_post_work_arg(transaction, dw, &desc1, 0, dfw_arg_force_computed);
|
||||
}
|
||||
}
|
||||
|
||||
dw = DFW_post_work(transaction, dfw_modify_field, &desc1, 0);
|
||||
DFW_post_work_arg(transaction, dw, &desc2, 0)->dfw_type = dfw_arg_new_name;
|
||||
DFW_post_work_arg(transaction, dw, &desc2, 0, dfw_arg_new_name);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2293,12 +2289,12 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb,
|
||||
DeferredWork* dw = DFW_post_work(transaction, dfw_modify_trigger, &desc1, 0);
|
||||
|
||||
if (EVL_field(0, new_rpb->rpb_record, f_trg_rname, &desc2))
|
||||
DFW_post_work_arg(transaction, dw, &desc2, 0)->dfw_type = dfw_arg_rel_name;
|
||||
DFW_post_work_arg(transaction, dw, &desc2, 0, dfw_arg_rel_name);
|
||||
|
||||
if (EVL_field(0, new_rpb->rpb_record, f_trg_type, &desc2))
|
||||
{
|
||||
DFW_post_work_arg(transaction, dw, &desc2,
|
||||
MOV_get_long(&desc2, 0))->dfw_type = dfw_arg_trg_type;
|
||||
MOV_get_long(&desc2, 0), dfw_arg_trg_type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2666,7 +2662,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
}
|
||||
|
||||
if (check_blr)
|
||||
DFW_post_work_arg(transaction, work, NULL, 0)->dfw_type = dfw_arg_check_blr;
|
||||
DFW_post_work_arg(transaction, work, NULL, 0, dfw_arg_check_blr);
|
||||
} // scope
|
||||
set_system_flag(tdbb, rpb, f_prc_sys_flag, 0);
|
||||
break;
|
||||
@ -2751,12 +2747,12 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
work = DFW_post_work(transaction, dfw_create_trigger, &desc, 0);
|
||||
|
||||
if (!(desc2.dsc_flags & DSC_null))
|
||||
DFW_post_work_arg(transaction, work, &desc2, 0)->dfw_type = dfw_arg_rel_name;
|
||||
DFW_post_work_arg(transaction, work, &desc2, 0, dfw_arg_rel_name);
|
||||
|
||||
if (EVL_field(0, rpb->rpb_record, f_trg_type, &desc2))
|
||||
{
|
||||
DFW_post_work_arg(transaction, work, &desc2,
|
||||
MOV_get_long(&desc2, 0))->dfw_type = dfw_arg_trg_type;
|
||||
MOV_get_long(&desc2, 0), dfw_arg_trg_type);
|
||||
}
|
||||
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user