2

バイナリ文字列に対して部分文字列置換操作を実行したいと考えています。タイプtextcf)の文字列に対してこれとまったく同じことを行う関数が利用可能です:

replace(string text, from text, to text)

bytea残念ながら、タイプのバイナリ文字列(cf )にはありません。

さて、バイナリ文字列に対してこの操作を再実装する必要があるのでしょうか、それとも対応する基本的な文字列関数をこのタスクに使用できるのでしょうか? 私のアプリケーションを壊す可能性のある極端なケースはありますか:

select replace('\000\015Hello World\000\015Hello World'::bytea::text,
               'World',
               'Jenny')::bytea

これまでのところ、ドキュメントに特定のメモは見つかりませんでした。誰かがそれについて私を助けることができますか?

4

2 に答える 2

3

@DanielVérité の提案によると、plpgsql文字列を type のバイナリ文字列に置き換える関数を実装しましたbytea。実装では、バイナリ文字列セクションの関数のみを使用したので、安全に使用できると思います。

これが私のコードです:

CREATE OR REPLACE FUNCTION
replace_binary(input_str bytea, pattern bytea, replacement bytea)
RETURNS bytea
AS $$
DECLARE
    buf bytea;
    pos integer;
BEGIN
    buf := '';
    -- validate input
    IF coalesce(length(input_str), 0) = 0 OR coalesce(length(pattern), 0) = 0
    THEN
        RETURN input_str;
    END IF;
    replacement := coalesce(replacement, '');
    LOOP
        -- find position of pattern in input
        pos := position(pattern in input_str);
        IF pos = 0 THEN
            -- not found: append remaining input to buffer and return
            buf := buf || substring(input_str from 1);
            RETURN buf;
        ELSE
            -- found: append substring before pattern to buffer
            buf := buf || substring(input_str from 1 for pos - 1);
            -- append replacement
            buf := buf || replacement;
            -- go on with substring of input
            input_str := substring(input_str from pos + length(pattern));
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql
IMMUTABLE;

私のテストケースに関しては、それは非常にうまく機能します:

with input(buf, pattern, replacement) as (values 
    ('tt'::bytea, 't'::bytea, 'ttt'::bytea),
    ('test'::bytea, 't'::bytea, 'ttt'::bytea),
    ('abcdefg'::bytea, 't'::bytea, 'ttt'::bytea),
    ('\000\015Hello 0orld\000\015Hello 0orld'::bytea, '0'::bytea, '1'::bytea))

select encode(replace_binary(buf, pattern, replacement), 'escape') from input;

期待どおりの出力:

               encode               
------------------------------------
 tttttt
 tttesttt
 abcdefg
 \000\rHello 1orld\000\rHello 1orld
(4 rows)
于 2013-07-04T10:18:46.207 に答える