Optmize query denormalization
Instead of copying original query text byte by byte, copy data between query placeholders in chunks, example: `INSERT INTO foo(a, b, c) VALUES('test', 100, 'test again)'` Would result in normalized query: `INSERT INTO foo(a, b, c) VALUES($1, $2, $3)` The original patch would copy the parts between placeholders byte by byte, e.g. `INSERT INTO foo(a, b, c) VALUES(`, instead we can copy this whole block at once, 1 function call and maybe 1 buffer re-allocation per call. Also make use of `appendBinaryStringInfo` to avoid calculating string length as we have this info already.pull/481/head
parent
70aaa0875e
commit
6acc63e5a6
|
@ -20,6 +20,7 @@
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
#include "utils/guc.h"
|
#include "utils/guc.h"
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
#include "commands/dbcommands.h"
|
#include "commands/dbcommands.h"
|
||||||
#include "commands/explain.h"
|
#include "commands/explain.h"
|
||||||
|
@ -4085,40 +4086,58 @@ get_denormalized_query(const ParamListInfo paramlist, const char *query_text)
|
||||||
int i;
|
int i;
|
||||||
char **param_text;
|
char **param_text;
|
||||||
const char *cursor_ori;
|
const char *cursor_ori;
|
||||||
|
const char *cursor_curr;
|
||||||
StringInfoData result_buf;
|
StringInfoData result_buf;
|
||||||
|
ptrdiff_t len;
|
||||||
|
|
||||||
param_text = get_params_text_list(paramlist);
|
param_text = get_params_text_list(paramlist);
|
||||||
param_num = paramlist->numParams;
|
param_num = paramlist->numParams;
|
||||||
current_param = 0;
|
current_param = 0;
|
||||||
cursor_ori = query_text;
|
cursor_ori = query_text;
|
||||||
|
cursor_curr = cursor_ori;
|
||||||
initStringInfo(&result_buf);
|
initStringInfo(&result_buf);
|
||||||
|
|
||||||
while(*cursor_ori != '\0')
|
do
|
||||||
{
|
{
|
||||||
if(*cursor_ori != '$')
|
// advance cursor until detecting a placeholder '$' start.
|
||||||
|
while (*cursor_ori && *cursor_ori != '$')
|
||||||
|
++cursor_ori;
|
||||||
|
|
||||||
|
// calculate length of query text before placeholder.
|
||||||
|
len = cursor_ori - cursor_curr;
|
||||||
|
|
||||||
|
// check if end of string is reached
|
||||||
|
if (!*cursor_ori)
|
||||||
{
|
{
|
||||||
/* copy the origin query string to result*/
|
// there may have remaining query data to append
|
||||||
appendStringInfoChar(&result_buf,*cursor_ori);
|
if (len > 0)
|
||||||
cursor_ori++;
|
appendBinaryStringInfo(&result_buf, cursor_curr, len);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
// append query text before the '$' sign found.
|
||||||
|
if (len > 0)
|
||||||
|
appendBinaryStringInfo(&result_buf, cursor_curr, len);
|
||||||
|
|
||||||
|
// skip '$'
|
||||||
|
++cursor_ori;
|
||||||
|
|
||||||
/* skip the placeholder */
|
/* skip the placeholder */
|
||||||
|
while(*cursor_ori && *cursor_ori >= '0' && *cursor_ori <= '9')
|
||||||
cursor_ori++;
|
cursor_ori++;
|
||||||
while(*cursor_ori >= '0' && *cursor_ori <= '9')
|
|
||||||
{
|
// advance current cursor
|
||||||
cursor_ori++;
|
cursor_curr = cursor_ori;
|
||||||
}
|
|
||||||
/* replace the placeholder with actual value */
|
/* replace the placeholder with actual value */
|
||||||
appendStringInfo(&result_buf,"%s",param_text[current_param++]);
|
appendStringInfoString(&result_buf, param_text[current_param++]);
|
||||||
}
|
} while (*cursor_ori != '\0');
|
||||||
}
|
|
||||||
|
|
||||||
/* free the query text array*/
|
/* free the query text array*/
|
||||||
for(i = 0; i < param_num; i++)
|
for(i = 0; i < param_num; i++)
|
||||||
{
|
|
||||||
pfree(param_text[i]);
|
pfree(param_text[i]);
|
||||||
}
|
|
||||||
pfree(param_text);
|
pfree(param_text);
|
||||||
|
|
||||||
return result_buf;
|
return result_buf;
|
||||||
|
|
Loading…
Reference in New Issue