mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Fix calculation of space needed for parsed words in tab completion.
Yesterday in commit d854118c8
, I had a serious brain fade leading me to
underestimate the number of words that the tab-completion logic could
divide a line into. On input such as "(((((", each character will get
seen as a separate word, which means we do indeed sometimes need more
space for the words than for the original line. Fix that.
This commit is contained in:
parent
6f8cb1e234
commit
f5a4370aea
@ -3652,41 +3652,39 @@ get_previous_words(int point, char **buffer, int *nwords)
|
||||
{
|
||||
char **previous_words;
|
||||
char *buf;
|
||||
int buflen;
|
||||
char *outptr;
|
||||
int words_found = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Construct a writable buffer including both preceding and current lines
|
||||
* of the query, up to "point" which is where the currently completable
|
||||
* word begins. Because our definition of "word" is such that a non-word
|
||||
* character must end each word, we can use this buffer to return the word
|
||||
* data as-is, by placing a '\0' after each word.
|
||||
* If we have anything in tab_completion_query_buf, paste it together with
|
||||
* rl_line_buffer to construct the full query. Otherwise we can just use
|
||||
* rl_line_buffer as the input string.
|
||||
*/
|
||||
buflen = point + 1;
|
||||
if (tab_completion_query_buf)
|
||||
buflen += tab_completion_query_buf->len + 1;
|
||||
*buffer = buf = pg_malloc(buflen);
|
||||
i = 0;
|
||||
if (tab_completion_query_buf)
|
||||
if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
|
||||
{
|
||||
memcpy(buf, tab_completion_query_buf->data,
|
||||
tab_completion_query_buf->len);
|
||||
i += tab_completion_query_buf->len;
|
||||
i = tab_completion_query_buf->len;
|
||||
buf = pg_malloc(point + i + 2);
|
||||
memcpy(buf, tab_completion_query_buf->data, i);
|
||||
buf[i++] = '\n';
|
||||
memcpy(buf + i, rl_line_buffer, point);
|
||||
i += point;
|
||||
buf[i] = '\0';
|
||||
/* Readjust point to reference appropriate offset in buf */
|
||||
point = i;
|
||||
}
|
||||
memcpy(buf + i, rl_line_buffer, point);
|
||||
i += point;
|
||||
buf[i] = '\0';
|
||||
|
||||
/* Readjust point to reference appropriate offset in buf */
|
||||
point = i;
|
||||
else
|
||||
buf = rl_line_buffer;
|
||||
|
||||
/*
|
||||
* Allocate array of word start points. There can be at most length/2 + 1
|
||||
* words in the buffer.
|
||||
* Allocate an array of string pointers and a buffer to hold the strings
|
||||
* themselves. The worst case is that the line contains only
|
||||
* non-whitespace WORD_BREAKS characters, making each one a separate word.
|
||||
* This is usually much more space than we need, but it's cheaper than
|
||||
* doing a separate malloc() for each word.
|
||||
*/
|
||||
previous_words = (char **) pg_malloc((point / 2 + 1) * sizeof(char *));
|
||||
previous_words = (char **) pg_malloc(point * sizeof(char *));
|
||||
*buffer = outptr = (char *) pg_malloc(point * 2);
|
||||
|
||||
/*
|
||||
* First we look for a non-word char before the current point. (This is
|
||||
@ -3752,14 +3750,20 @@ get_previous_words(int point, char **buffer, int *nwords)
|
||||
}
|
||||
|
||||
/* Return the word located at start to end inclusive */
|
||||
previous_words[words_found] = &buf[start];
|
||||
buf[end + 1] = '\0';
|
||||
words_found++;
|
||||
previous_words[words_found++] = outptr;
|
||||
i = end - start + 1;
|
||||
memcpy(outptr, &buf[start], i);
|
||||
outptr += i;
|
||||
*outptr++ = '\0';
|
||||
|
||||
/* Continue searching */
|
||||
point = start - 1;
|
||||
}
|
||||
|
||||
/* Release parsing input workspace, if we made one above */
|
||||
if (buf != rl_line_buffer)
|
||||
free(buf);
|
||||
|
||||
*nwords = words_found;
|
||||
return previous_words;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user