2012-04-25 5 views
5

¿Existe alguna función/procedimiento almacenado en PostgreSQL/plpgsql que sea igual que los javascripts coddeURI?Javascript encodeURI como función en postgresql?

¿Qué significa? Javascript tiene un práctico construido en función de codificar cualquier tipo de url:

encodeURI (URL) -> Devuelve la URL codificada

Por ejemplo: encodeURI('http://hu.wikipedia.org/wiki/São_Paulo') -> Devuelve una cadena que es "http://hu.wikipedia.org/wiki/S%C3%A3o_Paulo"

I buscando exactamente lo mismo.

No deseo codificar cada parámetro por separado. No quiero una función como javascript encodeURIComponent, que no es la misma. El ejemplo anterior da como resultado una salida diferente con

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

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

Es codificar toda la cadena no sólo la parte de la ruta. Entonces esto no es lo que estoy buscando. Necesito una función plpgsql que dé como resultado una salida equivalente a la función javascript encodeURI.

Gracias!

Respuesta

4

que escribí extensiones PostgreSQL url_enocode que resolver este problema

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 

o

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

Esta parece ser la solución más cercana a lo que necesito ... – Roki

+0

Quizás lo modifique un poco ... Tiene un error, después del protocolo (http) ... Si agrega c == ':' en la línea 95, funcionará perfectamente ... (y la línea 154 también ... para ser consistente) – Roki

+0

Esta es solo la versión inicial. Agregaré las funciones uri_encode y uri_decode, no puedo modificar como propones, porque: es chars reservados. –

11

lenta e ineficiente, considere hacer la versión C de esta función:

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; 

Resultados:

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

Oh, gracias! Estoy buscando una función incorporada o una biblioteca postgres para instalar que contenga este tipo de función. Soy optimista, y creo que alguien lo hizo antes que nosotros, porque es un problema simple/cotidiano ... También hice casi el mismo procedimiento almacenado, pero como escribiste también, es ineficaz y lento. Y sí, como mencionaste la versión C nativa es la única manera de hacerlo gritar ...Entonces, mi pregunta es sobre qué instalar, qué usar, cuál es la mejor biblioteca para esto, no escribir un tipo de código ... :-) – Roki

6

Con PL/V8 ... hacer trampa?

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

aquí es "pura SQL" (sin plv8, plpython o plpgsql se necesita aun) la implementación de apoyo caracteres de varios bytes (incluyendo emoji de 3 y de 4 bytes):

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; 

(fuente: https://github.com/NikolayS/postgrest-google-translate/pull/8)

1

Hoy me encontré con "No tratará con 3 (o más) secuencias de bytes." para los caracteres coreanos, mientras he estado usando la respuesta de @vyegorov durante bastante tiempo, más de un año, necesito cambiarlo, solo tira las cadenas hexagonales de bytea con el prefijo "%".

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; 

ejemplo,

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

Yo también ... Gracias. – sashaegorov

Cuestiones relacionadas