8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 10:03:03 +01:00
firebird-mirror/src/jrd/recsrc/RecordSource.h

1026 lines
27 KiB
C
Raw Normal View History

/*
* 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 Dmitry Yemanov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2009 Dmitry Yemanov <dimitr@firebirdsql.org>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef JRD_RECORD_SOURCE_H
#define JRD_RECORD_SOURCE_H
#include "../common/classes/array.h"
#include "../jrd/req.h"
#include "../jrd/rse.h"
#include "../jrd/inf_pub.h"
namespace Ods
{
struct btree_page;
}
namespace Jrd
{
class thread_db;
class jrd_req;
class jrd_nod;
class jrd_prc;
2010-02-15 01:43:04 +01:00
class AggNode;
class Sort;
class CompilerScratch;
class RecordBuffer;
class BtrPageGCLock;
struct index_desc;
struct record_param;
struct temporary_key;
struct win;
class BaseBufferedStream;
class BufferedStream;
2009-12-13 13:08:02 +01:00
typedef Firebird::HalfStaticArray<UCHAR, OPT_STATIC_ITEMS> StreamsArray;
// Abstract base class
class RecordSource
{
public:
virtual void open(thread_db* tdbb) const = 0;
virtual void close(thread_db* tdbb) const = 0;
virtual bool getRecord(thread_db* tdbb) const = 0;
virtual bool refetchRecord(thread_db* tdbb) const = 0;
virtual bool lockRecord(thread_db* tdbb) const = 0;
virtual void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const = 0;
virtual void markRecursive() = 0;
virtual void invalidateRecords(jrd_req* request) const = 0;
virtual void findUsedStreams(StreamsArray& streams) const = 0;
virtual void nullRecords(thread_db* tdbb) const = 0;
virtual void saveRecords(thread_db* tdbb) const = 0;
virtual void restoreRecords(thread_db* tdbb) const = 0;
2009-12-15 14:55:35 +01:00
virtual ~RecordSource();
static bool rejectDuplicate(const UCHAR* /*data1*/, const UCHAR* /*data2*/, void* /*userArg*/)
{
return true;
}
protected:
// Generic impure block
struct Impure
{
ULONG irsb_flags;
};
static const ULONG irsb_open = 1;
static const ULONG irsb_first = 2;
static const ULONG irsb_joined = 4;
static const ULONG irsb_mustread = 8;
2009-12-14 10:23:27 +01:00
static const ULONG irsb_singular_processed = 16;
RecordSource()
: m_impure(0), m_recursive(false)
{}
2009-12-10 02:32:47 +01:00
static void dumpName(thread_db* tdbb, const Firebird::string& name,
Firebird::UCharBuffer& buffer);
static void dumpInversion(thread_db* tdbb, const jrd_nod* inversion,
Firebird::UCharBuffer& buffer);
static void saveRecord(thread_db* tdbb, record_param* rpb);
static void restoreRecord(thread_db* tdbb, record_param* rpb);
ULONG m_impure;
bool m_recursive;
};
// Helper class implementing some common methods
class RecordStream : public RecordSource
{
public:
RecordStream(CompilerScratch* csb, UCHAR stream, Format* format = NULL);
virtual bool refetchRecord(thread_db* tdbb) const;
virtual bool lockRecord(thread_db* tdbb) const;
virtual void markRecursive();
virtual void invalidateRecords(jrd_req* request) const;
virtual void findUsedStreams(StreamsArray& streams) const;
virtual void nullRecords(thread_db* tdbb) const;
virtual void saveRecords(thread_db* tdbb) const;
virtual void restoreRecords(thread_db* tdbb) const;
protected:
const UCHAR m_stream;
2010-07-06 13:09:32 +02:00
const Format* const m_format;
};
// Helper class to make const-correct nested record sources
template <typename T = RecordSource>
class NestedSource
{
public:
NestedSource(T* source)
: m_source(source)
{
}
NestedSource<T>& operator =(T* source)
{
m_source = source;
return *this;
}
operator T*() { return m_source; }
operator const T*() const { return m_source; }
T* operator ->() { return m_source; }
const T* operator ->() const { return m_source; }
private:
T* m_source;
};
// Primary (table scan) access methods
class FullTableScan : public RecordStream
{
public:
FullTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
private:
const Firebird::string m_name;
};
class BitmapTableScan : public RecordStream
{
struct Impure : public RecordSource::Impure
{
RecordBitmap** irsb_bitmap;
};
public:
2009-12-10 02:32:47 +01:00
BitmapTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream,
jrd_nod* inversion);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
private:
const Firebird::string m_name;
jrd_nod* const m_inversion;
};
class IndexTableScan : public RecordStream
{
struct Impure : public RecordSource::Impure
{
RecordNumber irsb_nav_number; // last record number
SLONG irsb_nav_page; // index page number
SLONG irsb_nav_incarnation; // buffer/page incarnation counter
RecordBitmap** irsb_nav_bitmap; // bitmap for inversion tree
RecordBitmap* irsb_nav_records_visited; // bitmap of records already retrieved
BtrPageGCLock* irsb_nav_btr_gc_lock; // lock to prevent removal of currently walked index page
USHORT irsb_nav_offset; // page offset of current index node
USHORT irsb_nav_lower_length; // length of lower key value
USHORT irsb_nav_upper_length; // length of upper key value
USHORT irsb_nav_length; // length of expanded key
UCHAR irsb_nav_data[1]; // expanded key, upper bound, and index desc
};
public:
2009-12-10 02:32:47 +01:00
IndexTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream,
jrd_nod* index, USHORT keyLength);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void setInversion(jrd_nod* inversion)
{
fb_assert(!m_inversion);
m_inversion = inversion;
}
private:
int compareKeys(const index_desc*, const UCHAR*, USHORT, const temporary_key*, USHORT) const;
bool findSavedNode(thread_db* tdbb, Impure* impure, win* window, UCHAR**) const;
UCHAR* getPosition(thread_db* tdbb, Impure* impure, win* window) const;
UCHAR* openStream(thread_db* tdbb, Impure* impure, win* window) const;
void setPage(thread_db* tdbb, Impure* impure, win* window) const;
void setPosition(thread_db* tdbb, Impure* impure, record_param*,
win* window, const UCHAR*, const temporary_key&) const;
bool setupBitmaps(thread_db* tdbb, Impure* impure) const;
const Firebird::string m_name;
jrd_nod* const m_index;
jrd_nod* m_inversion;
2010-03-11 12:40:41 +01:00
const size_t m_length;
size_t m_offset;
};
class ExternalTableScan : public RecordStream
{
struct Impure : public RecordSource::Impure
{
FB_UINT64 irsb_position;
};
public:
ExternalTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
private:
const Firebird::string m_name;
};
class VirtualTableScan : public RecordStream
{
struct Impure : public RecordSource::Impure
{
RecordBuffer* irsb_record_buffer;
};
public:
VirtualTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
private:
const Firebird::string m_name;
};
class UsersTableScan : public RecordStream
{
struct Impure : public RecordSource::Impure
{
RecordBuffer* irsb_record_buffer;
};
public:
UsersTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
private:
const Firebird::string m_name;
};
class ProcedureScan : public RecordStream
{
struct Impure : public RecordSource::Impure
{
jrd_req* irsb_req_handle;
VaryingString* irsb_message;
};
public:
ProcedureScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream,
jrd_prc* procedure, jrd_nod* inputs, jrd_nod* message);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
private:
void assignParams(thread_db* tdbb, const dsc* from_desc, const dsc* flag_desc,
const UCHAR* msg, const dsc* to_desc, SSHORT to_id, Record* record) const;
const Firebird::string m_name;
2010-07-06 13:09:32 +02:00
const jrd_prc* const m_procedure;
jrd_nod* const m_inputs;
jrd_nod* const m_message;
};
// Filtering (one -> one) access methods
class SingularStream : public RecordSource
{
public:
SingularStream(CompilerScratch* csb, RecordSource* next);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
2010-07-06 13:09:32 +02:00
NestedSource<> m_next;
};
class LockedStream : public RecordSource
{
public:
LockedStream(CompilerScratch* csb, RecordSource* next);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
2010-07-06 13:09:32 +02:00
NestedSource<> m_next;
};
class FirstRowsStream : public RecordSource
{
struct Impure : public RecordSource::Impure
{
SINT64 irsb_count;
};
public:
FirstRowsStream(CompilerScratch* csb, RecordSource* next, jrd_nod* value);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
2010-07-06 13:09:32 +02:00
NestedSource<> m_next;
jrd_nod* const m_value;
};
class SkipRowsStream : public RecordSource
{
struct Impure : public RecordSource::Impure
{
SINT64 irsb_count;
};
public:
SkipRowsStream(CompilerScratch* csb, RecordSource* next, jrd_nod* value);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
2010-07-06 13:09:32 +02:00
NestedSource<> m_next;
jrd_nod* const m_value;
};
class FilteredStream : public RecordSource
{
public:
FilteredStream(CompilerScratch* csb, RecordSource* next, jrd_nod* boolean);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
void setAnyBoolean(jrd_nod* anyBoolean, bool ansiAny, bool ansiNot)
{
fb_assert(!m_anyBoolean);
m_anyBoolean = anyBoolean;
2009-12-10 02:32:47 +01:00
m_ansiAny = ansiAny;
m_ansiAll = !ansiAny;
m_ansiNot = ansiNot;
}
private:
bool evaluateBoolean(thread_db* tdbb) const;
2010-07-06 13:09:32 +02:00
NestedSource<> m_next;
jrd_nod* const m_boolean;
jrd_nod* m_anyBoolean;
bool m_ansiAny;
bool m_ansiAll;
bool m_ansiNot;
};
class SortedStream : public RecordSource
{
struct Impure : public RecordSource::Impure
{
Sort* irsb_sort;
};
public:
2009-12-12 21:36:56 +01:00
static const USHORT FLAG_PROJECT = 0x1; // sort is really a project
static const USHORT FLAG_UNIQUE = 0x2; // sorts using unique key - for distinct and group by
// Special values for SortMap::Item::fieldId.
static const SSHORT ID_DBKEY = -1; // dbkey value
static const SSHORT ID_DBKEY_VALID = -2; // dbkey valid flag
static const SSHORT ID_TRANS = -3; // transaction id of record
// Sort map block
2009-12-12 21:56:12 +01:00
class SortMap : public Firebird::PermanentStorage
2009-12-12 21:36:56 +01:00
{
public:
struct Item
{
void clear()
{
desc.clear();
flagOffset = stream = fieldId = 0;
node = NULL;
}
dsc desc; // relative descriptor
USHORT flagOffset; // offset of missing flag
USHORT stream; // stream for field id
SSHORT fieldId; // id for field (or ID constants)
jrd_nod* node; // expression node
};
2009-12-13 11:41:53 +01:00
explicit SortMap(MemoryPool& p)
2009-12-12 21:56:12 +01:00
: PermanentStorage(p),
length(0),
keyLength(0),
flags(0),
2009-12-12 21:56:12 +01:00
keyItems(p),
2009-12-12 21:36:56 +01:00
items(p)
{
}
USHORT length; // sort record length
USHORT keyLength; // key length in longwords
USHORT flags; // misc sort flags
Firebird::Array<sort_key_def> keyItems; // address of key descriptors
Firebird::Array<Item> items;
};
SortedStream(CompilerScratch* csb, RecordSource* next, SortMap* map);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
USHORT getLength() const
{
2009-12-12 21:36:56 +01:00
return m_map->length;
}
USHORT getKeyLength() const
{
2009-12-12 21:36:56 +01:00
return m_map->keyLength;
}
UCHAR* getData(thread_db* tdbb) const;
void mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const;
private:
Sort* init(thread_db* tdbb) const;
2010-07-06 13:09:32 +02:00
NestedSource<> m_next;
const SortMap* const m_map;
};
// Make moves in a window without going out of partition boundaries.
class SlidingWindow
{
public:
2010-07-06 13:09:32 +02:00
SlidingWindow(thread_db* aTdbb, const BaseBufferedStream* aStream, jrd_nod* aGroup, jrd_req* aRequest);
~SlidingWindow();
bool move(SINT64 delta);
private:
thread_db* tdbb;
2010-07-06 13:09:32 +02:00
const BaseBufferedStream* const stream;
jrd_nod* group;
jrd_req* request;
Firebird::Array<impure_value> partitionKeys;
bool moved;
FB_UINT64 savedPosition;
};
class AggregatedStream : public RecordStream
{
2009-12-10 02:32:47 +01:00
enum State
{
STATE_PROCESS_EOF = 0, // We processed everything now process (EOF)
STATE_PENDING, // Values are pending from a prior fetch
STATE_EOF_FOUND, // We encountered EOF from the last attempted fetch
STATE_GROUPING // Entering EVL group before fetching the first record
2009-12-10 02:32:47 +01:00
};
struct Impure : public RecordSource::Impure
{
2009-12-10 02:32:47 +01:00
State state;
FB_UINT64 pending;
};
public:
AggregatedStream(CompilerScratch* csb, UCHAR stream, jrd_nod* const group,
jrd_nod* const map, BaseBufferedStream* next, jrd_nod* order);
AggregatedStream(CompilerScratch* csb, UCHAR stream, jrd_nod* const group,
jrd_nod* const map, RecordSource* next);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
private:
2010-02-15 01:43:04 +01:00
void init(CompilerScratch* csb);
State evaluateGroup(thread_db* tdbb, State state) const;
void finiDistinct(thread_db* tdbb, jrd_req* request) const;
2010-07-06 13:09:32 +02:00
NestedSource<BaseBufferedStream> m_bufferedStream;
NestedSource<> m_next;
jrd_nod* const m_group;
jrd_nod* const m_map;
jrd_nod* const m_order;
2010-02-15 01:43:04 +01:00
Firebird::Array<const jrd_nod*> m_winPassMap;
};
class WindowedStream : public RecordSource
{
public:
WindowedStream(CompilerScratch* csb, const jrd_nod* nodWindows, RecordSource* next);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
2010-07-06 13:09:32 +02:00
NestedSource<BufferedStream> m_next;
NestedSource<> m_joinedStream;
};
// Abstract class for different implementations of buffered streams.
class BaseBufferedStream : public RecordSource
{
public:
2010-07-06 13:09:32 +02:00
virtual void locate(thread_db* tdbb, FB_UINT64 position) const = 0;
virtual FB_UINT64 getCount(jrd_req* request) const = 0;
virtual FB_UINT64 getPosition(jrd_req* request) const = 0;
};
class BufferedStream : public BaseBufferedStream
{
struct FieldMap
{
2009-12-14 13:56:27 +01:00
static const UCHAR REGULAR_FIELD = 1;
static const UCHAR TRANSACTION_ID = 2;
static const UCHAR DBKEY_NUMBER = 3;
static const UCHAR DBKEY_VALID = 4;
2009-12-14 13:56:27 +01:00
FieldMap() : map_type(0), map_stream(0), map_id(0)
{}
FieldMap(UCHAR type, UCHAR stream, ULONG id)
: map_type(type), map_stream(stream), map_id(id)
{}
UCHAR map_type;
UCHAR map_stream;
USHORT map_id;
};
struct Impure : public RecordSource::Impure
{
RecordBuffer* irsb_buffer;
FB_UINT64 irsb_position;
};
public:
BufferedStream(CompilerScratch* csb, RecordSource* next);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
2010-07-06 13:09:32 +02:00
void locate(thread_db* tdbb, FB_UINT64 position) const;
FB_UINT64 getCount(jrd_req* request) const;
FB_UINT64 getPosition(jrd_req* request) const
{
Impure* const impure = request->getImpure<Impure>(m_impure);
return impure->irsb_position;
}
private:
2010-07-06 13:09:32 +02:00
NestedSource<> m_next;
Firebird::HalfStaticArray<FieldMap, OPT_STATIC_ITEMS> m_map;
2010-07-06 13:09:32 +02:00
const Format* m_format;
};
// Multiplexing (many -> one) access methods
class NestedLoopJoin : public RecordSource
{
public:
NestedLoopJoin(CompilerScratch* csb, size_t count, RecordSource* const* args);
NestedLoopJoin(CompilerScratch* csb, RecordSource* outer, RecordSource* inner,
jrd_nod* boolean, bool semiJoin, bool antiJoin);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
bool fetchRecord(thread_db*, size_t) const;
const bool m_outerJoin;
const bool m_semiJoin;
const bool m_antiJoin;
2010-07-06 13:09:32 +02:00
Firebird::Array<NestedSource<> > m_args;
jrd_nod* const m_boolean;
};
class FullOuterJoin : public RecordSource
{
public:
FullOuterJoin(CompilerScratch* csb, RecordSource* arg1, RecordSource* arg2);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
2010-07-06 13:09:32 +02:00
NestedSource<> m_arg1;
NestedSource<> m_arg2;
};
class HashJoin : public RecordSource
{
class HashTable;
2010-01-12 15:21:30 +01:00
struct Impure : public RecordSource::Impure
{
HashTable* irsb_hash_table;
};
public:
HashJoin(CompilerScratch* csb, size_t count,
RecordSource* const* args, jrd_nod* const* keys);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
size_t hashKeys(thread_db* tdbb, jrd_req* request, HashTable* table, jrd_nod* keys) const;
bool compareKeys(thread_db* tdbb, jrd_req* request) const;
bool fetchRecord(thread_db* tdbb, HashTable* table, size_t stream) const;
RecordSource* m_leader;
jrd_nod* m_leaderKeys;
Firebird::Array<BufferedStream*> m_args;
Firebird::Array<jrd_nod*> m_keys;
2010-01-12 15:21:30 +01:00
const bool m_outerJoin;
const bool m_semiJoin;
const bool m_antiJoin;
};
class MergeJoin : public RecordSource
{
struct MergeFile
{
TempSpace* mfb_space; // merge file uses SORT I/O routines
ULONG mfb_equal_records; // equality group cardinality
ULONG mfb_record_size; // matches sort map length
ULONG mfb_current_block; // current merge block in buffer
ULONG mfb_block_size; // merge block I/O size
ULONG mfb_blocking_factor; // merge equality records per block
UCHAR* mfb_block_data; // merge block I/O buffer
};
struct Impure : public RecordSource::Impure
{
USHORT irsb_mrg_count; // next stream in group
struct irsb_mrg_repeat
{
SLONG irsb_mrg_equal; // queue of equal records
SLONG irsb_mrg_equal_end; // end of the equal queue
SLONG irsb_mrg_equal_current; // last fetched record from equal queue
SLONG irsb_mrg_last_fetched; // first sort merge record of next group
SSHORT irsb_mrg_order; // logical merge order by substream
MergeFile irsb_mrg_file; // merge equivalence file
} irsb_mrg_rpt[1];
};
static const size_t MERGE_BLOCK_SIZE = 65536;
public:
MergeJoin(CompilerScratch* csb, size_t count,
SortedStream* const* args, jrd_nod* const* keys);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
void findUsedStreams(StreamsArray& streams) const;
void nullRecords(thread_db* tdbb) const;
void saveRecords(thread_db* tdbb) const;
void restoreRecords(thread_db* tdbb) const;
private:
int compare(thread_db* tdbb, jrd_nod* node1, jrd_nod* node2) const;
UCHAR* getData(thread_db* tdbb, MergeFile* mfb, SLONG record) const;
SLONG getRecord(thread_db* tdbb, size_t index) const;
bool fetchRecord(thread_db* tdbb, size_t index) const;
Firebird::Array<SortedStream*> m_args;
Firebird::Array<jrd_nod*> m_keys;
};
class Union : public RecordStream
{
struct Impure : public RecordSource::Impure
{
USHORT irsb_count;
};
public:
Union(CompilerScratch* csb, UCHAR stream,
size_t argCount, RecordSource* const* args, jrd_nod* const* maps,
size_t streamCount, const UCHAR* streams);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
private:
Firebird::Array<RecordSource*> m_args;
Firebird::Array<jrd_nod*> m_maps;
StreamsArray m_streams;
};
class RecursiveStream : public RecordStream
{
static const size_t MAX_RECURSE_LEVEL = 1024;
enum Mode { ROOT, RECURSE };
struct Impure: public RecordSource::Impure
{
USHORT irsb_level;
Mode irsb_mode;
UCHAR* irsb_stack;
UCHAR* irsb_data;
};
public:
RecursiveStream(CompilerScratch* csb, UCHAR stream, UCHAR mapStream,
RecordSource* root, RecordSource* inner,
jrd_nod* rootMap, jrd_nod* innerMap,
size_t streamCount, const UCHAR* innerStreams,
2010-01-22 09:23:36 +01:00
size_t saveOffset);
void open(thread_db* tdbb) const;
void close(thread_db* tdbb) const;
bool getRecord(thread_db* tdbb) const;
bool refetchRecord(thread_db* tdbb) const;
bool lockRecord(thread_db* tdbb) const;
void dump(thread_db* tdbb, Firebird::UCharBuffer& buffer) const;
void markRecursive();
void invalidateRecords(jrd_req* request) const;
private:
const UCHAR m_mapStream;
RecordSource* const m_root;
RecordSource* const m_inner;
jrd_nod* const m_rootMap;
jrd_nod* const m_innerMap;
StreamsArray m_innerStreams;
2010-01-26 09:20:27 +01:00
const size_t m_saveOffset;
2010-01-22 09:23:36 +01:00
size_t m_saveSize;
};
} // namespace
#endif // JRD_RECORD_SOURCE_H