mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 04:43:03 +01:00
Fixed CORE-5061: ISQL plan output is unexpectedly truncated after a query is simplified to become shorter.
This commit is contained in:
parent
f4defcd2bc
commit
24b7a7982c
@ -1819,7 +1819,8 @@ static void sql_info(thread_db* tdbb,
|
||||
|
||||
if (plan.hasData())
|
||||
{
|
||||
const ULONG buffer_length = end_info - info - 3; // 1-byte item + 2-byte length
|
||||
// 1-byte item + 2-byte length + isc_info_end/isc_info_truncated == 4
|
||||
const ULONG buffer_length = end_info - info - 4;
|
||||
const ULONG max_length = MIN(buffer_length, MAX_USHORT);
|
||||
|
||||
if (plan.length() > max_length)
|
||||
@ -1837,12 +1838,13 @@ static void sql_info(thread_db* tdbb,
|
||||
}
|
||||
|
||||
plan += " ...";
|
||||
}
|
||||
|
||||
if (plan.length() > max_length)
|
||||
{
|
||||
// If it's still too long, give up
|
||||
fb_assert(info < end_info);
|
||||
if (plan.length() <= max_length)
|
||||
{
|
||||
info = put_item(item, plan.length(), reinterpret_cast<const UCHAR*>(plan.c_str()),
|
||||
info, end_info);
|
||||
}
|
||||
|
||||
*info = isc_info_truncated;
|
||||
info = NULL;
|
||||
}
|
||||
|
@ -7747,63 +7747,58 @@ static void process_plan()
|
||||
|
||||
UCHAR plan_info[1];
|
||||
plan_info[0] = setValues.ExplainPlan ? isc_info_sql_explain_plan : isc_info_sql_get_plan;
|
||||
UCHAR plan_buffer[PLAN_BUFFER_LENGTH];
|
||||
memset(plan_buffer, 0, sizeof(plan_buffer));
|
||||
UCHAR* planPtr = plan_buffer;
|
||||
unsigned planSize = sizeof(plan_buffer);
|
||||
PtrSentry<UCHAR> planSentry;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
Firebird::HalfStaticArray<UCHAR, MAX_SSHORT> planBuffer;
|
||||
unsigned planSize = MAX_SSHORT;
|
||||
UCHAR* planPtr = planBuffer.getBuffer(planSize);
|
||||
|
||||
Firebird::string planString;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
global_Stmt->getInfo(fbStatus, sizeof(plan_info), plan_info, planSize, planPtr);
|
||||
if (ISQL_errmsg(fbStatus))
|
||||
{
|
||||
return;
|
||||
|
||||
bool truncated = false;
|
||||
|
||||
for (const UCHAR* ptr = planPtr; ptr < planPtr + planSize && *ptr != isc_info_end;)
|
||||
{
|
||||
switch (*ptr++)
|
||||
{
|
||||
case isc_info_sql_get_plan:
|
||||
case isc_info_sql_explain_plan:
|
||||
{
|
||||
const ULONG len = gds__vax_integer(ptr, sizeof(USHORT));
|
||||
ptr += sizeof(USHORT);
|
||||
planString.assign((const char*) ptr, len);
|
||||
ptr += len;
|
||||
}
|
||||
break;
|
||||
case isc_info_truncated:
|
||||
// Probably FB 2.1 and before will crash with MAX_USHORT
|
||||
if (i == 0 && ENCODE_ODS(isqlGlob.major_ods, isqlGlob.minor_ods) >= ODS_11_2)
|
||||
{
|
||||
planSize = MAX_USHORT;
|
||||
planBuffer.resize(planSize);
|
||||
planPtr = planBuffer.begin();
|
||||
}
|
||||
truncated = true;
|
||||
break;
|
||||
case isc_info_end:
|
||||
break;
|
||||
default:
|
||||
IUTILS_printf2(Diag, "Unknown error while retrieving plan%s", NEWLINE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (planPtr[0])
|
||||
{
|
||||
case isc_info_sql_get_plan:
|
||||
case isc_info_sql_explain_plan:
|
||||
{
|
||||
ULONG len = gds__vax_integer(planPtr + 1, 2);
|
||||
if (len > planSize - 3)
|
||||
len = planSize - 3;
|
||||
IUTILS_printf2(Diag, "%.*s%s", len, planPtr + 3, NEWLINE);
|
||||
}
|
||||
return;
|
||||
case isc_info_truncated:
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
planSentry.exchange((planPtr = FB_NEW UCHAR[planSize = MAX_SSHORT]), true);
|
||||
break;
|
||||
case 1:
|
||||
// Probably FB 2.1 and before will crash with MAX_USHORT.
|
||||
if ((isqlGlob.major_ods == 11 && isqlGlob.minor_ods >= 2) || // FB2.5
|
||||
isqlGlob.major_ods > 11)
|
||||
{
|
||||
planSentry.clean();
|
||||
planSentry.exchange((planPtr = FB_NEW UCHAR[planSize = MAX_USHORT]), true);
|
||||
break;
|
||||
}
|
||||
// else fall into
|
||||
case 2:
|
||||
IUTILS_printf2(Diag, "Plan truncated%s", NEWLINE);
|
||||
return;
|
||||
default:
|
||||
IUTILS_printf2(Diag, "Logical error in isql%s", NEWLINE);
|
||||
fb_assert(false);
|
||||
return;
|
||||
}
|
||||
if (!truncated)
|
||||
break;
|
||||
case isc_info_end:
|
||||
return; // Assume no plan.
|
||||
default:
|
||||
IUTILS_printf2(Diag, "Unknown error while retrieving plan%s", NEWLINE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IUTILS_printf2(Diag, "%s%s", planString.hasData() ? planString.c_str(): "Plan truncated",
|
||||
NEWLINE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
// Define lengths used in isql.e
|
||||
|
||||
const int PRINT_BUFFER_LENGTH = 1024;
|
||||
const int PLAN_BUFFER_LENGTH = 1024 * 16;
|
||||
const int MAXTERM_SIZE = 32; // SQL termination character
|
||||
const int USER_LENGTH = 128;
|
||||
const int PASSWORD_LENGTH = 128;
|
||||
|
Loading…
Reference in New Issue
Block a user