提交 889ba39e 编写于 作者: P Polina Bungina 提交者: Ning Yu

Fix query string truncation while dispatching to QE

Execution of a long enough query containing multi-byte characters can cause incorrect truncation of the query string. Incorrect truncation implies an occasional cut of a multi-byte character and (with log_min_duration_statement set to 0 ) subsequent write of an invalid symbol to segment logs. Such broken character present in logs produces problems when trying to fetch logs info from gp_toolkit.__gp_log_segment_ext  table - queries fail with the following error: «ERROR: invalid byte sequence for encoding…». 
This is caused by buildGpQueryString function in `cdbdisp_query.c`, which prepares query text for dispatch to QE. It does not take into account character length when truncation is necessary (text is longer than QUERY_STRING_TRUNCATE_SIZE). 
上级 c0f0ba08
......@@ -38,6 +38,7 @@
#include "utils/session_state.h"
#include "utils/typcache.h"
#include "miscadmin.h"
#include "mb/pg_wchar.h"
#include "cdb/cdbdisp.h"
#include "cdb/cdbdisp_query.h"
......@@ -871,6 +872,8 @@ buildGpQueryString(DispatchCommandQueryParms *pQueryParms,
int total_query_len;
char *shared_query,
*pos;
int cnt,
character_len;
MemoryContext oldContext;
/*
......@@ -886,8 +889,16 @@ buildGpQueryString(DispatchCommandQueryParms *pQueryParms,
* Here we only need to determine the truncated size, the actual work is
* done later when copying it to the result buffer.
*/
cnt = 0;
if (querytree || plantree)
command_len = strnlen(command, QUERY_STRING_TRUNCATE_SIZE - 1) + 1;
{
while (cnt < QUERY_STRING_TRUNCATE_SIZE)
{
character_len = pg_encoding_mblen(GetDatabaseEncoding(), command + cnt);
cnt += character_len;
}
command_len = strnlen(command, cnt - character_len) + 1;
}
else
command_len = strlen(command) + 1;
......
-- More tests related to dispatching and QD->QE communication.
--
-- Test buildGpQueryString of cdbdisp_query.c truncates a query longer than QUERY_STRING_TRUNCATE_SIZE and containing
-- multi-byte symbols properly
--
set log_min_duration_statement to 0;
create table truncate_test ("колонка 1" int, "колонка 2" int, "колонка 3" int, "колонка 4" int, "колонка 5" int,
"колонка 6" int, "колонка 7" int, "колонка 8" int, "колонка 9" int, "колонка 10" int, "колонка 11" int,
"колонка 12" int, "колонка 13" int, "колонка 14" int, "колонка 15" int, "колонка 16" int, "колонка 17" int,
"колонка 18" int, "колонка 19" int, "колонка 20" int, "колонка 21" int, "колонка 22" int, "колонка 23" int,
"колонка 24" int, "колонка 25" int, "колонка 26" int, "колонка 27" int, "колонка 28" int, "колонка 29" int,
"колонка 30" int, "колонка 31" int, "колонка 32" int, "колонка 33" int, "колонка 34" int, "колонка 35" int,
"колонка 36" int, "колонка 37" int, "колонка 38" int, "колонка 39" int, "колонка 40" int, "особая колонка" int);
select logdebug from gp_toolkit.__gp_log_segment_ext where logdebug ilike
'%create table truncate_test%' and logdebug not ilike '%gp_toolkit.__gp_log_segment_ext%' order by logtime desc limit 1;
logdebug
------------------------------------------------------------------------------------------------------------------
create table truncate_test ("колонка 1" int, "колонка 2" int, "колонка 3" int, "колонка 4" int, "колонка 5" int,+
"колонка 6" int, "колонка 7" int, "колонка 8" int, "колонка 9" int, "колонка 10" int, "колонка 11" int, +
"колонка 12" int, "колонка 13" int, "колонка 14" int, "колонка 15" int, "колонка 16" int, "колонка 17" int, +
"колонка 18" int, "колонка 19" int, "колонка 20" int, "колонка 21" int, "колонка 22" int, "колонка 23" int, +
"колонка 24" int, "колонка 25" int, "колонка 26" int, "колонка 27" int, "колонка 28" int, "колонка 29" int, +
"колонка 30" int, "колонка 31" int, "колонка 32" int, "колонка 33" int, "колонка 34" int, "колонка 35" int, +
"колонка 36" int, "колонка 37" int, "колонка 38" int, "колонка 39" int, "колонка 40" int, "о
(1 row)
drop table truncate_test;
reset log_min_duration_statement;
--
-- Test that error messages come out correctly, with non-default
-- client_encoding. (This test assumes that the regression database does
-- *not* use latin1, otherwise this doesn't test anything interesting.)
......
-- More tests related to dispatching and QD->QE communication.
--
-- Test buildGpQueryString of cdbdisp_query.c truncates a query longer than QUERY_STRING_TRUNCATE_SIZE and containing
-- multi-byte symbols properly
--
set log_min_duration_statement to 0;
create table truncate_test ("колонка 1" int, "колонка 2" int, "колонка 3" int, "колонка 4" int, "колонка 5" int,
"колонка 6" int, "колонка 7" int, "колонка 8" int, "колонка 9" int, "колонка 10" int, "колонка 11" int,
"колонка 12" int, "колонка 13" int, "колонка 14" int, "колонка 15" int, "колонка 16" int, "колонка 17" int,
"колонка 18" int, "колонка 19" int, "колонка 20" int, "колонка 21" int, "колонка 22" int, "колонка 23" int,
"колонка 24" int, "колонка 25" int, "колонка 26" int, "колонка 27" int, "колонка 28" int, "колонка 29" int,
"колонка 30" int, "колонка 31" int, "колонка 32" int, "колонка 33" int, "колонка 34" int, "колонка 35" int,
"колонка 36" int, "колонка 37" int, "колонка 38" int, "колонка 39" int, "колонка 40" int, "особая колонка" int);
select logdebug from gp_toolkit.__gp_log_segment_ext where logdebug ilike
'%create table truncate_test%' and logdebug not ilike '%gp_toolkit.__gp_log_segment_ext%' order by logtime desc limit 1;
drop table truncate_test;
reset log_min_duration_statement;
--
-- Test that error messages come out correctly, with non-default
-- client_encoding. (This test assumes that the regression database does
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册