2012-04-25 38 views
5

Có bất kỳ thủ tục hàm/lưu trữ nào trong PostgreSQL/plpgsql giống với mã javascripts encodeURI không?Javascript encodeURI như chức năng trong postgresql?

Điều đó có nghĩa là gì? Javascript có một tiện dụng được xây dựng trong chức năng để mã hóa bất kỳ loại url:

encodeURI (url) -> trả về url mã hóa

Ví dụ: encodeURI('http://hu.wikipedia.org/wiki/São_Paulo') -> trả về một String đó là "http://hu.wikipedia.org/wiki/S%C3%A3o_Paulo"

tôi tìm kiếm chính xác như nhau.

Tôi không muốn mã hóa từng thông số một cách riêng biệt. Tôi không muốn một hàm như javascript encodeURIComponent không giống nhau. Ví dụ trên kết quả đầu ra khác nhau với

encodeURIComponent('http://hu.wikipedia.org/wiki/São_Paulo') 

->"http%3A%2F%2Fhu.wikipedia.org%2Fwiki%2FS%C3%A3o_Paulo"

Đó là mã hóa toàn bộ chuỗi không chỉ là một phần con đường. Vì vậy, đây không phải là những gì tôi đang tìm kiếm. Tôi cần một chức năng plpgsql mà kết quả đầu ra tương đương với chức năng javascript encodeURI.

Cảm ơn!

Trả lời

4

tôi đã viết PostgreSQL mở rộng url_enocode rằng giải quyết vấn đề này

postgres=# select url_encode('http://hu.wikipedia.org/wiki/São_Paulo'); 
         url_encode      
─────────────────────────────────────────────────────── 
http%3A%2F%2Fhu.wikipedia.org%2Fwiki%2FS%C3%A3o_Paulo 

hoặc

postgres=# select uri_encode('http://hu.wikipedia.org/wiki/São_Paulo'); 
       uri_encode     
--------------------------------------------- 
http://hu.wikipedia.org/wiki/S%C3%A3o_Paulo 
+0

Điều này dường như giải pháp gần nhất những gì tôi cần ... – Roki

+0

Có lẽ tôi sửa đổi nó một chút ... Nó có lỗi, sau giao thức (http) ... Nếu bạn thêm c == ':' vào dòng thứ 95, nó sẽ hoạt động hoàn hảo ... (và dòng 154 cũng ... là nhất quán) – Roki

+0

Đây chỉ là phiên bản đầu tiên - tôi sẽ thêm một hàm uri_encode và uri_decode, không thể sửa đổi như bạn đề xuất, bởi vì: là các ký tự dành riêng. –

11

chậm và không hiệu quả, hãy xem xét làm C phiên bản của chức năng này:

CREATE OR REPLACE FUNCTION urlencode(in_str text, OUT _result text) 
    STRICT IMMUTABLE AS $urlencode$ 
DECLARE 
    _i  int4; 
    _temp varchar; 
    _ascii int4; 
BEGIN 
    _result = ''; 
    FOR _i IN 1 .. length(in_str) LOOP 
     _temp := substr(in_str, _i, 1); 
     IF _temp ~ '[0-9a-zA-Z:/@._?#-]+' THEN 
      _result := _result || _temp; 
     ELSE 
      _ascii := ascii(_temp); 
      IF _ascii > x'07ff'::int4 THEN 
       RAISE EXCEPTION 'Won''t deal with 3 (or more) byte sequences.'; 
      END IF; 
      IF _ascii <= x'07f'::int4 THEN 
       _temp := '%'||to_hex(_ascii); 
      ELSE 
       _temp := '%'||to_hex((_ascii & x'03f'::int4)+x'80'::int4); 
       _ascii := _ascii >> 6; 
       _temp := '%'||to_hex((_ascii & x'01f'::int4)+x'c0'::int4) 
          ||_temp; 
      END IF; 
      _result := _result || upper(_temp); 
     END IF; 
    END LOOP; 
    RETURN ; 
END; 
$urlencode$ LANGUAGE plpgsql; 

Kết quả:

# select urlencode('http://hu.wikipedia.org/wiki/São_Paulo'); 
-[ RECORD 1 ]------------------------------------------ 
urlencode | http://hu.wikipedia.org/wiki/S%C3%A3o_Paulo 
+0

Oh, cảm ơn bạn! Tôi đang tìm kiếm một chức năng được xây dựng trong hoặc thư viện postgres để cài đặt có chứa loại chức năng này. Tôi lạc quan, tôi nghĩ ai đó đã làm điều đó trước chúng tôi, bởi vì nó là một vấn đề đơn giản/hàng ngày ... Tôi cũng đã gần như cùng một thủ tục lưu trữ, nhưng khi bạn viết quá, nó không hiệu quả và chậm. Và có như bạn đã đề cập phiên bản C bản địa là cách duy nhất để làm cho nó hét lên ...Vì vậy, câu hỏi của tôi là về những gì để cài đặt, những gì để sử dụng, đó là thư viện tốt nhất cho điều này, không viết một loại mã ... :-) – Roki

6

Với PL/V8 ... gian lận?

create function encode_uri(text) returns text language plv8 strict immutable as $$ 
    return encodeURI($1); 
$$; 
1

Đây là "SQL tinh khiết" (không plv8, plpython hoặc thậm chí plpgsql là cần thiết) thực hiện hỗ trợ ký tự nhiều byte (bao gồm 3 và 4-byte biểu tượng cảm xúc):

create or replace function urlencode(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; 

(nguồn: https://github.com/NikolayS/postgrest-google-translate/pull/8)

1

Hôm nay tôi gặp phải "Sẽ không xử lý 3 (hoặc nhiều hơn) chuỗi byte". cho nhân vật Hàn Quốc trong khi tôi đã sử dụng câu trả lời của @vyegorov khá lâu, hơn một năm, cần phải thay đổi nó chỉ đổ các chuỗi hex bytea với "%" tiền tố.

CREATE OR REPLACE FUNCTION urlencode(in_str text, OUT _result text) 
    STRICT IMMUTABLE AS $urlencode$ 
DECLARE 
    _i  int4; 
    _temp varchar; 
    _hex varchar; 
    _ascii int4; 
BEGIN 
    _result = ''; 
    FOR _i IN 1 .. length(in_str) LOOP 
     _temp := substr(in_str, _i, 1); 
     IF _temp ~ '[0-9a-zA-Z:/@._?#-]+' THEN 
      _result := _result || _temp; 
     ELSE 
      _hex := encode(_temp::bytea, 'hex'); 
      _temp := ''; 
      WHILE LENGTH(_hex) > 0 LOOP 
       _temp := _temp || '%' || SUBSTRING(_hex, 1, 2); 
       _hex := SUBSTRING(_hex, 3, 999); 
      END LOOP; 
      _result := _result || upper(_temp); 
     END IF; 
    END LOOP; 
    RETURN ; 
END; 
$urlencode$ LANGUAGE plpgsql; 

dụ,

SELECT urlencode('a') UNION ALL --> "a" 
SELECT urlencode('À') UNION ALL --> "%C3%80" 
SELECT urlencode('Ā') UNION ALL --> "%C4%80" 
SELECT urlencode('ə') UNION ALL --> "%C9%99" 
SELECT urlencode('α') UNION ALL --> "%CE%B1" 
SELECT urlencode('가') UNION ALL --> "%EA%B0%80" 
SELECT urlencode('上') UNION ALL --> "%E4%B8%8A" 
SELECT urlencode('い')   --> "%E3%81%84" 
+0

Tôi cũng vậy ... Cảm ơn. – sashaegorov

Các vấn đề liên quan