Sprintf

From PostgreSQL wiki

Revision as of 17:22, 10 July 2009 by Decibel (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Snippets

sprintf

Works with PostgreSQL

Any version

Written in

PL/pgSQL

Depends on

Nothing


There are two versions, one for 8.3 and earlier and one for 8.4, below.

This is the 8.3 version:

CREATE OR REPLACE FUNCTION printf(fmt text, args text[]) returns text
language plpgsql AS $$
    DECLARE
        argcnt  int = 1;
        chrcnt  int = 0;
        fmtlen  int;
        CHR     text;
        output  text = '';
    BEGIN
        fmtlen = LENGTH(fmt);
        LOOP
            chrcnt = chrcnt + 1;
 
            -- ran out of format string? bail out
            IF chrcnt > fmtlen THEN
                EXIT;
            END IF;
 
            -- grab our char
            CHR = substring(fmt, chrcnt, 1);
 
            -- %% means output a single %, and skip them
            IF CHR = '%' AND substring(fmt, chrcnt + 1, 1) = '%' THEN
                output = output || '%';
                chrcnt = chrcnt + 1;
                continue;
            END IF;
 
            -- a % on its own means output an element from our arg list
            IF CHR = '%' THEN
                output = output || COALESCE(args[argcnt]::text, '');
                argcnt = argcnt + 1;
                continue;
            END IF;
 
            -- no special case? output the thing
            output = output || CHR;
        END LOOP;
 
        RETURN output;
    END;
$$;

It's called like this:

# select printf('% is a % and % is a %, but %% is a %', '{hello,word,1,number,percent sign}');
                      printf
------------------------------------------------------------
hello is a word and 1 is a number, but % is a percent sign
(1 fila)

The 8.4 version uses a VARIADIC argument:

CREATE OR REPLACE FUNCTION printf(fmt text, variadic args anyarray) returns text
language plpgsql AS $$
        DECLARE
                argcnt  int = 1;
                chrcnt  int = 0;
                fmtlen  int;
                CHR             text;
                output  text = '';
        BEGIN
                fmtlen = LENGTH(fmt);
                LOOP
                        chrcnt = chrcnt + 1;
 
                        -- ran out of format string? bail out
                        IF chrcnt > fmtlen THEN
                                EXIT;
                        END IF;
 
                        -- grab our char
                        CHR = substring(fmt, chrcnt, 1);
 
                        -- %% means output a single %, and skip them
                        IF CHR = '%' AND substring(fmt, chrcnt + 1, 1) = '%' THEN
                                output = output || '%';
                                chrcnt = chrcnt + 1;
                                continue;
                        END IF;
 
                        -- a % on its own means output an element from our arg list
                        IF CHR = '%' THEN
                                output = output || COALESCE(args[argcnt]::text, '');
                                argcnt = argcnt + 1;
                                continue;
                        END IF;
 
                        -- no special case? output the thing
                        output = output || CHR;
                END LOOP;
 
                RETURN output;
        END;
$$;

It's called like this:

# select printf('% is a % and % is a %, but %% is a %',
                'hello', 'word', 1::text, 'number', 'percent sign');
                           printf                           
------------------------------------------------------------
 hello is a word and 1 is a number, but % is a percent sign
(1 fila)


You can print more complex stuff such as records by using the textin(sometype-out-func(object)) notation. For records it looks like this:

alvherre=# select printf('the % row looks like %',
                         oid::regclass::text, textin(record_out(pg_class.*)))
             from pg_class limit 10;
                                                printf
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
the pg_type row looks like (pg_type,11,71,10,0,1247,0,7,283,0,0,t,f,f,r,28,0,t,f,f,f,f,648,{=r/alvherre},)
the information_schema.user_mapping_options row looks like (user_mapping_options,11326,11551,10,0,11550,0,0,0,0,0,f,f,f,v,5,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.user_mappings row looks like (user_mappings,11326,11555,10,0,11554,0,0,0,0,0,f,f,f,v,3,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.triggered_update_columns row looks like (triggered_update_columns,11326,11495,10,0,11494,0,0,0,0,0,f,f,f,v,7,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.triggers row looks like (triggers,11326,11498,10,0,11497,0,0,0,0,0,f,f,f,v,17,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.usage_privileges row looks like (usage_privileges,11326,11502,10,0,11501,0,0,0,0,0,f,f,f,v,8,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.view_column_usage row looks like (view_column_usage,11326,11506,10,0,11505,0,0,0,0,0,f,f,f,v,7,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.view_routine_usage row looks like (view_routine_usage,11326,11510,10,0,11509,0,0,0,0,0,f,f,f,v,6,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.view_table_usage row looks like (view_table_usage,11326,11514,10,0,11513,0,0,0,0,0,f,f,f,v,6,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)
the information_schema.views row looks like (views,11326,11518,10,0,11517,0,0,0,0,0,f,f,f,v,7,0,f,f,t,f,f,0,"{alvherre=arwdDxt/alvherre,=r/alvherre}",)

(10 filas)

This work was sponsored by CashNetUSA.

Personal tools