8
0
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:
dimitr 2016-01-02 12:08:31 +00:00
parent f4defcd2bc
commit 24b7a7982c
3 changed files with 51 additions and 55 deletions

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;