8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 07:23:02 +01:00
firebird-mirror/src/jrd/req.h

392 lines
12 KiB
C
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
* MODULE: req.h
* DESCRIPTION: Request block definitions
*
* 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.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced
* exception handling in SPs/triggers,
* implemented ROWS_AFFECTED system variable
2001-05-23 15:26:42 +02:00
*/
#ifndef JRD_REQ_H
#define JRD_REQ_H
2001-05-23 15:26:42 +02:00
2001-12-24 03:51:06 +01:00
#include "../include/fb_blk.h"
#include "../jrd/exe.h"
#include "../jrd/sort.h"
#include "../jrd/Attachment.h"
#include "../jrd/JrdStatement.h"
#include "../jrd/RecordNumber.h"
2008-01-16 10:48:41 +01:00
#include "../common/classes/stack.h"
#include "../common/classes/timestamp.h"
namespace EDS {
class Statement;
2008-04-12 13:57:46 +02:00
}
2001-12-24 03:51:06 +01:00
namespace Jrd {
class Lock;
2004-03-30 06:10:52 +02:00
class Format;
class jrd_rel;
class jrd_prc;
class Record;
class ValueListNode;
template <typename T> class vec;
class jrd_tra;
class Savepoint;
class RecordSource;
class Cursor;
2006-05-22 00:07:35 +02:00
class thread_db;
2009-08-16 08:23:19 +02:00
// record parameter block
2001-05-23 15:26:42 +02:00
2008-04-19 11:42:01 +02:00
struct record_param
{
2011-05-28 04:05:45 +02:00
record_param()
: rpb_transaction_nr(0), rpb_relation(0), rpb_record(NULL), rpb_prior(NULL),
rpb_undo(NULL), rpb_format_number(0),
2011-05-28 04:05:45 +02:00
rpb_page(0), rpb_line(0),
rpb_f_page(0), rpb_f_line(0),
rpb_b_page(0), rpb_b_line(0),
rpb_address(NULL), rpb_length(0), rpb_flags(0), rpb_stream_flags(0),
rpb_org_scans(0),
rpb_window(DB_PAGE_SPACE, -1)
{
}
2009-08-16 08:23:19 +02:00
RecordNumber rpb_number; // record number in relation
2012-05-26 20:05:56 +02:00
TraNumber rpb_transaction_nr; // transaction number
2009-08-16 08:23:19 +02:00
jrd_rel* rpb_relation; // relation of record
Record* rpb_record; // final record block
Record* rpb_prior; // prior record block if this is a delta record
Record* rpb_undo; // our first version of data if this is a second modification
USHORT rpb_format_number; // format number in relation
2001-05-23 15:26:42 +02:00
ULONG rpb_page; // page number
2009-08-16 08:23:19 +02:00
USHORT rpb_line; // line number on page
2001-05-23 15:26:42 +02:00
ULONG rpb_f_page; // fragment page number
2009-08-16 08:23:19 +02:00
USHORT rpb_f_line; // fragment line number on page
2001-05-23 15:26:42 +02:00
ULONG rpb_b_page; // back page
2009-08-16 08:23:19 +02:00
USHORT rpb_b_line; // back line
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
UCHAR* rpb_address; // address of record sans header
ULONG rpb_length; // length of record
2009-08-16 08:23:19 +02:00
USHORT rpb_flags; // record ODS flags replica
USHORT rpb_stream_flags; // stream flags
SSHORT rpb_org_scans; // relation scan count at stream open
2006-05-22 00:07:35 +02:00
2008-04-19 11:42:01 +02:00
inline WIN& getWindow(thread_db* tdbb)
{
2006-05-22 00:07:35 +02:00
if (rpb_relation) {
2008-12-22 10:00:05 +01:00
rpb_window.win_page.setPageSpaceID(rpb_relation->getPages(tdbb)->rel_pg_space_id);
2006-05-22 00:07:35 +02:00
}
return rpb_window;
}
private:
2001-05-23 15:26:42 +02:00
struct win rpb_window;
};
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Record flags must be an exact replica of ODS record header flags
2001-05-23 15:26:42 +02:00
2004-05-04 00:42:47 +02:00
const USHORT rpb_deleted = 1;
const USHORT rpb_chained = 2;
const USHORT rpb_fragment = 4;
const USHORT rpb_incomplete = 8;
const USHORT rpb_blob = 16;
2008-07-01 23:36:13 +02:00
const USHORT rpb_delta = 32; // prior version is a differences record
2009-11-28 08:29:26 +01:00
// rpb_large = 64 is missing
2008-07-01 23:36:13 +02:00
const USHORT rpb_damaged = 128; // record is busted
const USHORT rpb_gc_active = 256; // garbage collecting dead record version
const USHORT rpb_uk_modified= 512; // record key field values are changed
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Stream flags
2001-05-23 15:26:42 +02:00
2011-05-28 04:05:45 +02:00
const USHORT RPB_s_refetch = 0x01; // re-fetch required due to sort
const USHORT RPB_s_update = 0x02; // input stream fetched for update
const USHORT RPB_s_no_data = 0x04; // nobody is going to access the data
const USHORT RPB_s_undo_data = 0x08; // data got from undo log
const USHORT RPB_s_sweeper = 0x10; // garbage collector - skip swept pages
2001-05-23 15:26:42 +02:00
2010-10-15 11:05:34 +02:00
const unsigned int MAX_DIFFERENCES = 1024; // Max length of generated Differences string
// between two records
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Store allocation policy types. Parameter to DPM_store()
2001-05-23 15:26:42 +02:00
2009-08-20 03:32:24 +02:00
const USHORT DPM_primary = 1; // New primary record
const USHORT DPM_secondary = 2; // Chained version of primary record
const USHORT DPM_other = 3; // Independent (or don't care) record
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Record block (holds data, remember data?)
2001-05-23 15:26:42 +02:00
class Record : public pool_alloc_rpt<SCHAR, type_rec>
2001-12-24 03:51:06 +01:00
{
public:
2008-03-10 09:16:57 +01:00
explicit Record(MemoryPool& p) : rec_pool(p), rec_precedence(p) { }
// ASF: Record is memcopied in realloc_record (vio.cpp), starting at rec_format.
// rec_precedence has destructor, so don't move it to after rec_format.
MemoryPool& rec_pool; // pool where record to be expanded
PageStack rec_precedence; // stack of higher precedence pages/transactions
2009-08-16 08:23:19 +02:00
const Format* rec_format; // what the data looks like
ULONG rec_length; // how much there is
2004-03-30 06:10:52 +02:00
const Format* rec_fmt_bk; // backup format to cope with Borland's ill null signaling
2009-08-16 08:23:19 +02:00
UCHAR rec_flags; // misc record flags
RecordNumber rec_number; // original record_param number - used for undoing multiple updates
union
{
double rec_dummy; // this is to force next field to a double boundary
UCHAR rec_data[1]; // THIS VARIABLE MUST BE ALIGNED ON A DOUBLE BOUNDARY
};
2013-03-17 18:35:53 +01:00
void setNull(USHORT id)
{
rec_data[id >> 3] |= (1 << (id & 7));
}
void clearNull(USHORT id)
{
rec_data[id >> 3] &= ~(1 << (id & 7));
}
bool isNull(USHORT id)
{
return ((rec_data[id >> 3] & (1 << (id & 7))) != 0);
}
void nullify()
{
// Zero the record buffer and initialize all fields to NULLs
const size_t null_bytes = (rec_format->fmt_count + 7) >> 3;
memset(rec_data, 0xFF, null_bytes);
memset(rec_data + null_bytes, 0, rec_length - null_bytes);
}
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2004-05-04 00:42:47 +02:00
// rec_flags
2009-08-20 03:32:24 +02:00
const UCHAR REC_same_tx = 1; // record inserted/updated and deleted by same tx
const UCHAR REC_gc_active = 2; // relation garbage collect record block in use
const UCHAR REC_new_version = 4; // savepoint created new record version and deleted it
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// List of active blobs controlled by request
typedef Firebird::BePlusTree<ULONG, ULONG, MemoryPool> TempBlobIdTree;
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Affected rows counter class
2005-06-24 14:56:34 +02:00
2008-04-19 11:42:01 +02:00
class AffectedRows
{
2005-06-24 14:56:34 +02:00
public:
AffectedRows();
void clear();
void bumpFetched();
void bumpModified(bool);
int getCount() const;
private:
bool writeFlag;
int fetchedRows;
int modifiedRows;
};
2009-08-16 08:23:19 +02:00
// request block
2001-05-23 15:26:42 +02:00
class jrd_req : public pool_alloc<type_req>
2001-12-24 03:51:06 +01:00
{
public:
jrd_req(Attachment* attachment, /*const*/ JrdStatement* aStatement,
Firebird::MemoryStats* parent_stats)
: statement(aStatement),
req_pool(statement->pool),
req_memory_stats(parent_stats),
req_blobs(req_pool),
req_stats(*req_pool),
req_base_stats(*req_pool),
req_ext_stmt(NULL),
req_cursors(*req_pool),
req_ext_resultset(NULL),
req_domain_validation(NULL),
req_auto_trans(*req_pool),
req_sorts(*req_pool),
req_rpb(*req_pool),
impureArea(*req_pool)
{
setAttachment(attachment);
req_rpb = statement->rpbsSetup;
impureArea.grow(statement->impureSize);
}
/*const*/ JrdStatement* getStatement() const
{
return statement;
}
void setAttachment(Attachment* newAttachment)
{
req_attachment = newAttachment;
charSetId = statement->flags & JrdStatement::FLAG_INTERNAL ?
CS_METADATA : req_attachment->att_charset;
}
private:
/*const*/ JrdStatement* const statement;
public:
MemoryPool* req_pool;
2009-08-16 08:23:19 +02:00
Attachment* req_attachment; // database attachment
SLONG req_id; // request identifier
USHORT req_incarnation; // incarnation number
Firebird::MemoryStats req_memory_stats;
2008-12-05 01:56:15 +01:00
// Transaction pointer and doubly linked list pointers for requests in this
// transaction. Maintained by TRA_attach_request/TRA_detach_request.
jrd_tra* req_transaction;
jrd_req* req_tra_next;
jrd_req* req_tra_prev;
2009-08-16 08:23:19 +02:00
jrd_req* req_caller; // Caller of this request
// This field may be used to reconstruct the whole call stack
TempBlobIdTree req_blobs; // Temporary BLOBs owned by this request
const StmtNode* req_message; // Current message for send/receive
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
ULONG req_records_selected; // count of records selected by request (meeting selection criteria)
ULONG req_records_inserted; // count of records inserted by request
ULONG req_records_updated; // count of records updated by request
ULONG req_records_deleted; // count of records deleted by request
RuntimeStatistics req_stats;
RuntimeStatistics req_base_stats;
2009-08-16 08:23:19 +02:00
AffectedRows req_records_affected; // records affected by the last statement
2009-08-16 08:23:19 +02:00
USHORT req_view_flags; // special flags for virtual ops on views
jrd_rel* req_top_view_store; // the top view in store(), if any
jrd_rel* req_top_view_modify; // the top view in modify(), if any
jrd_rel* req_top_view_erase; // the top view in erase(), if any
2002-06-30 12:22:51 +02:00
const StmtNode* req_next; // next node for execution
2009-08-16 08:23:19 +02:00
EDS::Statement* req_ext_stmt; // head of list of active dynamic statements
Firebird::Array<const Cursor*> req_cursors; // named cursors
ExtEngineManager::ResultSet* req_ext_resultset; // external result set
2009-08-16 08:23:19 +02:00
USHORT req_label; // label for leave
ULONG req_flags; // misc request flags
Savepoint* req_proc_sav_point; // procedure savepoint list
Firebird::TimeStamp req_timestamp; // Start time of request
2009-02-01 23:10:12 +01:00
2009-02-02 04:35:52 +01:00
Firebird::AutoPtr<Jrd::RuntimeStatistics> req_fetch_baseline; // State of request performance counters when we reported it last time
2009-04-04 18:39:31 +02:00
SINT64 req_fetch_elapsed; // Number of clock ticks spent while fetching rows for this request since we reported it last time
2009-02-01 23:10:12 +01:00
SINT64 req_fetch_rowcount; // Total number of rows returned by this request
jrd_req* req_proc_caller; // Procedure's caller request
const ValueListNode* req_proc_inputs; // and its node with input parameters
2001-05-23 15:26:42 +02:00
ULONG req_src_line;
ULONG req_src_column;
dsc* req_domain_validation; // Current VALUE for constraint validation
2008-01-16 10:48:41 +01:00
Firebird::Stack<jrd_tra*> req_auto_trans; // Autonomous transactions
SortOwner req_sorts;
Firebird::Array<record_param> req_rpb; // record parameter blocks
Firebird::Array<UCHAR> impureArea; // impure area
USHORT charSetId; // "client" character set of the request
2003-08-22 12:56:55 +02:00
enum req_ta {
// Order should be maintained because the numbers are stored in BLR
// and should be in sync with ExternalTrigger::Action.
req_trigger_insert = 1,
req_trigger_update = 2,
req_trigger_delete = 3,
req_trigger_connect = 4,
req_trigger_disconnect = 5,
req_trigger_trans_start = 6,
req_trigger_trans_commit = 7,
req_trigger_trans_rollback = 8,
req_trigger_ddl = 9
2009-08-16 08:23:19 +02:00
} req_trigger_action; // action that caused trigger to fire
2003-08-22 12:56:55 +02:00
enum req_s {
2001-05-23 15:26:42 +02:00
req_evaluate,
2001-12-24 03:51:06 +01:00
req_return,
req_receive,
req_send,
req_proceed,
req_sync,
req_unwind
2009-08-16 08:23:19 +02:00
} req_operation; // operation for next node
2001-12-24 03:51:06 +01:00
2009-08-16 08:23:19 +02:00
StatusXcp req_last_xcp; // last known exception
template <typename T> T* getImpure(unsigned offset)
{
return reinterpret_cast<T*>(&impureArea[offset]);
}
void adjustCallerStats()
{
if (req_caller) {
req_caller->req_stats.adjust(req_base_stats, req_stats);
}
req_base_stats.assign(req_stats);
}
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Flags for req_flags
2004-04-29 13:16:31 +02:00
const ULONG req_active = 0x1L;
const ULONG req_stall = 0x2L;
const ULONG req_leave = 0x4L;
2009-10-31 12:27:17 +01:00
const ULONG req_null = 0x8L;
const ULONG req_abort = 0x10L;
const ULONG req_error_handler = 0x20L; // looper is called to handle error
2009-10-31 12:27:17 +01:00
const ULONG req_warning = 0x40L;
const ULONG req_in_use = 0x80L;
const ULONG req_continue_loop = 0x100L; // PSQL continue statement
2009-12-16 19:35:55 +01:00
const ULONG req_proc_fetch = 0x200L; // Fetch from procedure in progress
const ULONG req_same_tx_upd = 0x400L; // record was updated by same transaction
const ULONG req_reserved = 0x800L; // Request reserved for client
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Flags for req_view_flags
2002-06-30 12:22:51 +02:00
enum {
req_first_store_return = 0x1,
req_first_modify_return = 0x2,
req_first_erase_return = 0x4
};
2001-05-23 15:26:42 +02:00
2009-08-16 08:23:19 +02:00
// Index lock block
2001-05-23 15:26:42 +02:00
class IndexLock : public pool_alloc<type_idl>
2001-05-23 15:26:42 +02:00
{
2007-01-21 08:46:41 +01:00
public:
2009-08-16 08:23:19 +02:00
IndexLock* idl_next; // Next index lock block for relation
Lock* idl_lock; // Lock block
jrd_rel* idl_relation; // Parent relation
USHORT idl_id; // Index id
USHORT idl_count; // Use count
2001-12-24 03:51:06 +01:00
};
2001-05-23 15:26:42 +02:00
} //namespace Jrd
#endif // JRD_REQ_H