Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit303b26c

Browse files
committed
Fix psql's \sf and \ef for new-style SQL functions.
Some options of these commands need to be able to identify the startof the function body within the output of pg_get_functiondef().It used to be that that always began with "AS", but since theintroduction of new-style SQL functions, it might also start with"BEGIN" or "RETURN". Fix that on the psql side, and add someregression tests.Noted by me awhile ago, but I didn't do anything about it.Thanks to David Johnston for a nag.Discussion:https://postgr.es/m/AM9PR01MB8268D5CDABDF044EE9F42173FE8C9@AM9PR01MB8268.eurprd01.prod.exchangelabs.com
1 parent47e1224 commit303b26c

File tree

4 files changed

+94
-26
lines changed

4 files changed

+94
-26
lines changed

‎src/backend/utils/adt/ruleutils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2778,8 +2778,8 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
27782778
*
27792779
* Note: if you change the output format of this function, be careful not
27802780
* to break psql's rules (in \ef and \sf) for identifying the start of the
2781-
* function body. To wit: the function body starts on a line that begins
2782-
*with"AS ", and no preceding line will look like that.
2781+
* function body. To wit: the function body starts on a line that begins with
2782+
* "AS ", "BEGIN ", or "RETURN ", and no preceding line will look like that.
27832783
*/
27842784
Datum
27852785
pg_get_functiondef(PG_FUNCTION_ARGS)

‎src/bin/psql/command.c

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
164164
PQExpBufferbuf);
165165
staticintstrip_lineno_from_objdesc(char*obj);
166166
staticintcount_lines_in_buf(PQExpBufferbuf);
167-
staticvoidprint_with_linenumbers(FILE*output,char*lines,
168-
constchar*header_keyword);
167+
staticvoidprint_with_linenumbers(FILE*output,char*lines,boolis_func);
169168
staticvoidminimal_error_message(PGresult*res);
170169

171170
staticvoidprintSSLInfo(void);
@@ -1165,17 +1164,19 @@ exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
11651164
/*
11661165
* lineno "1" should correspond to the first line of the
11671166
* function body. We expect that pg_get_functiondef() will
1168-
* emit that on a line beginning with "AS ",and that there
1169-
* can be no such line before the real start of the function
1170-
* body. Increment lineno by the number of lines before that
1171-
* line, so that it becomes relative to the first line of the
1172-
* function definition.
1167+
* emit that on a line beginning with "AS ","BEGIN ", or
1168+
*"RETURN ", and that therecan be no such line before the
1169+
*real start of the functionbody. Increment lineno by the
1170+
*number of lines before thatline, so that it becomes
1171+
*relative to the first line of thefunction definition.
11731172
*/
11741173
constchar*lines=query_buf->data;
11751174

11761175
while (*lines!='\0')
11771176
{
1178-
if (strncmp(lines,"AS ",3)==0)
1177+
if (strncmp(lines,"AS ",3)==0||
1178+
strncmp(lines,"BEGIN ",6)==0||
1179+
strncmp(lines,"RETURN ",7)==0)
11791180
break;
11801181
lineno++;
11811182
/* find start of next line */
@@ -2452,15 +2453,8 @@ exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
24522453

24532454
if (show_linenumbers)
24542455
{
2455-
/*
2456-
* For functions, lineno "1" should correspond to the first
2457-
* line of the function body. We expect that
2458-
* pg_get_functiondef() will emit that on a line beginning
2459-
* with "AS ", and that there can be no such line before the
2460-
* real start of the function body.
2461-
*/
2462-
print_with_linenumbers(output,buf->data,
2463-
is_func ?"AS " :NULL);
2456+
/* add line numbers */
2457+
print_with_linenumbers(output,buf->data,is_func);
24642458
}
24652459
else
24662460
{
@@ -5353,24 +5347,28 @@ count_lines_in_buf(PQExpBuffer buf)
53535347
/*
53545348
* Write text at *lines to output with line numbers.
53555349
*
5356-
* If header_keyword isn't NULL, then line 1 should be the first line beginning
5357-
* with header_keyword; lines before that are unnumbered.
5350+
* For functions, lineno "1" should correspond to the first line of the
5351+
* function body; lines before that are unnumbered. We expect that
5352+
* pg_get_functiondef() will emit that on a line beginning with "AS ",
5353+
* "BEGIN ", or "RETURN ", and that there can be no such line before
5354+
* the real start of the function body.
53585355
*
53595356
* Caution: this scribbles on *lines.
53605357
*/
53615358
staticvoid
5362-
print_with_linenumbers(FILE*output,char*lines,
5363-
constchar*header_keyword)
5359+
print_with_linenumbers(FILE*output,char*lines,boolis_func)
53645360
{
5365-
boolin_header= (header_keyword!=NULL);
5366-
size_theader_sz=in_header ?strlen(header_keyword) :0;
5361+
boolin_header=is_func;
53675362
intlineno=0;
53685363

53695364
while (*lines!='\0')
53705365
{
53715366
char*eol;
53725367

5373-
if (in_header&&strncmp(lines,header_keyword,header_sz)==0)
5368+
if (in_header&&
5369+
(strncmp(lines,"AS ",3)==0||
5370+
strncmp(lines,"BEGIN ",6)==0||
5371+
strncmp(lines,"RETURN ",7)==0))
53745372
in_header= false;
53755373

53765374
/* increment lineno only for body's lines */

‎src/test/regress/expected/psql.out

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5165,6 +5165,13 @@ List of access methods
51655165
pg_catalog | bit_xor | smallint | smallint | agg
51665166
(3 rows)
51675167

5168+
\df *._pg_expandarray
5169+
List of functions
5170+
Schema | Name | Result data type | Argument data types | Type
5171+
--------------------+-----------------+------------------+-------------------------------------------+------
5172+
information_schema | _pg_expandarray | SETOF record | anyarray, OUT x anyelement, OUT n integer | func
5173+
(1 row)
5174+
51685175
\do - pg_catalog.int4
51695176
List of operators
51705177
Schema | Name | Left arg type | Right arg type | Result type | Description
@@ -5179,6 +5186,61 @@ List of access methods
51795186
pg_catalog | && | anyarray | anyarray | boolean | overlaps
51805187
(1 row)
51815188

5189+
-- check \sf
5190+
\sf information_schema._pg_expandarray
5191+
CREATE OR REPLACE FUNCTION information_schema._pg_expandarray(anyarray, OUT x anyelement, OUT n integer)
5192+
RETURNS SETOF record
5193+
LANGUAGE sql
5194+
IMMUTABLE PARALLEL SAFE STRICT
5195+
AS $function$select $1[s],
5196+
s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
5197+
from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
5198+
pg_catalog.array_upper($1,1),
5199+
1) as g(s)$function$
5200+
\sf+ information_schema._pg_expandarray
5201+
CREATE OR REPLACE FUNCTION information_schema._pg_expandarray(anyarray, OUT x anyelement, OUT n integer)
5202+
RETURNS SETOF record
5203+
LANGUAGE sql
5204+
IMMUTABLE PARALLEL SAFE STRICT
5205+
1 AS $function$select $1[s],
5206+
2 s operator(pg_catalog.-) pg_catalog.array_lower($1,1) operator(pg_catalog.+) 1
5207+
3 from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
5208+
4 pg_catalog.array_upper($1,1),
5209+
5 1) as g(s)$function$
5210+
\sf+ interval_pl_time
5211+
CREATE OR REPLACE FUNCTION pg_catalog.interval_pl_time(interval, time without time zone)
5212+
RETURNS time without time zone
5213+
LANGUAGE sql
5214+
IMMUTABLE PARALLEL SAFE STRICT COST 1
5215+
1 RETURN ($2 + $1)
5216+
\sf ts_debug(text)
5217+
CREATE OR REPLACE FUNCTION pg_catalog.ts_debug(document text, OUT alias text, OUT description text, OUT token text, OUT dictionaries regdictionary[], OUT dictionary regdictionary, OUT lexemes text[])
5218+
RETURNS SETOF record
5219+
LANGUAGE sql
5220+
STABLE PARALLEL SAFE STRICT
5221+
BEGIN ATOMIC
5222+
SELECT ts_debug.alias,
5223+
ts_debug.description,
5224+
ts_debug.token,
5225+
ts_debug.dictionaries,
5226+
ts_debug.dictionary,
5227+
ts_debug.lexemes
5228+
FROM ts_debug(get_current_ts_config(), ts_debug.document) ts_debug(alias, description, token, dictionaries, dictionary, lexemes);
5229+
END
5230+
\sf+ ts_debug(text)
5231+
CREATE OR REPLACE FUNCTION pg_catalog.ts_debug(document text, OUT alias text, OUT description text, OUT token text, OUT dictionaries regdictionary[], OUT dictionary regdictionary, OUT lexemes text[])
5232+
RETURNS SETOF record
5233+
LANGUAGE sql
5234+
STABLE PARALLEL SAFE STRICT
5235+
1 BEGIN ATOMIC
5236+
2 SELECT ts_debug.alias,
5237+
3 ts_debug.description,
5238+
4 ts_debug.token,
5239+
5 ts_debug.dictionaries,
5240+
6 ts_debug.dictionary,
5241+
7 ts_debug.lexemes
5242+
8 FROM ts_debug(get_current_ts_config(), ts_debug.document) ts_debug(alias, description, token, dictionaries, dictionary, lexemes);
5243+
9 END
51825244
-- check describing invalid multipart names
51835245
\dA regression.heap
51845246
improper qualified name (too many dotted names): regression.heap

‎src/test/regress/sql/psql.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,9 +1239,17 @@ drop role regress_partitioning_role;
12391239
\df has_database_privilegeoidtext
12401240
\df has_database_privilegeoidtext-
12411241
\dfabit* small*
1242+
\df*._pg_expandarray
12421243
\do-pg_catalog.int4
12431244
\do && anyarray*
12441245

1246+
-- check \sf
1247+
\sfinformation_schema._pg_expandarray
1248+
\sf+information_schema._pg_expandarray
1249+
\sf+ interval_pl_time
1250+
\sf ts_debug(text)
1251+
\sf+ ts_debug(text)
1252+
12451253
-- check describing invalid multipart names
12461254
\dAregression.heap
12471255
\dAnonesuch.heap

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp