mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-30 19:23:03 +01:00
6ae3e2cbaf
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.
325 lines
9.5 KiB
C++
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
|