Javascript encodeURI как функция в postgresql?
Существует ли какая-либо функция/хранимая процедура в PostgreSQL/plpgsql, которая совпадает с javascripts encodeURI?
Что это значит? Javascript имеет удобную встроенную функцию для кодирования любого вида url:
EncodeURI (url) - > возвращает закодированный url
Например:
encodeURI('http://hu.wikipedia.org/wiki/São_Paulo')
- > возвращает строку, которая является "http://hu.wikipedia.org/wiki/S%C3%A3o_Paulo"
Я ищу точно то же самое.
Я не хочу кодировать каждый параметр отдельно. Мне не нужна такая функция, как javascript encodeURIComponent но это не одно и то же. Приведенный выше пример приводит к другому выходу с
encodeURIComponent('http://hu.wikipedia.org/wiki/São_Paulo')
-> "http%3A%2F%2Fhu.wikipedia.org%2Fwiki%2FS%C3%A3o_Paulo"
Это кодирование всей строки, а не только части пути. Так что это не то, что я ищу. Мне нужна функция plpgsql, которая приводит к эквивалентному выходу функции javascript encodeURI.
Спасибо!
5 ответов:
Я написал расширения PostgreSQL url_enocode, которые решают эту проблему
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
Или
postgres=# select uri_encode('http://hu.wikipedia.org/wiki/São_Paulo'); uri_encode --------------------------------------------- http://hu.wikipedia.org/wiki/S%C3%A3o_Paulo
Медленно и неэффективно, рассмотрим выполнение
C
версии этой функции: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;
Результаты:
# select urlencode('http://hu.wikipedia.org/wiki/São_Paulo'); -[ RECORD 1 ]------------------------------------------ urlencode | http://hu.wikipedia.org/wiki/S%C3%A3o_Paulo
С PL / V8...обман?
create function encode_uri(text) returns text language plv8 strict immutable as $$ return encodeURI($1); $$;
Сегодня я столкнулся с тем, что " не будет иметь дело с 3 (или более) байтовыми последовательностями."для корейских символов, в то время как я использую ответ @vyegorov довольно долгое время, больше года, нужно изменить его просто сбрасывает шестнадцатеричные строки bytea с префиксом"%".
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;
Пример,
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"
Вот" чистый SQL " (не требуется plv8, plpython или даже plpgsql) реализация, поддерживающая многобайтовые символы (включая 3-и 4-байтовые emoji):
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;
(Источник: https://github.com/NikolayS/postgrest-google-translate/pull/8 )