urlencode с только встроенными функциями - PullRequest
3 голосов
/ 04 декабря 2008

Не используя plpgsql, я пытаюсь кодировать заданный текст в инструкции SELECT pgsql.

Проблема с этим подходом:

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

... заключается в том, что функции кодирования не передается параметр regexp, если только не существует другого способа вызова функций из выражения замены, который действительно работает. Поэтому мне интересно, есть ли выражение для замены, которое само по себе может кодировать совпадения в шестнадцатеричные значения.

Возможны другие комбинации функций. Я думал, что там будет умное регулярное выражение (и это все еще может быть ответ), но мне трудно его найти.

Ответы [ 4 ]

6 голосов
/ 04 декабря 2008
select regexp_replace(encode('héllo there','hex'),'(..)',E'%\\1','g');

Это не оставляет буквенно-цифровые символы удобочитаемыми.

1 голос
/ 19 октября 2016

Вот довольно короткая версия, и это даже функция «чистого 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;
1 голос
/ 09 ноября 2015

Вот функция, которую я написал, которая обрабатывает кодирование с использованием встроенных функций, сохраняя читаемость 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 голосов
/ 08 декабря 2008

Вы можете использовать CLR и импортировать пространство имен или использовать функцию, показанную в этой ссылке, это создает функцию T-SQL, которая выполняет кодировку.

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

...