2009-12-09 19:45:44 +01:00
|
|
|
/*
|
|
|
|
* 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"
|
2010-10-12 13:36:51 +02:00
|
|
|
#include "../common/classes/objects_array.h"
|
2010-08-09 17:48:51 +02:00
|
|
|
#include "../common/classes/NestConst.h"
|
2010-10-12 13:36:51 +02:00
|
|
|
#include "../jrd/RecordSourceNodes.h"
|
2010-04-05 23:20:08 +02:00
|
|
|
#include "../jrd/req.h"
|
2009-12-09 19:45:44 +01:00
|
|
|
#include "../jrd/rse.h"
|
|
|
|
#include "../jrd/inf_pub.h"
|
|
|
|
|
|
|
|
namespace Jrd
|
|
|
|
{
|
|
|
|
class thread_db;
|
|
|
|
class jrd_req;
|
|
|
|
class jrd_prc;
|
2010-02-15 01:43:04 +01:00
|
|
|
class AggNode;
|
2010-10-12 13:36:51 +02:00
|
|
|
class BoolExprNode;
|
2010-03-16 12:19:29 +01:00
|
|
|
class Sort;
|
2009-12-09 19:45:44 +01:00
|
|
|
class CompilerScratch;
|
|
|
|
class RecordBuffer;
|
|
|
|
class BtrPageGCLock;
|
|
|
|
struct index_desc;
|
|
|
|
struct record_param;
|
|
|
|
struct temporary_key;
|
|
|
|
struct win;
|
2010-02-16 01:26:53 +01:00
|
|
|
class BaseBufferedStream;
|
2010-01-18 22:37:47 +01:00
|
|
|
class BufferedStream;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
// Abstract base class
|
|
|
|
|
|
|
|
class RecordSource
|
|
|
|
{
|
|
|
|
public:
|
2010-07-05 20:37:35 +02:00
|
|
|
virtual void open(thread_db* tdbb) const = 0;
|
|
|
|
virtual void close(thread_db* tdbb) const = 0;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
virtual bool getRecord(thread_db* tdbb) const = 0;
|
|
|
|
virtual bool refetchRecord(thread_db* tdbb) const = 0;
|
|
|
|
virtual bool lockRecord(thread_db* tdbb) const = 0;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
virtual void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const = 0;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
virtual void markRecursive() = 0;
|
2010-07-05 20:37:35 +02:00
|
|
|
virtual void invalidateRecords(jrd_req* request) const = 0;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
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-09 19:45:44 +01:00
|
|
|
|
2009-12-15 14:55:35 +01:00
|
|
|
virtual ~RecordSource();
|
|
|
|
|
2010-02-13 21:29:29 +01:00
|
|
|
static bool rejectDuplicate(const UCHAR* /*data1*/, const UCHAR* /*data2*/, void* /*userArg*/)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
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;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
RecordSource()
|
|
|
|
: m_impure(0), m_recursive(false)
|
|
|
|
{}
|
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
static Firebird::string printName(thread_db* tdbb, const Firebird::string& name);
|
|
|
|
static Firebird::string printIndent(unsigned level);
|
|
|
|
static void printInversion(thread_db* tdbb, const InversionNode* inversion,
|
|
|
|
Firebird::string& plan, bool detailed, unsigned level, bool navigation = false);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
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:
|
2010-10-12 13:36:51 +02:00
|
|
|
RecordStream(CompilerScratch* csb, UCHAR stream, const Format* format = NULL);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
virtual bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
virtual bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
virtual void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
virtual void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
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;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
const UCHAR m_stream;
|
2010-07-06 13:09:32 +02:00
|
|
|
const Format* const m_format;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
// Primary (table scan) access methods
|
|
|
|
|
|
|
|
class FullTableScan : public RecordStream
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FullTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
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,
|
2010-10-12 13:36:51 +02:00
|
|
|
InversionNode* inversion);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
const Firebird::string m_name;
|
2010-10-12 13:36:51 +02:00
|
|
|
NestConst<InversionNode> const m_inversion;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
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
|
2010-03-16 07:26:41 +01:00
|
|
|
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
|
2009-12-09 19:45:44 +01:00
|
|
|
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,
|
2010-10-12 13:36:51 +02:00
|
|
|
InversionNode* index, USHORT keyLength);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-10-12 13:36:51 +02:00
|
|
|
void setInversion(InversionNode* inversion)
|
2009-12-09 19:45:44 +01:00
|
|
|
{
|
|
|
|
fb_assert(!m_inversion);
|
|
|
|
m_inversion = inversion;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2010-07-05 20:37:35 +02:00
|
|
|
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;
|
2010-03-16 07:26:41 +01:00
|
|
|
void setPosition(thread_db* tdbb, Impure* impure, record_param*,
|
2010-07-05 20:37:35 +02:00
|
|
|
win* window, const UCHAR*, const temporary_key&) const;
|
|
|
|
bool setupBitmaps(thread_db* tdbb, Impure* impure) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
const Firebird::string m_name;
|
2010-10-12 13:36:51 +02:00
|
|
|
NestConst<InversionNode> const m_index;
|
|
|
|
NestConst<InversionNode> m_inversion;
|
2010-03-11 12:40:41 +01:00
|
|
|
const size_t m_length;
|
|
|
|
size_t m_offset;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class ExternalTableScan : public RecordStream
|
|
|
|
{
|
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
|
|
|
FB_UINT64 irsb_position;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
ExternalTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
const Firebird::string m_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
class VirtualTableScan : public RecordStream
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
VirtualTableScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-13 14:31:35 +02:00
|
|
|
protected:
|
|
|
|
virtual bool retrieveRecord(thread_db* tdbb, jrd_rel* relation,
|
|
|
|
FB_UINT64 position, Record* record) const = 0;
|
2010-07-09 14:51:05 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
const Firebird::string m_name;
|
|
|
|
};
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
class ProcedureScan : public RecordStream
|
|
|
|
{
|
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
|
|
|
jrd_req* irsb_req_handle;
|
|
|
|
VaryingString* irsb_message;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2009-12-10 16:27:17 +01:00
|
|
|
ProcedureScan(CompilerScratch* csb, const Firebird::string& name, UCHAR stream,
|
2010-11-21 04:47:29 +01:00
|
|
|
const jrd_prc* procedure, const ValueListNode* sourceList,
|
2010-12-04 23:15:03 +01:00
|
|
|
const ValueListNode* targetList, MessageNode* message);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
void assignParams(thread_db* tdbb, const dsc* from_desc, const dsc* flag_desc,
|
2010-07-05 20:37:35 +02:00
|
|
|
const UCHAR* msg, const dsc* to_desc, SSHORT to_id, Record* record) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2009-12-10 16:27:17 +01:00
|
|
|
const Firebird::string m_name;
|
2010-07-06 13:09:32 +02:00
|
|
|
const jrd_prc* const m_procedure;
|
2010-11-21 04:47:29 +01:00
|
|
|
const ValueListNode* m_sourceList;
|
|
|
|
const ValueListNode* m_targetList;
|
2010-12-04 23:15:03 +01:00
|
|
|
NestConst<MessageNode> const m_message;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Filtering (one -> one) access methods
|
|
|
|
|
|
|
|
class SingularStream : public RecordSource
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SingularStream(CompilerScratch* csb, RecordSource* next);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_next;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class LockedStream : public RecordSource
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LockedStream(CompilerScratch* csb, RecordSource* next);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_next;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class FirstRowsStream : public RecordSource
|
|
|
|
{
|
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
|
|
|
SINT64 irsb_count;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2010-11-21 04:47:29 +01:00
|
|
|
FirstRowsStream(CompilerScratch* csb, RecordSource* next, ValueExprNode* value);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_next;
|
2010-11-21 04:47:29 +01:00
|
|
|
NestConst<ValueExprNode> const m_value;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class SkipRowsStream : public RecordSource
|
|
|
|
{
|
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
|
|
|
SINT64 irsb_count;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2010-11-21 04:47:29 +01:00
|
|
|
SkipRowsStream(CompilerScratch* csb, RecordSource* next, ValueExprNode* value);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_next;
|
2010-11-21 04:47:29 +01:00
|
|
|
NestConst<ValueExprNode> const m_value;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class FilteredStream : public RecordSource
|
|
|
|
{
|
|
|
|
public:
|
2010-10-12 13:36:51 +02:00
|
|
|
FilteredStream(CompilerScratch* csb, RecordSource* next, BoolExprNode* boolean);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-10-12 13:36:51 +02:00
|
|
|
void setAnyBoolean(BoolExprNode* anyBoolean, bool ansiAny, bool ansiNot)
|
2009-12-09 19:45:44 +01:00
|
|
|
{
|
|
|
|
fb_assert(!m_anyBoolean);
|
|
|
|
m_anyBoolean = anyBoolean;
|
|
|
|
|
2009-12-10 02:32:47 +01:00
|
|
|
m_ansiAny = ansiAny;
|
|
|
|
m_ansiAll = !ansiAny;
|
2009-12-09 19:45:44 +01:00
|
|
|
m_ansiNot = ansiNot;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2010-07-05 20:37:35 +02:00
|
|
|
bool evaluateBoolean(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_next;
|
2010-10-12 13:36:51 +02:00
|
|
|
NestConst<BoolExprNode> const m_boolean;
|
|
|
|
NestConst<BoolExprNode> m_anyBoolean;
|
2009-12-09 19:45:44 +01:00
|
|
|
bool m_ansiAny;
|
|
|
|
bool m_ansiAll;
|
|
|
|
bool m_ansiNot;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SortedStream : public RecordSource
|
|
|
|
{
|
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
2010-03-16 12:19:29 +01:00
|
|
|
Sort* irsb_sort;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-08-09 17:48:51 +02:00
|
|
|
dsc desc; // relative descriptor
|
|
|
|
USHORT flagOffset; // offset of missing flag
|
|
|
|
USHORT stream; // stream for field id
|
|
|
|
SSHORT fieldId; // id for field (or ID constants)
|
2010-11-21 04:47:29 +01:00
|
|
|
NestConst<ValueExprNode> node; // expression node
|
2009-12-12 21:36:56 +01:00
|
|
|
};
|
|
|
|
|
2009-12-13 11:41:53 +01:00
|
|
|
explicit SortMap(MemoryPool& p)
|
2009-12-12 21:56:12 +01:00
|
|
|
: PermanentStorage(p),
|
2010-03-06 03:13:22 +01:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
SortedStream(CompilerScratch* csb, RecordSource* next, SortMap* map);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
USHORT getLength() const
|
|
|
|
{
|
2009-12-12 21:36:56 +01:00
|
|
|
return m_map->length;
|
2009-12-09 19:45:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
USHORT getKeyLength() const
|
|
|
|
{
|
2009-12-12 21:36:56 +01:00
|
|
|
return m_map->keyLength;
|
2009-12-09 19:45:44 +01:00
|
|
|
}
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
UCHAR* getData(thread_db* tdbb) const;
|
|
|
|
void mapData(thread_db* tdbb, jrd_req* request, UCHAR* data) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-07-05 20:37:35 +02:00
|
|
|
Sort* init(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_next;
|
2010-07-06 13:09:32 +02:00
|
|
|
const SortMap* const m_map;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
2010-02-16 01:26:53 +01:00
|
|
|
// Make moves in a window without going out of partition boundaries.
|
|
|
|
class SlidingWindow
|
|
|
|
{
|
|
|
|
public:
|
2010-10-12 13:36:51 +02:00
|
|
|
SlidingWindow(thread_db* aTdbb, const BaseBufferedStream* aStream,
|
2010-11-21 04:47:29 +01:00
|
|
|
const NestValueArray* aGroup, jrd_req* aRequest);
|
2010-02-16 01:26:53 +01:00
|
|
|
~SlidingWindow();
|
|
|
|
|
|
|
|
bool move(SINT64 delta);
|
|
|
|
|
|
|
|
private:
|
|
|
|
thread_db* tdbb;
|
2010-07-06 13:09:32 +02:00
|
|
|
const BaseBufferedStream* const stream;
|
2010-11-21 04:47:29 +01:00
|
|
|
const NestValueArray* group;
|
2010-02-16 01:26:53 +01:00
|
|
|
jrd_req* request;
|
|
|
|
Firebird::Array<impure_value> partitionKeys;
|
|
|
|
bool moved;
|
|
|
|
FB_UINT64 savedPosition;
|
|
|
|
};
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
class AggregatedStream : public RecordStream
|
|
|
|
{
|
2009-12-10 02:32:47 +01:00
|
|
|
enum State
|
|
|
|
{
|
2010-01-18 22:37:47 +01:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
2009-12-10 02:32:47 +01:00
|
|
|
State state;
|
2010-02-14 00:55:48 +01:00
|
|
|
FB_UINT64 pending;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2010-11-21 04:47:29 +01:00
|
|
|
AggregatedStream(CompilerScratch* csb, UCHAR stream, const NestValueArray* group,
|
|
|
|
const MapNode* map, BaseBufferedStream* next, const NestValueArray* order);
|
2010-02-14 20:08:22 +01:00
|
|
|
|
2010-11-21 04:47:29 +01:00
|
|
|
AggregatedStream(CompilerScratch* csb, UCHAR stream, const NestValueArray* group,
|
2010-10-12 13:36:51 +02:00
|
|
|
const MapNode* map, RecordSource* next);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
2010-02-14 00:55:48 +01:00
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
private:
|
2010-02-15 01:43:04 +01:00
|
|
|
void init(CompilerScratch* csb);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
State evaluateGroup(thread_db* tdbb, State state) const;
|
|
|
|
void finiDistinct(thread_db* tdbb, jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<BaseBufferedStream> m_bufferedStream;
|
|
|
|
NestConst<RecordSource> m_next;
|
2010-11-21 04:47:29 +01:00
|
|
|
const NestValueArray* const m_group;
|
2010-10-12 13:36:51 +02:00
|
|
|
const MapNode* const m_map;
|
2010-11-21 04:47:29 +01:00
|
|
|
const NestValueArray* const m_order;
|
|
|
|
NestValueArray m_winPassSources;
|
|
|
|
NestValueArray m_winPassTargets;
|
2010-01-23 04:02:53 +01:00
|
|
|
};
|
|
|
|
|
2010-01-18 22:37:47 +01:00
|
|
|
class WindowedStream : public RecordSource
|
2009-12-09 19:45:44 +01:00
|
|
|
{
|
|
|
|
public:
|
2010-10-12 13:36:51 +02:00
|
|
|
WindowedStream(CompilerScratch* csb,
|
|
|
|
Firebird::ObjectsArray<WindowSourceNode::Partition>& partitions, RecordSource* next);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2010-01-18 22:37:47 +01:00
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<BufferedStream> m_next;
|
|
|
|
NestConst<RecordSource> m_joinedStream;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
2010-02-16 01:26:53 +01:00
|
|
|
// 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;
|
2010-02-16 01:26:53 +01:00
|
|
|
virtual FB_UINT64 getCount(jrd_req* request) const = 0;
|
|
|
|
virtual FB_UINT64 getPosition(jrd_req* request) const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class BufferedStream : public BaseBufferedStream
|
2009-12-09 19:45:44 +01:00
|
|
|
{
|
|
|
|
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-09 19:45:44 +01:00
|
|
|
|
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;
|
2009-12-09 19:45:44 +01:00
|
|
|
USHORT map_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
|
|
|
RecordBuffer* irsb_buffer;
|
|
|
|
FB_UINT64 irsb_position;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
BufferedStream(CompilerScratch* csb, RecordSource* next);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-06 13:09:32 +02:00
|
|
|
void locate(thread_db* tdbb, FB_UINT64 position) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
FB_UINT64 getCount(jrd_req* request) const;
|
|
|
|
|
2010-01-23 04:02:53 +01:00
|
|
|
FB_UINT64 getPosition(jrd_req* request) const
|
|
|
|
{
|
2010-04-05 23:20:08 +02:00
|
|
|
Impure* const impure = request->getImpure<Impure>(m_impure);
|
2010-01-23 04:02:53 +01:00
|
|
|
return impure->irsb_position;
|
|
|
|
}
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_next;
|
2009-12-09 19:45:44 +01:00
|
|
|
Firebird::HalfStaticArray<FieldMap, OPT_STATIC_ITEMS> m_map;
|
2010-07-06 13:09:32 +02:00
|
|
|
const Format* m_format;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 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,
|
2010-10-12 13:36:51 +02:00
|
|
|
BoolExprNode* boolean, bool semiJoin, bool antiJoin);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-07-05 20:37:35 +02:00
|
|
|
bool fetchRecord(thread_db*, size_t) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
const bool m_outerJoin;
|
|
|
|
const bool m_semiJoin;
|
|
|
|
const bool m_antiJoin;
|
2010-08-09 17:48:51 +02:00
|
|
|
Firebird::Array<NestConst<RecordSource> > m_args;
|
2010-10-12 13:36:51 +02:00
|
|
|
NestConst<BoolExprNode> const m_boolean;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class FullOuterJoin : public RecordSource
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FullOuterJoin(CompilerScratch* csb, RecordSource* arg1, RecordSource* arg2);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_arg1;
|
|
|
|
NestConst<RecordSource> m_arg2;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
2010-01-12 12:26:09 +01:00
|
|
|
class HashJoin : public RecordSource
|
|
|
|
{
|
2010-01-22 08:11:02 +01:00
|
|
|
class HashTable;
|
2010-01-12 12:26:09 +01:00
|
|
|
|
2010-01-12 15:21:30 +01:00
|
|
|
struct Impure : public RecordSource::Impure
|
2010-01-12 12:26:09 +01:00
|
|
|
{
|
2010-01-22 08:11:02 +01:00
|
|
|
HashTable* irsb_hash_table;
|
2010-01-12 12:26:09 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2010-01-22 08:11:02 +01:00
|
|
|
HashJoin(CompilerScratch* csb, size_t count,
|
2010-11-21 04:47:29 +01:00
|
|
|
RecordSource* const* args, const NestValueArray* const* keys);
|
2010-01-12 12:26:09 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2010-01-12 12:26:09 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2010-01-12 12:26:09 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2010-01-12 12:26:09 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2010-01-12 12:26:09 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2010-01-12 12:26:09 +01:00
|
|
|
|
|
|
|
private:
|
2010-10-12 13:36:51 +02:00
|
|
|
size_t hashKeys(thread_db* tdbb, jrd_req* request, HashTable* table,
|
2010-11-21 04:47:29 +01:00
|
|
|
const NestValueArray* keys) const;
|
2010-07-05 20:37:35 +02:00
|
|
|
bool compareKeys(thread_db* tdbb, jrd_req* request) const;
|
|
|
|
bool fetchRecord(thread_db* tdbb, HashTable* table, size_t stream) const;
|
2010-01-12 12:26:09 +01:00
|
|
|
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_leader;
|
2010-11-21 04:47:29 +01:00
|
|
|
const NestValueArray* m_leaderKeys;
|
2010-08-09 17:48:51 +02:00
|
|
|
Firebird::Array<NestConst<BufferedStream> > m_args;
|
2010-11-21 04:47:29 +01:00
|
|
|
Firebird::Array<const NestValueArray*> m_keys;
|
2010-01-12 15:21:30 +01:00
|
|
|
const bool m_outerJoin;
|
|
|
|
const bool m_semiJoin;
|
|
|
|
const bool m_antiJoin;
|
2010-01-12 12:26:09 +01:00
|
|
|
};
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
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:
|
2009-12-10 16:27:17 +01:00
|
|
|
MergeJoin(CompilerScratch* csb, size_t count,
|
2010-10-12 13:36:51 +02:00
|
|
|
SortedStream* const* args,
|
2010-11-21 04:47:29 +01:00
|
|
|
const NestValueArray* const* keys);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void findUsedStreams(StreamsArray& streams) const;
|
|
|
|
void nullRecords(thread_db* tdbb) const;
|
|
|
|
void saveRecords(thread_db* tdbb) const;
|
|
|
|
void restoreRecords(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-11-21 04:47:29 +01:00
|
|
|
int compare(thread_db* tdbb, const NestValueArray* node1,
|
|
|
|
const NestValueArray* node2) const;
|
2010-07-05 20:37:35 +02:00
|
|
|
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;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-08-09 17:48:51 +02:00
|
|
|
Firebird::Array<NestConst<SortedStream> > m_args;
|
2010-11-21 04:47:29 +01:00
|
|
|
Firebird::Array<const NestValueArray*> m_keys;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class Union : public RecordStream
|
|
|
|
{
|
|
|
|
struct Impure : public RecordSource::Impure
|
|
|
|
{
|
|
|
|
USHORT irsb_count;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
Union(CompilerScratch* csb, UCHAR stream,
|
2010-10-12 13:36:51 +02:00
|
|
|
size_t argCount, RecordSource* const* args, NestConst<MapNode>* maps,
|
2009-12-09 19:45:44 +01:00
|
|
|
size_t streamCount, const UCHAR* streams);
|
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-08-09 17:48:51 +02:00
|
|
|
Firebird::Array<NestConst<RecordSource> > m_args;
|
2010-10-12 13:36:51 +02:00
|
|
|
Firebird::Array<NestConst<MapNode> > m_maps;
|
2009-12-12 20:00:43 +01:00
|
|
|
StreamsArray m_streams;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
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,
|
2010-10-12 13:36:51 +02:00
|
|
|
const MapNode* rootMap, const MapNode* innerMap,
|
2009-12-09 19:45:44 +01:00
|
|
|
size_t streamCount, const UCHAR* innerStreams,
|
2011-02-06 20:34:43 +01:00
|
|
|
ULONG saveOffset);
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
void open(thread_db* tdbb) const;
|
|
|
|
void close(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2010-07-05 20:37:35 +02:00
|
|
|
bool getRecord(thread_db* tdbb) const;
|
|
|
|
bool refetchRecord(thread_db* tdbb) const;
|
|
|
|
bool lockRecord(thread_db* tdbb) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
2011-02-02 12:31:04 +01:00
|
|
|
void print(thread_db* tdbb, Firebird::string& plan,
|
|
|
|
bool detailed, unsigned level) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
void markRecursive();
|
2010-07-05 20:37:35 +02:00
|
|
|
void invalidateRecords(jrd_req* request) const;
|
2009-12-09 19:45:44 +01:00
|
|
|
|
|
|
|
private:
|
2010-11-01 20:32:17 +01:00
|
|
|
void cleanupLevel(jrd_req* request, Impure* impure) const;
|
|
|
|
|
2009-12-09 19:45:44 +01:00
|
|
|
const UCHAR m_mapStream;
|
2010-08-09 17:48:51 +02:00
|
|
|
NestConst<RecordSource> m_root;
|
|
|
|
NestConst<RecordSource> m_inner;
|
2010-10-12 13:36:51 +02:00
|
|
|
const MapNode* const m_rootMap;
|
|
|
|
const MapNode* const m_innerMap;
|
2009-12-12 20:00:43 +01:00
|
|
|
StreamsArray m_innerStreams;
|
2011-02-06 20:34:43 +01:00
|
|
|
const ULONG m_saveOffset;
|
2010-01-22 09:23:36 +01:00
|
|
|
size_t m_saveSize;
|
2009-12-09 19:45:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
#endif // JRD_RECORD_SOURCE_H
|