Skip to content

Instantly share code, notes, and snippets.

@Revolucent
Last active June 5, 2023 04:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Revolucent/ac38fe507e51ecfabf04 to your computer and use it in GitHub Desktop.
Save Revolucent/ac38fe507e51ecfabf04 to your computer and use it in GitHub Desktop.
sprintf function for PostgreSQL with indexed arguments
-- Inspired by https://wiki.postgresql.org/wiki/Sprintf,
-- but really, pretty different.
CREATE FUNCTION sprintf(_format TEXT, VARIADIC _args ANYARRAY) RETURNS TEXT
LANGUAGE PLPGSQL
STRICT IMMUTABLE
AS $$
DECLARE _f INT DEFAULT 0; -- Index of current character in format string
DECLARE _c TEXT; -- Current character
DECLARE _match TEXT;
DECLARE _matches TEXT[];
DECLARE _result TEXT DEFAULT '';
BEGIN
LOOP
_f := _f + 1;
IF _f > CHAR_LENGTH(_format) THEN
EXIT;
END IF;
_c = SUBSTRING(_format, _f, 1);
IF _c = '%' THEN
_matches := REGEXP_MATCHES(SUBSTRING(_format FROM _f), '(^%(\d*)%)');
IF _matches IS NOT NULL THEN
_match := _matches[2];
IF _match = '' THEN
_result := _result || _c;
_f := _f + 1;
ELSE
_result := _result || _args[_match::INT]::TEXT;
_f := _f + CHAR_LENGTH(_matches[1]) - 1;
END IF;
ELSE
_result := _result || _c;
END IF;
ELSE
_result := _result || _c;
END IF;
END LOOP;
RETURN _result;
END
$$;
@Revolucent
Copy link
Author

Here's how you use this bugger:

sprintf('The odds are %1%%%, got it? %1%!', 50);

Which becomes:

'The odds are 50%, got it? 50!'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment