Change uri_path to return text

This commit is contained in:
Peter Eisentraut 2015-04-03 22:49:52 -04:00
parent 53789ec067
commit 527cc23bc4
5 changed files with 218 additions and 126 deletions

View File

@ -88,6 +88,19 @@ A number of functions are provided to extract parts of a URI:
Extracts the port of a URI as an integer, for example `5432`. If Extracts the port of a URI as an integer, for example `5432`. If
no port is specified, the return value is null. no port is specified, the return value is null.
- `uri_path(uri) returns text`
Extracts the path component of a URI. Logically, a URI always
contains a path. The return value can be an empty string but
never null.
- `uri_path_array(uri) returns text[]`
Returns the path component of a URI as an array, with the path
split at the slash characters. This is probably not as useful as
the `uri_path` function, but it is provided here because the
`uriparser` library exposes it.
- `uri_query(uri) returns text` - `uri_query(uri) returns text`
Extracts the query part of a URI (roughly speaking, everything Extracts the query part of a URI (roughly speaking, everything

View File

@ -13,7 +13,9 @@ VALUES ('http://www.postgresql.org/'),
('http://[1080::8:800:200C:417A]/foo'), ('http://[1080::8:800:200C:417A]/foo'),
('http://host:'), ('http://host:'),
(''), (''),
('foobar'); ('/'),
('foobar'),
('/foobar');
SELECT * FROM test; SELECT * FROM test;
a | b a | b
----+----------------------------------------------------------------------------------------- ----+-----------------------------------------------------------------------------------------
@ -28,8 +30,10 @@ SELECT * FROM test;
9 | http://[1080::8:800:200C:417A]/foo 9 | http://[1080::8:800:200C:417A]/foo
10 | http://host: 10 | http://host:
11 | 11 |
12 | foobar 12 | /
(12 rows) 13 | foobar
14 | /foobar
(14 rows)
-- error cases -- error cases
SELECT uri 'http://host:port/'; SELECT uri 'http://host:port/';
@ -44,135 +48,172 @@ SELECT b AS uri,
uri_host_inet(b), uri_host_inet(b),
uri_port(b), uri_port(b),
uri_path(b), uri_path(b),
uri_path_array(b),
uri_query(b), uri_query(b),
uri_fragment(b) uri_fragment(b)
FROM test; FROM test;
-[ RECORD 1 ]-+---------------------------------------------------------------------------------------- -[ RECORD 1 ]--+----------------------------------------------------------------------------------------
uri | http://www.postgresql.org/ uri | http://www.postgresql.org/
uri_scheme | http uri_scheme | http
uri_userinfo | _null_ uri_userinfo | _null_
uri_host | www.postgresql.org uri_host | www.postgresql.org
uri_host_inet | _null_ uri_host_inet | _null_
uri_port | _null_ uri_port | _null_
uri_path | {""} uri_path | /
uri_query | _null_ uri_path_array | {""}
uri_fragment | _null_ uri_query | _null_
-[ RECORD 2 ]-+---------------------------------------------------------------------------------------- uri_fragment | _null_
uri | http://www.postgresql.org/docs/devel/static/xfunc-sql.html#XFUNC-SQL-FUNCTION-ARGUMENTS -[ RECORD 2 ]--+----------------------------------------------------------------------------------------
uri_scheme | http uri | http://www.postgresql.org/docs/devel/static/xfunc-sql.html#XFUNC-SQL-FUNCTION-ARGUMENTS
uri_userinfo | _null_ uri_scheme | http
uri_host | www.postgresql.org uri_userinfo | _null_
uri_host_inet | _null_ uri_host | www.postgresql.org
uri_port | _null_ uri_host_inet | _null_
uri_path | {docs,devel,static,xfunc-sql.html} uri_port | _null_
uri_query | _null_ uri_path | /docs/devel/static/xfunc-sql.html
uri_fragment | XFUNC-SQL-FUNCTION-ARGUMENTS uri_path_array | {docs,devel,static,xfunc-sql.html}
-[ RECORD 3 ]-+---------------------------------------------------------------------------------------- uri_query | _null_
uri | https://duckduckgo.com/?q=postgresql&ia=about uri_fragment | XFUNC-SQL-FUNCTION-ARGUMENTS
uri_scheme | https -[ RECORD 3 ]--+----------------------------------------------------------------------------------------
uri_userinfo | _null_ uri | https://duckduckgo.com/?q=postgresql&ia=about
uri_host | duckduckgo.com uri_scheme | https
uri_host_inet | _null_ uri_userinfo | _null_
uri_port | _null_ uri_host | duckduckgo.com
uri_path | {""} uri_host_inet | _null_
uri_query | q=postgresql&ia=about uri_port | _null_
uri_fragment | _null_ uri_path | /
-[ RECORD 4 ]-+---------------------------------------------------------------------------------------- uri_path_array | {""}
uri | ftp://ftp.gnu.org/gnu/bison uri_query | q=postgresql&ia=about
uri_scheme | ftp uri_fragment | _null_
uri_userinfo | _null_ -[ RECORD 4 ]--+----------------------------------------------------------------------------------------
uri_host | ftp.gnu.org uri | ftp://ftp.gnu.org/gnu/bison
uri_host_inet | _null_ uri_scheme | ftp
uri_port | _null_ uri_userinfo | _null_
uri_path | {gnu,bison} uri_host | ftp.gnu.org
uri_query | _null_ uri_host_inet | _null_
uri_fragment | _null_ uri_port | _null_
-[ RECORD 5 ]-+---------------------------------------------------------------------------------------- uri_path | /gnu/bison
uri | mailto:foo@example.com uri_path_array | {gnu,bison}
uri_scheme | mailto uri_query | _null_
uri_userinfo | _null_ uri_fragment | _null_
uri_host | _null_ -[ RECORD 5 ]--+----------------------------------------------------------------------------------------
uri_host_inet | _null_ uri | mailto:foo@example.com
uri_port | _null_ uri_scheme | mailto
uri_path | {foo@example.com} uri_userinfo | _null_
uri_query | _null_ uri_host | _null_
uri_fragment | _null_ uri_host_inet | _null_
-[ RECORD 6 ]-+---------------------------------------------------------------------------------------- uri_port | _null_
uri | ssh://username@review.openstack.org:29418/openstack/nova.git uri_path | foo@example.com
uri_scheme | ssh uri_path_array | {foo@example.com}
uri_userinfo | username uri_query | _null_
uri_host | review.openstack.org uri_fragment | _null_
uri_host_inet | _null_ -[ RECORD 6 ]--+----------------------------------------------------------------------------------------
uri_port | 29418 uri | ssh://username@review.openstack.org:29418/openstack/nova.git
uri_path | {openstack,nova.git} uri_scheme | ssh
uri_query | _null_ uri_userinfo | username
uri_fragment | _null_ uri_host | review.openstack.org
-[ RECORD 7 ]-+---------------------------------------------------------------------------------------- uri_host_inet | _null_
uri | http://admin:password@192.168.0.1 uri_port | 29418
uri_scheme | http uri_path | /openstack/nova.git
uri_userinfo | admin:password uri_path_array | {openstack,nova.git}
uri_host | 192.168.0.1 uri_query | _null_
uri_host_inet | 192.168.0.1 uri_fragment | _null_
uri_port | _null_ -[ RECORD 7 ]--+----------------------------------------------------------------------------------------
uri_path | {} uri | http://admin:password@192.168.0.1
uri_query | _null_ uri_scheme | http
uri_fragment | _null_ uri_userinfo | admin:password
-[ RECORD 8 ]-+---------------------------------------------------------------------------------------- uri_host | 192.168.0.1
uri | http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html uri_host_inet | 192.168.0.1
uri_scheme | http uri_port | _null_
uri_userinfo | _null_ uri_path |
uri_host | FEDC:BA98:7654:3210:FEDC:BA98:7654:3210 uri_path_array | {}
uri_host_inet | fedc:ba98:7654:3210:fedc:ba98:7654:3210 uri_query | _null_
uri_port | 80 uri_fragment | _null_
uri_path | {index.html} -[ RECORD 8 ]--+----------------------------------------------------------------------------------------
uri_query | _null_ uri | http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
uri_fragment | _null_ uri_scheme | http
-[ RECORD 9 ]-+---------------------------------------------------------------------------------------- uri_userinfo | _null_
uri | http://[1080::8:800:200C:417A]/foo uri_host | FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
uri_scheme | http uri_host_inet | fedc:ba98:7654:3210:fedc:ba98:7654:3210
uri_userinfo | _null_ uri_port | 80
uri_host | 1080::8:800:200C:417A uri_path | /index.html
uri_host_inet | 1080::8:800:200c:417a uri_path_array | {index.html}
uri_port | _null_ uri_query | _null_
uri_path | {foo} uri_fragment | _null_
uri_query | _null_ -[ RECORD 9 ]--+----------------------------------------------------------------------------------------
uri_fragment | _null_ uri | http://[1080::8:800:200C:417A]/foo
-[ RECORD 10 ]+---------------------------------------------------------------------------------------- uri_scheme | http
uri | http://host: uri_userinfo | _null_
uri_scheme | http uri_host | 1080::8:800:200C:417A
uri_userinfo | _null_ uri_host_inet | 1080::8:800:200c:417a
uri_host | host uri_port | _null_
uri_host_inet | _null_ uri_path | /foo
uri_port | _null_ uri_path_array | {foo}
uri_path | {} uri_query | _null_
uri_query | _null_ uri_fragment | _null_
uri_fragment | _null_ -[ RECORD 10 ]-+----------------------------------------------------------------------------------------
-[ RECORD 11 ]+---------------------------------------------------------------------------------------- uri | http://host:
uri | uri_scheme | http
uri_scheme | _null_ uri_userinfo | _null_
uri_userinfo | _null_ uri_host | host
uri_host | _null_ uri_host_inet | _null_
uri_host_inet | _null_ uri_port | _null_
uri_port | _null_ uri_path |
uri_path | {} uri_path_array | {}
uri_query | _null_ uri_query | _null_
uri_fragment | _null_ uri_fragment | _null_
-[ RECORD 12 ]+---------------------------------------------------------------------------------------- -[ RECORD 11 ]-+----------------------------------------------------------------------------------------
uri | foobar uri |
uri_scheme | _null_ uri_scheme | _null_
uri_userinfo | _null_ uri_userinfo | _null_
uri_host | _null_ uri_host | _null_
uri_host_inet | _null_ uri_host_inet | _null_
uri_port | _null_ uri_port | _null_
uri_path | {foobar} uri_path |
uri_query | _null_ uri_path_array | {}
uri_fragment | _null_ uri_query | _null_
uri_fragment | _null_
-[ RECORD 12 ]-+----------------------------------------------------------------------------------------
uri | /
uri_scheme | _null_
uri_userinfo | _null_
uri_host | _null_
uri_host_inet | _null_
uri_port | _null_
uri_path | /
uri_path_array | {}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 13 ]-+----------------------------------------------------------------------------------------
uri | foobar
uri_scheme | _null_
uri_userinfo | _null_
uri_host | _null_
uri_host_inet | _null_
uri_port | _null_
uri_path | foobar
uri_path_array | {foobar}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 14 ]-+----------------------------------------------------------------------------------------
uri | /foobar
uri_scheme | _null_
uri_userinfo | _null_
uri_host | _null_
uri_host_inet | _null_
uri_port | _null_
uri_path | /foobar
uri_path_array | {foobar}
uri_query | _null_
uri_fragment | _null_
\x off \x off
SELECT DISTINCT b FROM test ORDER BY b; SELECT DISTINCT b FROM test ORDER BY b;
b b
----------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------
/
/foobar
foobar foobar
ftp://ftp.gnu.org/gnu/bison ftp://ftp.gnu.org/gnu/bison
http://[1080::8:800:200C:417A]/foo http://[1080::8:800:200C:417A]/foo
@ -184,5 +225,5 @@ SELECT DISTINCT b FROM test ORDER BY b;
https://duckduckgo.com/?q=postgresql&ia=about https://duckduckgo.com/?q=postgresql&ia=about
mailto:foo@example.com mailto:foo@example.com
ssh://username@review.openstack.org:29418/openstack/nova.git ssh://username@review.openstack.org:29418/openstack/nova.git
(12 rows) (14 rows)

View File

@ -16,7 +16,9 @@ VALUES ('http://www.postgresql.org/'),
('http://[1080::8:800:200C:417A]/foo'), ('http://[1080::8:800:200C:417A]/foo'),
('http://host:'), ('http://host:'),
(''), (''),
('foobar'); ('/'),
('foobar'),
('/foobar');
SELECT * FROM test; SELECT * FROM test;
@ -32,6 +34,7 @@ SELECT b AS uri,
uri_host_inet(b), uri_host_inet(b),
uri_port(b), uri_port(b),
uri_path(b), uri_path(b),
uri_path_array(b),
uri_query(b), uri_query(b),
uri_fragment(b) uri_fragment(b)
FROM test; FROM test;

29
uri.c
View File

@ -1,6 +1,7 @@
#include <postgres.h> #include <postgres.h>
#include <catalog/pg_type.h> #include <catalog/pg_type.h>
#include <fmgr.h> #include <fmgr.h>
#include <lib/stringinfo.h>
#include <utils/array.h> #include <utils/array.h>
#include <utils/builtins.h> #include <utils/builtins.h>
#include <utils/inet.h> #include <utils/inet.h>
@ -223,6 +224,34 @@ uri_fragment(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(uri_path); PG_FUNCTION_INFO_V1(uri_path);
Datum Datum
uri_path(PG_FUNCTION_ARGS) uri_path(PG_FUNCTION_ARGS)
{
Datum arg = PG_GETARG_DATUM(0);
char *s = TextDatumGetCString(arg);
UriUriA uri;
StringInfoData buf;
UriPathSegmentA *p;
initStringInfo(&buf);
parse_uri(s, &uri);
if (uri.absolutePath || (uriIsHostSetA(&uri) && uri.pathHead))
appendStringInfoChar(&buf, '/');
for (p = uri.pathHead; p; p = p->next)
{
appendBinaryStringInfo(&buf, p->text.first, p->text.afterLast - p->text.first);
if (p->next)
appendStringInfoChar(&buf, '/');
}
uriFreeUriMembersA(&uri);
PG_RETURN_TEXT_P(cstring_to_text(buf.data));
}
PG_FUNCTION_INFO_V1(uri_path_array);
Datum
uri_path_array(PG_FUNCTION_ARGS)
{ {
Datum arg = PG_GETARG_DATUM(0); Datum arg = PG_GETARG_DATUM(0);
char *s = TextDatumGetCString(arg); char *s = TextDatumGetCString(arg);

View File

@ -68,7 +68,13 @@ CREATE FUNCTION uri_fragment(uri) RETURNS text
LANGUAGE C LANGUAGE C
AS '$libdir/uri'; AS '$libdir/uri';
CREATE FUNCTION uri_path(uri) RETURNS text[] CREATE FUNCTION uri_path(uri) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_path_array(uri) RETURNS text[]
IMMUTABLE IMMUTABLE
STRICT STRICT
LANGUAGE C LANGUAGE C