8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-30 19:23:03 +01:00
firebird-mirror/src/jrd/Relation.h
dimitr 6ae3e2cbaf 1) Fixed CORE-4383: Index and BLOBs garbage collection doesn't work for update_in_place().
2) Applied the same approach to temporary GC records.
3) Refactored the Record class to avoid reallocations, to improve encapsulation and to simplify the code.
4) Slightly refactored UndoItem to isolate its logic from the Record class.
5) Reduced the in-memory size of the undo log.
6) Slightly better alternative to the legacy NULL reporting for outer joins.
7) Minor fixes and adjustments in BufferedStream.
2015-02-19 14:15:00 +00:00

325 lines
9.5 KiB
C++

/*
* 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): ______________________________________.
*
*
*/
#ifndef JRD_RELATION_H
#define JRD_RELATION_H
#include "../jrd/jrd.h"
#include "../jrd/pag.h"
#include "../jrd/val.h"
#include "../jrd/Attachment.h"
namespace Jrd
{
class BoolExprNode;
class RseNode;
class StmtNode;
// view context block to cache view aliases
class ViewContext
{
public:
explicit ViewContext(MemoryPool& p, const TEXT* context_name,
const TEXT* relation_name, USHORT context,
ViewContextType type)
: vcx_context_name(p, context_name, fb_strlen(context_name)),
vcx_relation_name(relation_name),
vcx_context(context),
vcx_type(type)
{
}
static USHORT generate(const ViewContext* vc)
{
return vc->vcx_context;
}
const Firebird::string vcx_context_name;
const Firebird::MetaName vcx_relation_name;
const USHORT vcx_context;
const ViewContextType vcx_type;
};
typedef Firebird::SortedArray<ViewContext*, Firebird::EmptyStorage<ViewContext*>,
USHORT, ViewContext> ViewContexts;
class RelationPages
{
public:
typedef ULONG RP_INSTANCE_ID;
vcl* rel_pages; // vector of pointer page numbers
RP_INSTANCE_ID rel_instance_id; // 0 or att_attachment_id or tra_number
// Vlad asked for this compile-time check to make sure we can contain a txn number here
typedef int RangeCheck[sizeof(RP_INSTANCE_ID) >= sizeof(TraNumber)];
SLONG rel_index_root; // index root page number
SLONG rel_data_pages; // count of relation data pages
ULONG rel_slot_space; // lowest pointer page with slot space
ULONG rel_pri_data_space; // lowest pointer page with primary data page space
ULONG rel_sec_data_space; // lowest pointer page with secondary data page space
USHORT rel_pg_space_id;
RelationPages()
{
rel_pages = 0;
rel_index_root = rel_data_pages = 0;
rel_instance_id = 0;
rel_slot_space = rel_pri_data_space = rel_sec_data_space = 0;
rel_pg_space_id = DB_PAGE_SPACE;
rel_next_free = 0;
useCount = 0;
}
inline SLONG addRef()
{
return useCount++;
}
void free(RelationPages*& nextFree);
static inline ULONG generate(const RelationPages* item)
{
return item->rel_instance_id;
}
private:
RelationPages* rel_next_free;
SLONG useCount;
friend class jrd_rel;
};
// Primary dependencies from all foreign references to relation's
// primary/unique keys
struct prim
{
vec<int>* prim_reference_ids;
vec<int>* prim_relations;
vec<int>* prim_indexes;
};
// Foreign references to other relations' primary/unique keys
struct frgn
{
vec<int>* frgn_reference_ids;
vec<int>* frgn_relations;
vec<int>* frgn_indexes;
};
// Relation block; one is created for each relation referenced
// in the database, though it is not really filled out until
// the relation is scanned
class jrd_rel : public pool_alloc<type_rel>
{
typedef Firebird::HalfStaticArray<Record*, 4> GCRecordList;
public:
MemoryPool* rel_pool;
USHORT rel_id;
USHORT rel_current_fmt; // Current format number
ULONG rel_flags;
Format* rel_current_format; // Current record format
Firebird::MetaName rel_name; // ascii relation name
vec<Format*>* rel_formats; // Known record formats
Firebird::MetaName rel_owner_name; // ascii owner
vec<jrd_fld*>* rel_fields; // vector of field blocks
RseNode* rel_view_rse; // view record select expression
ViewContexts rel_view_contexts; // sorted array of view contexts
Firebird::MetaName rel_security_name; // security class name for relation
ExternalFile* rel_file; // external file name
GCRecordList rel_gc_records; // records for garbage collection
USHORT rel_use_count; // requests compiled with relation
USHORT rel_sweep_count; // sweep and/or garbage collector threads active
SSHORT rel_scan_count; // concurrent sequential scan count
Lock* rel_existence_lock; // existence lock, if any
Lock* rel_partners_lock; // partners lock
Lock* rel_rescan_lock; // lock forcing relation to be scanned
IndexLock* rel_index_locks; // index existence locks
IndexBlock* rel_index_blocks; // index blocks for caching index info
trig_vec* rel_pre_erase; // Pre-operation erase trigger
trig_vec* rel_post_erase; // Post-operation erase trigger
trig_vec* rel_pre_modify; // Pre-operation modify trigger
trig_vec* rel_post_modify; // Post-operation modify trigger
trig_vec* rel_pre_store; // Pre-operation store trigger
trig_vec* rel_post_store; // Post-operation store trigger
prim rel_primary_dpnds; // foreign dependencies on this relation's primary key
frgn rel_foreign_refs; // foreign references to other relations' primary keys
Firebird::Mutex rel_drop_mutex;
bool isSystem() const;
bool isTemporary() const;
bool isVirtual() const;
bool isView() const;
// global temporary relations attributes
RelationPages* getPages(thread_db* tdbb, TraNumber tran = MAX_TRA_NUMBER, bool allocPages = true);
RelationPages* getBasePages()
{
return &rel_pages_base;
}
bool delPages(thread_db* tdbb, TraNumber tran = MAX_TRA_NUMBER, RelationPages* aPages = NULL);
void getRelLockKey(thread_db* tdbb, UCHAR* key);
USHORT getRelLockKeyLength() const;
void cleanUp();
class RelPagesSnapshot : public Firebird::Array<RelationPages*>
{
public:
typedef Firebird::Array<RelationPages*> inherited;
RelPagesSnapshot(thread_db* tdbb, jrd_rel* relation)
{
spt_tdbb = tdbb;
spt_relation = relation;
}
~RelPagesSnapshot() { clear(); }
void clear();
private:
thread_db* spt_tdbb;
jrd_rel* spt_relation;
friend class jrd_rel;
};
void fillPagesSnapshot(RelPagesSnapshot&, const bool AttachmentOnly = false);
private:
typedef Firebird::SortedArray<
RelationPages*,
Firebird::EmptyStorage<RelationPages*>,
ULONG, // This type should be able to hold a TraNumber value
RelationPages>
RelationPagesInstances;
// Vlad asked for this compile-time check to make sure we can contain a txn number here
typedef int RangeCheck[sizeof(ULONG) >= sizeof(TraNumber)];
RelationPagesInstances* rel_pages_inst;
RelationPages rel_pages_base;
RelationPages* rel_pages_free;
RelationPages* getPagesInternal(thread_db* tdbb, TraNumber tran, bool allocPages);
public:
explicit jrd_rel(MemoryPool& p)
: rel_pool(&p), rel_name(p), rel_owner_name(p),
rel_view_contexts(p), rel_security_name(p), rel_gc_records(p)
{}
bool hasTriggers() const;
};
// rel_flags
const ULONG REL_scanned = 0x0001; // Field expressions scanned (or being scanned)
const ULONG REL_system = 0x0002;
const ULONG REL_deleted = 0x0004; // Relation known gonzo
const ULONG REL_get_dependencies = 0x0008; // New relation needs dependencies during scan
const ULONG REL_force_scan = 0x0010; // system relation has been updated since ODS change, force a scan
const ULONG REL_check_existence = 0x0020; // Existence lock released pending drop of relation
const ULONG REL_blocking = 0x0040; // Blocking someone from dropping relation
const ULONG REL_sys_triggers = 0x0080; // The relation has system triggers to compile
const ULONG REL_sql_relation = 0x0100; // Relation defined as sql table
const ULONG REL_check_partners = 0x0200; // Rescan primary dependencies and foreign references
const ULONG REL_being_scanned = 0x0400; // relation scan in progress
const ULONG REL_sys_trigs_being_loaded = 0x0800; // System triggers being loaded
const ULONG REL_deleting = 0x1000; // relation delete in progress
const ULONG REL_temp_tran = 0x2000; // relation is a GTT delete rows
const ULONG REL_temp_conn = 0x4000; // relation is a GTT preserve rows
const ULONG REL_virtual = 0x8000; // relation is virtual
const ULONG REL_jrd_view = 0x10000; // relation is VIEW
inline bool jrd_rel::isSystem() const
{
return rel_flags & REL_system;
}
inline bool jrd_rel::isTemporary() const
{
return (rel_flags & (REL_temp_tran | REL_temp_conn));
}
inline bool jrd_rel::isVirtual() const
{
return (rel_flags & REL_virtual);
}
inline bool jrd_rel::isView() const
{
return (rel_flags & REL_jrd_view);
}
inline RelationPages* jrd_rel::getPages(thread_db* tdbb, TraNumber tran, bool allocPages)
{
if (!isTemporary())
return &rel_pages_base;
return getPagesInternal(tdbb, tran, allocPages);
}
// Field block, one for each field in a scanned relation
class jrd_fld : public pool_alloc<type_fld>
{
public:
BoolExprNode* fld_validation; // validation clause, if any
BoolExprNode* fld_not_null; // if field cannot be NULL
ValueExprNode* fld_missing_value; // missing value, if any
ValueExprNode* fld_computation; // computation for virtual field
ValueExprNode* fld_source; // source for view fields
ValueExprNode* fld_default_value; // default value, if any
ArrayField* fld_array; // array description, if array
Firebird::MetaName fld_name; // Field name
Firebird::MetaName fld_security_name; // security class name for field
Firebird::MetaName fld_generator_name; // identity generator name
public:
explicit jrd_fld(MemoryPool& p)
: fld_name(p), fld_security_name(p), fld_generator_name(p)
{ }
};
}
#endif // JRD_RELATION_H