|
1 | | -CREATE TYPE fortune_t AS (id int, message text); |
| 1 | +create domain "text/html" as text; |
2 | 2 |
|
3 | | -create or replace function fortune_template(f fortune_t) returns text as $$ |
4 | | - SELECT format('<tr><td>%s</td><td>%s</td></tr>', $1.id, regexp_replace($1.message, '<', '<','g')); |
5 | | -$$ language sql volatile; |
| 3 | +create or replace function sanitize_html(text) returns text as $$ |
| 4 | + select replace(replace(replace(replace(replace($1, '&', '&'), '"', '"'),'>', '>'),'<', '<'), '''', ''') |
| 5 | +$$ language sql immutable; |
6 | 6 |
|
7 | | -create or replace function fortunes_template(fortunes fortune_t[]) returns text as $$ |
8 | | -WITH header AS ( |
9 | | - SELECT 0 as id,'<!DOCTYPE html> |
10 | | -<html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>' as html |
11 | | -), footer AS ( |
12 | | - SELECT 2,'</table></body></html>' as html |
13 | | -), fortunes AS ( |
14 | | - SELECT unnest as fortune from unnest($1) |
15 | | -), additional AS ( |
16 | | - SELECT (-1, 'Additional fortune added at request time.')::fortune_t as f |
17 | | -), all_fortunes AS ( |
18 | | - SELECT * from (SELECT * FROM fortunes UNION ALL SELECT * from additional) p ORDER BY (fortune).message |
19 | | -), fortunes_html AS ( |
20 | | - SELECT 1,string_agg(fortune_template(fortune), '') from all_fortunes |
21 | | -), html AS ( |
22 | | - SELECT * FROM header UNION SELECT * FROM fortunes_html UNION SELECT * from footer ORDER BY id |
23 | | -) |
24 | | -SELECT string_agg(html,'') from html; |
25 | | -$$ language sql volatile; |
| 7 | +create or replace function fortune_template("Fortune") returns text as $$ |
| 8 | + SELECT format('<tr><td>%s</td><td>%s</td></tr>', $1.id, sanitize_html($1.message)); |
| 9 | +$$ language sql immutable; |
26 | 10 |
|
27 | | -create or replace function "fortunes.html"() returns bytea as $$ |
28 | | -DECLARE |
29 | | - fortunes fortune_t[]; |
30 | | -BEGIN |
31 | | - SET LOCAL "response.headers" = '[{"Content-Type": "text/html"}]'; |
32 | | - SELECT array_agg(CAST((id,message) AS fortune_t)) FROM "Fortunes" INTO fortunes; |
33 | | - RETURN convert_to(fortunes_template(fortunes), 'UTF8'); |
34 | | -END |
35 | | -$$ language plpgsql volatile; |
| 11 | +create or replace function fortunes() returns "text/html" as $$ |
| 12 | + -- This is only necessary bc. of the benchmark: The domain gives us content-type: text/html, |
| 13 | + -- but the benchmark explicitly tests for the charset in the content-type. |
| 14 | + select set_config('response.headers', '[{"Content-Type": "text/html; charset=utf-8"}]', true); |
| 15 | + |
| 16 | + select '<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>' |
| 17 | + || string_agg(fortune_template(f), NULL order by f.message collate unicode asc) |
| 18 | + || '</table></body></html>' |
| 19 | + from (select * from "Fortune" union all select 0, 'Additional fortune added at request time.') f; |
| 20 | +$$ language sql volatile; |
0 commit comments