*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 1530,1536 ****
SQL literal; %% outputs a literal %>.
A conversion can reference an explicit parameter position by preceding
the conversion specifier with n>$>, where
! n is the argument position.
See also .
format('Hello %s, %1$s', 'World')
--- 1530,1537 ----
SQL literal; %% outputs a literal %>.
A conversion can reference an explicit parameter position by preceding
the conversion specifier with n>$>, where
! n is the argument position. A warnig is raised
! when positional and ordered placeholders are used together.
See also .
format('Hello %s, %1$s', 'World')
*** a/src/backend/utils/adt/varlena.c
--- b/src/backend/utils/adt/varlena.c
***************
*** 3958,3964 **** text_format(PG_FUNCTION_ARGS)
const char *start_ptr;
const char *end_ptr;
text *result;
! int arg = 0;
/* When format string is null, returns null */
if (PG_ARGISNULL(0))
--- 3958,3968 ----
const char *start_ptr;
const char *end_ptr;
text *result;
! int arg;
! int position = 0;
! bool positional = false;
! bool ordered = false;
! bool warning_emmited = false;
/* When format string is null, returns null */
if (PG_ARGISNULL(0))
***************
*** 4006,4013 **** text_format(PG_FUNCTION_ARGS)
*/
if (*cp < '0' || *cp > '9')
{
! ++arg;
! if (arg <= 0) /* overflow? */
{
/*
* Should not happen, as you can't pass billions of arguments
--- 4010,4025 ----
*/
if (*cp < '0' || *cp > '9')
{
! /* don't allow mix styles - reflects glibc behave */
! if (positional && !warning_emmited)
! {
! elog(WARNING, "ordered and positional placeholders are used together");
! warning_emmited = true;
! }
! ordered = true;
!
! ++position;
! if (position <= 0) /* overflow? */
{
/*
* Should not happen, as you can't pass billions of arguments
***************
*** 4017,4022 **** text_format(PG_FUNCTION_ARGS)
--- 4029,4035 ----
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("argument number is out of range")));
}
+ arg = position;
}
else
{
***************
*** 4054,4059 **** text_format(PG_FUNCTION_ARGS)
--- 4067,4079 ----
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unterminated conversion specifier")));
+ if (ordered && !warning_emmited)
+ {
+ elog(WARNING, "ordered and positional placeholders are used together");
+ warning_emmited = true;
+ }
+ positional = true;
+
/* There's no argument 0. */
if (arg == 0)
ereport(ERROR,
*** a/src/test/regress/expected/text.out
--- b/src/test/regress/expected/text.out
***************
*** 229,243 **** ERROR: unterminated conversion specifier
--- 229,253 ----
select format('%1$1', 1);
ERROR: unrecognized conversion specifier "1"
--checkk mix of positional and ordered placeholders
+ --should raise warnings
select format('Hello %s %1$s %s', 'World', 'Hello again');
+ WARNING: ordered and positional placeholders are used together
format
-------------------------------
Hello World World Hello again
(1 row)
select format('Hello %s %s, %2$s %2$s', 'World', 'Hello again');
+ WARNING: ordered and positional placeholders are used together
format
--------------------------------------------------
Hello World Hello again, Hello again Hello again
(1 row)
+ select format('Hello %s %2$s %s', 'World', 'Hello again');
+ WARNING: ordered and positional placeholders are used together
+ format
+ -------------------------------------
+ Hello World Hello again Hello again
+ (1 row)
+
*** a/src/test/regress/sql/text.sql
--- b/src/test/regress/sql/text.sql
***************
*** 74,78 **** select format('%1s', 1);
--- 74,80 ----
select format('%1$', 1);
select format('%1$1', 1);
--checkk mix of positional and ordered placeholders
+ --should raise warnings
select format('Hello %s %1$s %s', 'World', 'Hello again');
select format('Hello %s %s, %2$s %2$s', 'World', 'Hello again');
+ select format('Hello %s %2$s %s', 'World', 'Hello again');