Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions builds/install/misc/firebird.conf
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,19 @@
#ReadConsistency = 1


# ----------------------------
# Define maximum recursion depth of the plan output.
#
# When set to non-zero, allows to recurse into selectable procedures and
# include their nested plans into the plan of the outer query.
#
# Per-database configurable.
#
# Type: integer
#
#PlanRecursionLimit = 0


# ----------------------------
# The engine provides a number of new datatypes unknown to legacy clients.
# To simplify use of old applications set this parameter to the Firebird version
Expand Down
7 changes: 6 additions & 1 deletion src/common/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ enum ConfigKey
KEY_MAX_STATEMENT_CACHE_SIZE,
KEY_PARALLEL_WORKERS,
KEY_MAX_PARALLEL_WORKERS,
KEY_PLAN_RECURSION_LIMIT,
MAX_CONFIG_KEY // keep it last
};

Expand Down Expand Up @@ -310,7 +311,8 @@ constexpr ConfigEntry entries[MAX_CONFIG_KEY] =
{TYPE_STRING, "TempTableDirectory", false, ""},
{TYPE_INTEGER, "MaxStatementCacheSize", false, 2 * 1048576}, // bytes
{TYPE_INTEGER, "ParallelWorkers", true, 1},
{TYPE_INTEGER, "MaxParallelWorkers", true, 1}
{TYPE_INTEGER, "MaxParallelWorkers", true, 1},
{TYPE_INTEGER, "PlanRecursionLimit", false, 0}
};


Expand Down Expand Up @@ -638,6 +640,9 @@ class Config : public RefCounted, public GlobalStorage
CONFIG_GET_GLOBAL_INT(getParallelWorkers, KEY_PARALLEL_WORKERS);

CONFIG_GET_GLOBAL_INT(getMaxParallelWorkers, KEY_MAX_PARALLEL_WORKERS);

CONFIG_GET_PER_DB_INT(getPlanRecursionLimit, KEY_PLAN_RECURSION_LIMIT);

};

// Implementation of interface to access master configuration file
Expand Down
4 changes: 3 additions & 1 deletion src/jrd/ProfilerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,9 @@ void ProfilerManager::prepareRecSource(thread_db* tdbb, Request* request, const
const auto thisRsb = planItem.recordSource;

string& accessPath = planItem.accessPath;
thisRsb->print(tdbb, accessPath, true, 0, false);

PlanPrintContext context(tdbb->getDatabase(), accessPath, true, false);
thisRsb->print(tdbb, context, 0);

constexpr auto INDENT_MARKER = "\n ";
constexpr unsigned INDENT_COUNT = 4;
Expand Down
8 changes: 4 additions & 4 deletions src/jrd/recsrc/AggregatedStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,16 +380,16 @@ void AggregatedStream::getChildren(Array<const RecordSource*>& children) const
children.add(m_next);
}

void AggregatedStream::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void AggregatedStream::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Aggregate";
printOptInfo(plan);
}

if (recurse)
m_next->print(tdbb, plan, detailed, level, recurse);
if (plan.goDeeper())
m_next->print(tdbb, plan, level);
}

bool AggregatedStream::internalGetRecord(thread_db* tdbb) const
Expand Down
5 changes: 2 additions & 3 deletions src/jrd/recsrc/BitmapTableScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,9 @@ void BitmapTableScan::getChildren(Array<const RecordSource*>& children) const
{
}

void BitmapTableScan::print(thread_db* tdbb, string& plan,
bool detailed, unsigned level, bool recurse) const
void BitmapTableScan::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Table " +
printName(tdbb, m_relation->rel_name.c_str(), m_alias) + " Access By ID";
Expand Down
8 changes: 4 additions & 4 deletions src/jrd/recsrc/BufferedStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,9 @@ void BufferedStream::getChildren(Array<const RecordSource*>& children) const
children.add(m_next);
}

void BufferedStream::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void BufferedStream::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
string extras;
extras.printf(" (record length: %" ULONGFORMAT")", m_format->fmt_length);
Expand All @@ -330,8 +330,8 @@ void BufferedStream::print(thread_db* tdbb, string& plan, bool detailed, unsigne
printOptInfo(plan);
}

if (recurse)
m_next->print(tdbb, plan, detailed, level, recurse);
if (plan.goDeeper())
m_next->print(tdbb, plan, level);
}

void BufferedStream::markRecursive()
Expand Down
14 changes: 7 additions & 7 deletions src/jrd/recsrc/ConditionalStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,29 +120,29 @@ void ConditionalStream::getChildren(Array<const RecordSource*>& children) const
children.add(m_second);
}

void ConditionalStream::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void ConditionalStream::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Condition";
printOptInfo(plan);

if (recurse)
if (plan.goDeeper())
{
m_first->print(tdbb, plan, true, level, recurse);
m_second->print(tdbb, plan, true, level, recurse);
m_first->print(tdbb, plan, level);
m_second->print(tdbb, plan, level);
}
}
else
{
if (!level)
plan += "(";

m_first->print(tdbb, plan, false, level + 1, recurse);
m_first->print(tdbb, plan, level + 1);

plan += ", ";

m_second->print(tdbb, plan, false, level + 1, recurse);
m_second->print(tdbb, plan, level + 1);

if (!level)
plan += ")";
Expand Down
18 changes: 10 additions & 8 deletions src/jrd/recsrc/Cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,28 @@ void Select::initializeInvariants(Request* request) const
}
}

void Select::print(thread_db* tdbb, Firebird::string& plan, bool detailed, unsigned level, bool recurse) const
void Select::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += level ? RecordSource::printIndent(level) : "\n";

if (m_rse->isSubQuery())
{
plan += "\nSub-query";
plan += "Sub-query";

if (m_rse->isInvariant())
plan += " (invariant)";
}
else if (m_cursorName.hasData())
{
plan += "\nCursor \"" + string(m_cursorName) + "\"";
plan += "Cursor \"" + string(m_cursorName) + "\"";

if (m_rse->isScrollable())
plan += " (scrollable)";
}
else
plan += "\nSelect Expression";
plan += "Select Expression";

if (m_line || m_column)
{
Expand All @@ -135,7 +137,7 @@ void Select::print(thread_db* tdbb, Firebird::string& plan, bool detailed, unsig
plan += pos;
}
}
else
else if (!level)
{
if (m_line || m_column)
{
Expand All @@ -147,8 +149,8 @@ void Select::print(thread_db* tdbb, Firebird::string& plan, bool detailed, unsig
plan += "\nPLAN ";
}

if (recurse)
m_root->print(tdbb, plan, detailed, level, true);
if (plan.goDeeper())
m_root->print(tdbb, plan, level);
}

// ---------------------
Expand Down
8 changes: 4 additions & 4 deletions src/jrd/recsrc/Cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@

#include "../common/classes/array.h"
#include "../jrd/MetaName.h"
#include "../jrd/recsrc/RecordSource.h"

namespace Jrd
{
class thread_db;
class CompilerScratch;
class RecordSource;
class RseNode;

// Select class (common base for sub-queries and cursors)
Expand Down Expand Up @@ -70,11 +70,11 @@ namespace Jrd

void printPlan(thread_db* tdbb, Firebird::string& plan, bool detailed) const
{
print(tdbb, plan, detailed, 0, true);
PlanPrintContext context(tdbb->getDatabase(), plan, detailed, true);
print(tdbb, context, 0);
}

void print(thread_db* tdbb, Firebird::string& plan,
bool detailed, unsigned level, bool recurse) const override;
void print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const override;

void getChildren(Firebird::Array<const RecordSource*>& children) const override
{
Expand Down
5 changes: 2 additions & 3 deletions src/jrd/recsrc/ExternalTableScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,9 @@ void ExternalTableScan::getChildren(Array<const RecordSource*>& children) const
{
}

void ExternalTableScan::print(thread_db* tdbb, string& plan,
bool detailed, unsigned level, bool recurse) const
void ExternalTableScan::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Table " +
printName(tdbb, m_relation->rel_name.c_str(), m_alias) + " Full Scan";
Expand Down
8 changes: 4 additions & 4 deletions src/jrd/recsrc/FilteredStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ void FilteredStream::getChildren(Array<const RecordSource*>& children) const
children.add(m_next);
}

void FilteredStream::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void FilteredStream::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Filter";

Expand All @@ -133,8 +133,8 @@ void FilteredStream::print(thread_db* tdbb, string& plan, bool detailed, unsigne
printOptInfo(plan);
}

if (recurse)
m_next->print(tdbb, plan, detailed, level, recurse);
if (plan.goDeeper())
m_next->print(tdbb, plan, level);
}

void FilteredStream::markRecursive()
Expand Down
8 changes: 4 additions & 4 deletions src/jrd/recsrc/FirstRowsStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,16 @@ void FirstRowsStream::getChildren(Array<const RecordSource*>& children) const
children.add(m_next);
}

void FirstRowsStream::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void FirstRowsStream::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "First N Records";
printOptInfo(plan);
}

if (recurse)
m_next->print(tdbb, plan, detailed, level, recurse);
if (plan.goDeeper())
m_next->print(tdbb, plan, level);
}

void FirstRowsStream::markRecursive()
Expand Down
14 changes: 7 additions & 7 deletions src/jrd/recsrc/FullOuterJoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,25 +118,25 @@ void FullOuterJoin::getChildren(Array<const RecordSource*>& children) const
children.add(m_arg2);
}

void FullOuterJoin::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void FullOuterJoin::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Full Outer Join";

if (recurse)
if (plan.goDeeper())
{
m_arg1->print(tdbb, plan, true, level, recurse);
m_arg2->print(tdbb, plan, true, level, recurse);
m_arg1->print(tdbb, plan, level);
m_arg2->print(tdbb, plan, level);
}
}
else
{
level++;
plan += "JOIN (";
m_arg1->print(tdbb, plan, false, level, recurse);
m_arg1->print(tdbb, plan, level);
plan += ", ";
m_arg2->print(tdbb, plan, false, level, recurse);
m_arg2->print(tdbb, plan, level);
plan += ")";
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/jrd/recsrc/FullTableScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ void FullTableScan::getChildren(Array<const RecordSource*>& children) const
{
}

void FullTableScan::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void FullTableScan::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
auto lowerBounds = 0, upperBounds = 0;
for (const auto range : m_dbkeyRanges)
Expand Down
14 changes: 7 additions & 7 deletions src/jrd/recsrc/HashJoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,33 +462,33 @@ void HashJoin::getChildren(Array<const RecordSource*>& children) const
children.add(m_args[i].source);
}

void HashJoin::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void HashJoin::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Hash Join (inner)";
printOptInfo(plan);

if (recurse)
if (plan.goDeeper())
{
m_leader.source->print(tdbb, plan, true, level, recurse);
m_leader.source->print(tdbb, plan, level);

for (FB_SIZE_T i = 0; i < m_args.getCount(); i++)
m_args[i].source->print(tdbb, plan, true, level, recurse);
m_args[i].source->print(tdbb, plan, level);
}
}
else
{
level++;
plan += "HASH (";
m_leader.source->print(tdbb, plan, false, level, recurse);
m_leader.source->print(tdbb, plan, level);
plan += ", ";
for (FB_SIZE_T i = 0; i < m_args.getCount(); i++)
{
if (i)
plan += ", ";

m_args[i].source->print(tdbb, plan, false, level, recurse);
m_args[i].source->print(tdbb, plan, level);
}
plan += ")";
}
Expand Down
4 changes: 2 additions & 2 deletions src/jrd/recsrc/IndexTableScan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ void IndexTableScan::getChildren(Array<const RecordSource*>& children) const
{
}

void IndexTableScan::print(thread_db* tdbb, string& plan, bool detailed, unsigned level, bool recurse) const
void IndexTableScan::print(thread_db* tdbb, PlanPrintContext& plan, unsigned level) const
{
if (detailed)
if (plan.isDetailed())
{
plan += printIndent(++level) + "Table " +
printName(tdbb, m_relation->rel_name.c_str(), m_alias) + " Access By ID";
Expand Down
Loading