如何在postgresql中模拟php-urldecode函数



我有一个用php中的urlencode编码的列url。我想做出这样的选择选择some_mix_of_functions(…)作为解码FROM表

替换不是一个好的解决方案,因为我必须手动添加所有解码。还有其他解决方案可以达到预期效果吗?

可以:

CREATE OR REPLACE FUNCTION decode_url_part(p varchar) RETURNS varchar AS $$
SELECT convert_from(CAST(E'\x' || string_agg(CASE WHEN length(r.m[1]) = 1 THEN encode(convert_to(r.m[1], 'SQL_ASCII'), 'hex') ELSE substring(r.m[1] from 2 for 2) END, '') AS bytea), 'UTF8')
FROM regexp_matches($1, '%[0-9a-f][0-9a-f]|.', 'gi') AS r(m);
$$ LANGUAGE SQL IMMUTABLE STRICT;

这创建了一个函数decode_url_part,然后你可以这样使用它:

SELECT decode_url_part('your%20urlencoded%20string')

或者,您可以只使用上面函数体中的函数和子查询的组合。

它不处理"+"字符(表示空白),但我想添加它很容易(如果您需要的话)。

此外,这假设utf-8编码用于非ascii字符,但如果需要,您可以将"UTF8"替换为自己的编码。

需要注意的是,上面的代码依赖于未记录的postgresql特性,即regexp_matches函数的结果按照它们在原始字符串中出现的顺序进行处理(这是自然的,但在文档中没有指定)。

正如PabloSantaCruz所指出的,string_agg是一个PostgreSQL 9.0聚合函数。下面的等效代码没有使用它(我希望它适用于8.x):

SELECT convert_from(CAST(E'\x' || array_to_string(ARRAY(
    SELECT CASE WHEN length(r.m[1]) = 1 THEN encode(convert_to(r.m[1], 'SQL_ASCII'), 'hex') ELSE substring(r.m[1] from 2 for 2) END
    FROM regexp_matches($1, '%[0-9a-f][0-9a-f]|.', 'gi') AS r(m)
), '') AS bytea), 'UTF8');

不开箱即用。但是您可以创建一个pl/perl函数来封装等价的perl。(或者一个pl.php函数)。

最新更新