4

I have a column url encoded with urlencode in php. I wish to make a select like this SELECT some_mix_of_functions(...) AS Decoded FROM table

Replace is not a good solution because I will have to add all the decoding by hand. Any other solution to get the desire result ?

2 Answers 2

15

Yes you can:

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;

This creates a function decode_url_part, then you can use it like that:

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

Or you can just use the mix of functions and subqueries from the body of the above function.

This doesn't handle '+' characters (representing whitespace), but I guess adding this is quite easy (if you ever need it).

Also, this assumes utf-8 encoding for non-ascii characters, but you can replace 'UTF8' with your own encoding if you want.

It should be noted that the above code relies on undocumented postgresql feature, namely that the results of regexp_matches function are processed in the order they occur in the original string (which is natural, but not specified in docs).

As Pablo Santa Cruz notes, string_agg is a PostgreSQL 9.0 aggregate function. The equivalent code below doesn't use it (I hope it works for 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');
Sign up to request clarification or add additional context in comments.

1 Comment

Please note that string_aggis a PostgreSQL 9.0 aggregate function.
0

Not out of the box. But you could create a pl/perl function that wraps the perl equivalent. (Or a pl/php function).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.