Domanda

Senza usare plpgsql, sto cercando di urlencode un dato testo all'interno di un'istruzione SELECT pgsql.

Il problema con questo approccio:

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

... è che alla funzione di codifica non viene passato il parametro regexp, a meno che non ci sia un altro modo per chiamare le funzioni dall'espressione di sostituzione che funziona effettivamente. Quindi mi chiedo se esiste un'espressione sostitutiva che, da sola, può codificare le corrispondenze in valori esadecimali.

Potrebbero esserci altre combinazioni di funzioni. Ho pensato che ci sarebbe stata una regex intelligente (e questa potrebbe essere ancora la risposta) là fuori, ma ho difficoltà a trovarla.

È stato utile?

Soluzione

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

Questo non lascia i caratteri alfanumerici leggibili dall'uomo, però.

Altri suggerimenti

Ecco una funzione che ho scritto che gestisce la codifica utilizzando le funzioni integrate preservando la leggibilità dell'URL.

Regex si abbina per catturare coppie di caratteri (facoltativi) sicuri e (al massimo uno) caratteri non sicuri. Le selezioni nidificate consentono a quelle coppie di essere codificate e ricombinate restituendo una stringa completamente codificata.

Ho eseguito una suite di test con tutti i tipi di permutazioni (caratteri codificati iniziali / finali / solo / ripetuti e finora sembra codificare correttamente.

I caratteri speciali sicuri sono _ ~. - e /. La mia inclusione di " / " su quell'elenco è probabilmente non standard, ma si adatta al caso d'uso che ho dove il testo di input può essere un percorso e voglio che rimanga.

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$

Ecco una versione piuttosto breve, ed è persino " puro SQL " funzione, non plpgsql. Sono supportati caratteri multibyte (incluse emoji a 3 e 4 byte).

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;

Puoi usare CLR e importare lo spazio dei nomi o usare la funzione mostrata in questo link, questo crea una funzione T-SQL che esegue la codifica.

http://www.sqljunkies.com /WebLog/peter_debetta/archive/2007/03/09/28987.aspx

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top