2008-12-04 44 views
3

不使用plpgsql,我試圖urlencode在pgsql SELECT語句中給定的文本。僅具有內置函數的urlencode

這種方法的問題:

select regexp_replace('héllo there','([^A-Za-z0-9])','%' || encode(E'\\1','hex'),'g') 

...是編碼功能不通過正則表達式的參數,除非有另一種方式來調用函數從替換式的實際工作中。所以我想知道是否有一個替換表達式,它本身可以將匹配編碼爲十六進制值。可能還有其他功能組合。我認爲那裏會有一個聰明的正則表達式(這可能仍然是答案),但我無法找到它。

回答

6
select regexp_replace(encode('héllo there','hex'),'(..)',E'%\\1','g'); 

雖然這不會使字母數字字符變爲人類可讀的。

1

這是我寫的編碼使用內置的功能,同時保留URL的可讀性手柄的功能。

正則表達式匹配捕獲(可選)安全字符對和(最多一個)非安全字符對。嵌套選擇允許對這些對進行編碼並重新組合,返回完全編碼的字符串。

我已經通過測試套件以各種排列(前/後的運行/只/重複編碼字符,迄今似乎正確編碼

的安全的特殊字符是_〜 - 。和/。我對列入「/」名單上可能是不規範的,但適合使用情況下,我有其中輸入文本可能是一個路徑,我想,要保持。

CREATE OR REPLACE FUNCTION oseberg.encode_uri(input text) 
    RETURNS text 
    LANGUAGE plpgsql 
    IMMUTABLE STRICT 
AS $function$ 
DECLARE 
    parsed text; 
    safePattern text; 
BEGIN 
    safePattern = 'a-zA-Z0-9_~/\-\.'; 
    IF input ~ ('[^' || safePattern || ']') THEN 
    SELECT STRING_AGG(fragment, '') 
    INTO parsed 
    FROM (
     SELECT prefix || encoded AS fragment 
     FROM (
     SELECT COALESCE(match[1], '') AS prefix, 
       COALESCE('%' || encode(match[2]::bytea, 'hex'), '') AS encoded 
     FROM (
      SELECT regexp_matches(
      input, 
      '([' || safePattern || ']*)([^' || safePattern || '])?', 
      'g') AS match 
     ) matches 
    ) parsed 
    ) fragments; 
    RETURN parsed; 
    ELSE 
    RETURN input; 
    END IF; 
END; 
$function$ 
0

這裏是很短版本,它甚至是「純SQL」函數,而不是plpgsql。支持多字節字符(包括3字節和4字節的表情符號)

create or replace function urlencode(in_str text, OUT _result text) returns text as $$ 
    select 
    string_agg(
     case 
     when ol>1 or ch !~ '[0-9a-za-z:/@._?#-]+' 
      then regexp_replace(upper(substring(ch::bytea::text, 3)), '(..)', E'%\\1', 'g') 
     else ch 
     end, 
     '' 
    ) 
    from (
    select ch, octet_length(ch) as ol 
    from regexp_split_to_table($1, '') as ch 
) as s; 
$$ language sql immutable strict;