Compare commits

..

No commits in common. "master" and "1.20150415" have entirely different histories.

22 changed files with 68 additions and 876 deletions

View File

@ -1,35 +0,0 @@
env:
DEBIAN_FRONTEND: noninteractive
LANG: C
task:
name: Linux (Debian/Ubuntu)
matrix:
- container:
image: ubuntu:20.04
env:
matrix:
- PGVERSION: 14
- PGVERSION: 13
- PGVERSION: 12
- PGVERSION: 11
- PGVERSION: 10
- PGVERSION: 9.6
- PGVERSION: 9.5
- PGVERSION: 9.4
- PGVERSION: 9.3
setup_script:
- apt-get update
- apt-get -y install curl gnupg lsb-release
- curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
- echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
- apt-get update
- apt-get -y install gcc liburiparser-dev make pkg-config postgresql-$PGVERSION postgresql-server-dev-$PGVERSION
- pg_createcluster --start $PGVERSION test -p 55435 -- -A trust
build_script:
- PATH=/usr/lib/postgresql/$PGVERSION/bin:$PATH
- make all
- make install
test_script:
- PATH=/usr/lib/postgresql/$PGVERSION/bin:$PATH
- PGPORT=55435 make installcheck PGUSER=postgres

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.o
*.so
/results/
/*--*.sql

14
.travis.yml Normal file
View File

@ -0,0 +1,14 @@
language: c
before_install:
- wget https://gist.github.com/petere/5893799/raw/apt.postgresql.org.sh
- wget https://gist.github.com/petere/6023944/raw/pg-travis-test.sh
- sudo sh ./apt.postgresql.org.sh
install:
- sudo apt-get install -qq liburiparser-dev
env:
- PGVERSION=9.1
- PGVERSION=9.2
- PGVERSION=9.3
- PGVERSION=9.4
script:
- bash ./pg-travis-test.sh

View File

@ -1,19 +0,0 @@
© 2015 Peter Eisentraut <peter@eisentraut.org>
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written
agreement is hereby granted, provided that the above copyright notice
and this paragraph and the following two paragraphs appear in all
copies.
IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
DOCUMENTATION, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
IS" BASIS, AND THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

View File

@ -1,10 +1,12 @@
PG_CONFIG = pg_config
PKG_CONFIG = pkg-config
extension_version = 0
EXTENSION = uri
MODULE_big = uri
OBJS = uri.o
DATA = uri--0.sql uri--1.sql uri--0--1.sql
DATA_built = uri--$(extension_version).sql
ifeq (no,$(shell $(PKG_CONFIG) liburiparser || echo no))
$(warning liburiparser not registed with pkg-config, build might fail)
@ -13,8 +15,11 @@ endif
PG_CPPFLAGS += $(shell $(PKG_CONFIG) --cflags-only-I liburiparser)
SHLIB_LINK += $(shell $(PKG_CONFIG) --libs liburiparser)
REGRESS = init test escape
REGRESS = init test
REGRESS_OPTS = --inputdir=test
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
uri--$(extension_version).sql: uri.sql
cat $^ >$@

View File

@ -126,22 +126,3 @@ Other functions:
without normalization. If you want to consider distinct URIs
without regard for mostly irrelevant syntax differences, pass them
through this function.
- `uri_escape(text, space_to_plus boolean DEFAULT false, normalize_breaks boolean DEFAULT false) returns text`
Percent-encodes all reserved characters from the text. This can
be useful for constructing URIs from strings.
If `space_to_plus` is true, then spaces are replaced by plus
signs. If `normalize_breaks` is true, then line breaks are
converted to CR LF pairs (and subsequently percent-encoded). Note
that these two conversions come from the HTML standard for
encoding form data but are not part of the specification for URIs.
- `uri_unescape(text, plus_to_space boolean DEFAULT false, break_conversion boolean DEFAULT false) returns text`
Decodes all percent-encodings in the text.
If `plus_to_space` is true, then plus signs are converted to
spaces. If `break_conversion` is true, then CR LF pairs are
converted to simple newlines (`\n`).

23
debian/changelog vendored
View File

@ -1,23 +0,0 @@
pguri (1.20151224-4) bookworm; urgency=medium
* Update PostgreSQL version to 15
-- jordi fita mas <jordi@tandem.blog> Thu, 15 Jun 2023 10:44:11 +0000
pguri (1.20151224-3) bullseye; urgency=medium
* Fix architecture from all to any
-- jordi fita mas <jordi@tandem.blog> Wed, 25 Jan 2023 00:07:13 +0000
pguri (1.20151224-2) bullseye; urgency=medium
* Add pkg-config dependency
-- jordi fita mas <jordi@tandem.blog> Tue, 24 Jan 2023 14:21:22 +0000
pguri (1.20151224-1) bullseye; urgency=medium
* Add Debian packaging
-- jordi fita mas <jordi@tandem.blog> Tue, 24 Jan 2023 13:07:39 +0000

35
debian/control vendored
View File

@ -1,35 +0,0 @@
Source: pguri
Section: database
Priority: optional
Maintainer: jordi fita mas <jordi@tandem.blog>
Build-Depends:
debhelper-compat (= 13),
postgresql-all (>= 217~),
liburiparser-dev,
pkg-config
Standards-Version: 4.6.0
Vcs-Browser: https://github.com/petere/pguri
Vcs-Git: https://github.com/petere/pguri.git
Homepage: https://github.com/petere/pguri
Rules-Requires-Root: no
Package: postgresql-15-pguri
Architecture: any
Depends:
${shlibs:Depends},
${misc:Depends},
postgresql-15
description: uri type for PostgreSQL
This is an extension for PostgreSQL that provides a uri data type. Advantages
over using plain text for storing URIs include:
.
* URI syntax checking,
* functions for extracting URI components, and
* human-friendly sorting.
.
The actual URI parsing is provided by the uriparser library, which supports
URI syntax as per RFC 3986.
.
Note that this might not be the right data type to use if you want to store
user-provided URI data, such as HTTP referrers, since they might contain
arbitrary junk.

35
debian/control.in vendored
View File

@ -1,35 +0,0 @@
Source: pguri
Section: database
Priority: optional
Maintainer: jordi fita mas <jordi@tandem.blog>
Build-Depends:
debhelper-compat (= 13),
postgresql-all (>= 217~),
liburiparser-dev,
pkg-config
Standards-Version: 4.6.0
Vcs-Browser: https://github.com/petere/pguri
Vcs-Git: https://github.com/petere/pguri.git
Homepage: https://github.com/petere/pguri
Rules-Requires-Root: no
Package: postgresql-PGVERSION-pguri
Architecture: any
Depends:
${shlibs:Depends},
${misc:Depends},
postgresql-PGVERSION
description: uri type for PostgreSQL
This is an extension for PostgreSQL that provides a uri data type. Advantages
over using plain text for storing URIs include:
.
* URI syntax checking,
* functions for extracting URI components, and
* human-friendly sorting.
.
The actual URI parsing is provided by the uriparser library, which supports
URI syntax as per RFC 3986.
.
Note that this might not be the right data type to use if you want to store
user-provided URI data, such as HTTP referrers, since they might contain
arbitrary junk.

29
debian/copyright vendored
View File

@ -1,29 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://github.com/petere/pguri
Upstream-Name: pguri
Upstream-Contact: peter@eisentraut.org
Files: *
Copyright: 2015 Peter Eisentraut
License:
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement is
hereby granted, provided that the above copyright notice and this paragraph and
the following two paragraphs appear in all copies.
.
IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHORS HAVE
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.
THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE
AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
Files: debian/*
Copyright: 2023 jordi fita mas
License:
This debian package is distributed under the same license as the source
package.

1
debian/pgversions vendored
View File

@ -1 +0,0 @@
13+

6
debian/rules vendored
View File

@ -1,6 +0,0 @@
#!/usr/bin/make -f
include /usr/share/postgresql-common/pgxs_debian_control.mk
%:
dh $@ --with pgxs_loop

View File

@ -1 +0,0 @@
3.0 (quilt)

View File

@ -1,99 +0,0 @@
SELECT uri_escape('foobar');
uri_escape
------------
foobar
(1 row)
SELECT uri_escape(':/?#[]@!$&''()*+,;=');
uri_escape
--------------------------------------------------------
%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D
(1 row)
SELECT uri_escape('foo bar');
uri_escape
------------
foo%20bar
(1 row)
SELECT uri_escape('foo bar', space_to_plus := false);
uri_escape
------------
foo%20bar
(1 row)
SELECT uri_escape('foo bar', space_to_plus := true);
uri_escape
------------
foo+bar
(1 row)
SELECT uri_escape(E'foo\nbar');
uri_escape
------------
foo%0Abar
(1 row)
SELECT uri_escape(E'foo\nbar', normalize_breaks := false);
uri_escape
------------
foo%0Abar
(1 row)
SELECT uri_escape(E'foo\nbar', normalize_breaks := true);
uri_escape
--------------
foo%0D%0Abar
(1 row)
SELECT uri_unescape('foobar');
uri_unescape
--------------
foobar
(1 row)
SELECT uri_unescape('%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D');
uri_unescape
--------------------
:/?#[]@!$&'()*+,;=
(1 row)
SELECT uri_unescape('foo+bar');
uri_unescape
--------------
foo+bar
(1 row)
SELECT uri_unescape('foo+bar', plus_to_space := false);
uri_unescape
--------------
foo+bar
(1 row)
SELECT uri_unescape('foo+bar', plus_to_space := true);
uri_unescape
--------------
foo bar
(1 row)
SELECT uri_unescape('foo%0D%0Abar');
uri_unescape
--------------
foo +
bar
(1 row)
SELECT uri_unescape('foo%0D%0Abar', break_conversion := false);
uri_unescape
--------------
foo +
bar
(1 row)
SELECT uri_unescape('foo%0D%0Abar', break_conversion := true);
uri_unescape
--------------
foo\r +
bar
(1 row)

View File

@ -4,14 +4,10 @@ CREATE TABLE test (a serial, b uri);
INSERT INTO test (b)
VALUES ('http://www.postgresql.org/'),
('http://www.postgresql.org/docs/devel/static/xfunc-sql.html#XFUNC-SQL-FUNCTION-ARGUMENTS'),
('http://www.postgresql.org:591/'),
('http://www.postgresql.org:80/'),
('https://duckduckgo.com/?q=postgresql&ia=about'),
('ftp://ftp.gnu.org/gnu/bison'),
('mailto:foo@example.com'),
('ssh://username@review.openstack.org:29418/openstack/nova.git'),
('ssh://foobar@review.openstack.org:29418/openstack/nova.git'),
('ssh://review.openstack.org:29418/openstack/nova.git'),
('http://admin:password@192.168.0.1'),
('http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html'),
('http://[1080::8:800:200C:417A]/foo'),
@ -30,26 +26,22 @@ SELECT * FROM test;
----+-----------------------------------------------------------------------------------------
1 | http://www.postgresql.org/
2 | http://www.postgresql.org/docs/devel/static/xfunc-sql.html#XFUNC-SQL-FUNCTION-ARGUMENTS
3 | http://www.postgresql.org:591/
4 | http://www.postgresql.org:80/
5 | https://duckduckgo.com/?q=postgresql&ia=about
6 | ftp://ftp.gnu.org/gnu/bison
7 | mailto:foo@example.com
8 | ssh://username@review.openstack.org:29418/openstack/nova.git
9 | ssh://foobar@review.openstack.org:29418/openstack/nova.git
10 | ssh://review.openstack.org:29418/openstack/nova.git
11 | http://admin:password@192.168.0.1
12 | http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
13 | http://[1080::8:800:200C:417A]/foo
14 | http://host:
15 |
16 | /
17 | foobar
18 | /foobar
19 | HTTP://www.EXAMPLE.com/
20 | http://www.ex%41mple.com/
21 | eXAMPLE://a/./b/../b/%63/%7bfoo%7d
(21 rows)
3 | https://duckduckgo.com/?q=postgresql&ia=about
4 | ftp://ftp.gnu.org/gnu/bison
5 | mailto:foo@example.com
6 | ssh://username@review.openstack.org:29418/openstack/nova.git
7 | http://admin:password@192.168.0.1
8 | http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
9 | http://[1080::8:800:200C:417A]/foo
10 | http://host:
11 |
12 | /
13 | foobar
14 | /foobar
15 | HTTP://www.EXAMPLE.com/
16 | http://www.ex%41mple.com/
17 | eXAMPLE://a/./b/../b/%63/%7bfoo%7d
(17 rows)
-- error cases
SELECT uri 'http://host:port/';
@ -94,30 +86,6 @@ uri_path_array | {docs,devel,static,xfunc-sql.html}
uri_query | _null_
uri_fragment | XFUNC-SQL-FUNCTION-ARGUMENTS
-[ RECORD 3 ]--+----------------------------------------------------------------------------------------
uri | http://www.postgresql.org:591/
uri_normalize | http://www.postgresql.org:591/
uri_scheme | http
uri_userinfo | _null_
uri_host | www.postgresql.org
uri_host_inet | _null_
uri_port | 591
uri_path | /
uri_path_array | {""}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 4 ]--+----------------------------------------------------------------------------------------
uri | http://www.postgresql.org:80/
uri_normalize | http://www.postgresql.org:80/
uri_scheme | http
uri_userinfo | _null_
uri_host | www.postgresql.org
uri_host_inet | _null_
uri_port | 80
uri_path | /
uri_path_array | {""}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 5 ]--+----------------------------------------------------------------------------------------
uri | https://duckduckgo.com/?q=postgresql&ia=about
uri_normalize | https://duckduckgo.com/?q=postgresql&ia=about
uri_scheme | https
@ -129,7 +97,7 @@ uri_path | /
uri_path_array | {""}
uri_query | q=postgresql&ia=about
uri_fragment | _null_
-[ RECORD 6 ]--+----------------------------------------------------------------------------------------
-[ RECORD 4 ]--+----------------------------------------------------------------------------------------
uri | ftp://ftp.gnu.org/gnu/bison
uri_normalize | ftp://ftp.gnu.org/gnu/bison
uri_scheme | ftp
@ -141,7 +109,7 @@ uri_path | /gnu/bison
uri_path_array | {gnu,bison}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 7 ]--+----------------------------------------------------------------------------------------
-[ RECORD 5 ]--+----------------------------------------------------------------------------------------
uri | mailto:foo@example.com
uri_normalize | mailto:foo@example.com
uri_scheme | mailto
@ -153,7 +121,7 @@ uri_path | foo@example.com
uri_path_array | {foo@example.com}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 8 ]--+----------------------------------------------------------------------------------------
-[ RECORD 6 ]--+----------------------------------------------------------------------------------------
uri | ssh://username@review.openstack.org:29418/openstack/nova.git
uri_normalize | ssh://username@review.openstack.org:29418/openstack/nova.git
uri_scheme | ssh
@ -165,31 +133,7 @@ uri_path | /openstack/nova.git
uri_path_array | {openstack,nova.git}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 9 ]--+----------------------------------------------------------------------------------------
uri | ssh://foobar@review.openstack.org:29418/openstack/nova.git
uri_normalize | ssh://foobar@review.openstack.org:29418/openstack/nova.git
uri_scheme | ssh
uri_userinfo | foobar
uri_host | review.openstack.org
uri_host_inet | _null_
uri_port | 29418
uri_path | /openstack/nova.git
uri_path_array | {openstack,nova.git}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 10 ]-+----------------------------------------------------------------------------------------
uri | ssh://review.openstack.org:29418/openstack/nova.git
uri_normalize | ssh://review.openstack.org:29418/openstack/nova.git
uri_scheme | ssh
uri_userinfo | _null_
uri_host | review.openstack.org
uri_host_inet | _null_
uri_port | 29418
uri_path | /openstack/nova.git
uri_path_array | {openstack,nova.git}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 11 ]-+----------------------------------------------------------------------------------------
-[ RECORD 7 ]--+----------------------------------------------------------------------------------------
uri | http://admin:password@192.168.0.1
uri_normalize | http://admin:password@192.168.0.1
uri_scheme | http
@ -201,7 +145,7 @@ uri_path |
uri_path_array | {}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 12 ]-+----------------------------------------------------------------------------------------
-[ RECORD 8 ]--+----------------------------------------------------------------------------------------
uri | http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
uri_normalize | http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:80/index.html
uri_scheme | http
@ -213,7 +157,7 @@ uri_path | /index.html
uri_path_array | {index.html}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 13 ]-+----------------------------------------------------------------------------------------
-[ RECORD 9 ]--+----------------------------------------------------------------------------------------
uri | http://[1080::8:800:200C:417A]/foo
uri_normalize | http://[1080:0000:0000:0000:0008:0800:200c:417a]/foo
uri_scheme | http
@ -225,7 +169,7 @@ uri_path | /foo
uri_path_array | {foo}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 14 ]-+----------------------------------------------------------------------------------------
-[ RECORD 10 ]-+----------------------------------------------------------------------------------------
uri | http://host:
uri_normalize | http://host:
uri_scheme | http
@ -237,7 +181,7 @@ uri_path |
uri_path_array | {}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 15 ]-+----------------------------------------------------------------------------------------
-[ RECORD 11 ]-+----------------------------------------------------------------------------------------
uri |
uri_normalize |
uri_scheme | _null_
@ -249,7 +193,7 @@ uri_path |
uri_path_array | {}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 16 ]-+----------------------------------------------------------------------------------------
-[ RECORD 12 ]-+----------------------------------------------------------------------------------------
uri | /
uri_normalize | /
uri_scheme | _null_
@ -261,7 +205,7 @@ uri_path | /
uri_path_array | {}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 17 ]-+----------------------------------------------------------------------------------------
-[ RECORD 13 ]-+----------------------------------------------------------------------------------------
uri | foobar
uri_normalize | foobar
uri_scheme | _null_
@ -273,7 +217,7 @@ uri_path | foobar
uri_path_array | {foobar}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 18 ]-+----------------------------------------------------------------------------------------
-[ RECORD 14 ]-+----------------------------------------------------------------------------------------
uri | /foobar
uri_normalize | /foobar
uri_scheme | _null_
@ -285,7 +229,7 @@ uri_path | /foobar
uri_path_array | {foobar}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 19 ]-+----------------------------------------------------------------------------------------
-[ RECORD 15 ]-+----------------------------------------------------------------------------------------
uri | HTTP://www.EXAMPLE.com/
uri_normalize | http://www.example.com/
uri_scheme | HTTP
@ -297,7 +241,7 @@ uri_path | /
uri_path_array | {""}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 20 ]-+----------------------------------------------------------------------------------------
-[ RECORD 16 ]-+----------------------------------------------------------------------------------------
uri | http://www.ex%41mple.com/
uri_normalize | http://www.example.com/
uri_scheme | http
@ -309,7 +253,7 @@ uri_path | /
uri_path_array | {""}
uri_query | _null_
uri_fragment | _null_
-[ RECORD 21 ]-+----------------------------------------------------------------------------------------
-[ RECORD 17 ]-+----------------------------------------------------------------------------------------
uri | eXAMPLE://a/./b/../b/%63/%7bfoo%7d
uri_normalize | example://a/b/c/%7Bfoo%7D
uri_scheme | eXAMPLE
@ -329,34 +273,19 @@ SELECT DISTINCT b FROM test ORDER BY b;
/
/foobar
foobar
HTTP://www.EXAMPLE.com/
eXAMPLE://a/./b/../b/%63/%7bfoo%7d
foobar
ftp://ftp.gnu.org/gnu/bison
http://admin:password@192.168.0.1
http://[1080::8:800:200C:417A]/foo
http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
http://admin:password@192.168.0.1
http://host:
http://www.ex%41mple.com/
HTTP://www.EXAMPLE.com/
http://www.postgresql.org/
http://www.postgresql.org/docs/devel/static/xfunc-sql.html#XFUNC-SQL-FUNCTION-ARGUMENTS
http://www.postgresql.org:80/
http://www.postgresql.org:591/
https://duckduckgo.com/?q=postgresql&ia=about
mailto:foo@example.com
ssh://review.openstack.org:29418/openstack/nova.git
ssh://foobar@review.openstack.org:29418/openstack/nova.git
ssh://username@review.openstack.org:29418/openstack/nova.git
(21 rows)
CREATE TABLE test2 (x text, y uri);
INSERT INTO test2 VALUES ('foo', 'http://www.postgresql.org/');
-- check hashing (issue petere/pguri#3)
SET enable_nestloop = off;
SET enable_mergejoin = off;
SELECT * FROM test JOIN test2 ON b = y AND a = 1;
a | b | x | y
---+----------------------------+-----+----------------------------
1 | http://www.postgresql.org/ | foo | http://www.postgresql.org/
(1 row)
(17 rows)

View File

@ -1,21 +0,0 @@
SELECT uri_escape('foobar');
SELECT uri_escape(':/?#[]@!$&''()*+,;=');
SELECT uri_escape('foo bar');
SELECT uri_escape('foo bar', space_to_plus := false);
SELECT uri_escape('foo bar', space_to_plus := true);
SELECT uri_escape(E'foo\nbar');
SELECT uri_escape(E'foo\nbar', normalize_breaks := false);
SELECT uri_escape(E'foo\nbar', normalize_breaks := true);
SELECT uri_unescape('foobar');
SELECT uri_unescape('%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D');
SELECT uri_unescape('foo+bar');
SELECT uri_unescape('foo+bar', plus_to_space := false);
SELECT uri_unescape('foo+bar', plus_to_space := true);
SELECT uri_unescape('foo%0D%0Abar');
SELECT uri_unescape('foo%0D%0Abar', break_conversion := false);
SELECT uri_unescape('foo%0D%0Abar', break_conversion := true);

View File

@ -7,14 +7,10 @@ CREATE TABLE test (a serial, b uri);
INSERT INTO test (b)
VALUES ('http://www.postgresql.org/'),
('http://www.postgresql.org/docs/devel/static/xfunc-sql.html#XFUNC-SQL-FUNCTION-ARGUMENTS'),
('http://www.postgresql.org:591/'),
('http://www.postgresql.org:80/'),
('https://duckduckgo.com/?q=postgresql&ia=about'),
('ftp://ftp.gnu.org/gnu/bison'),
('mailto:foo@example.com'),
('ssh://username@review.openstack.org:29418/openstack/nova.git'),
('ssh://foobar@review.openstack.org:29418/openstack/nova.git'),
('ssh://review.openstack.org:29418/openstack/nova.git'),
('http://admin:password@192.168.0.1'),
('http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html'),
('http://[1080::8:800:200C:417A]/foo'),
@ -52,12 +48,3 @@ SELECT b AS uri,
\x off
SELECT DISTINCT b FROM test ORDER BY b;
CREATE TABLE test2 (x text, y uri);
INSERT INTO test2 VALUES ('foo', 'http://www.postgresql.org/');
-- check hashing (issue petere/pguri#3)
SET enable_nestloop = off;
SET enable_mergejoin = off;
SELECT * FROM test JOIN test2 ON b = y AND a = 1;

View File

@ -1,22 +0,0 @@
CREATE FUNCTION uri_hash(uri) RETURNS integer
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE OPERATOR CLASS uri_ops_hash
DEFAULT FOR TYPE uri USING hash AS
OPERATOR 1 =,
FUNCTION 1 uri_hash(uri);
CREATE FUNCTION uri_escape(text, space_to_plus boolean DEFAULT false, normalize_breaks boolean DEFAULT false) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_unescape(text, plus_to_space boolean DEFAULT false, break_conversion boolean DEFAULT false) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';

View File

@ -1,225 +0,0 @@
SET client_min_messages = warning;
CREATE TYPE uri;
CREATE FUNCTION uri_in(cstring) RETURNS uri
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_out(uri) RETURNS cstring
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE TYPE uri (
INTERNALLENGTH = -1,
INPUT = uri_in,
OUTPUT = uri_out
);
CREATE CAST (uri AS text) WITH INOUT AS ASSIGNMENT;
CREATE CAST (text AS uri) WITH INOUT AS ASSIGNMENT;
CREATE FUNCTION uri_scheme(uri) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_userinfo(uri) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_host(uri) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_host_inet(uri) RETURNS inet
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_port(uri) RETURNS integer
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_query(uri) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_fragment(uri) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_path(uri) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_path_array(uri) RETURNS text[]
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_normalize(uri) RETURNS uri
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_lt(uri, uri) RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_le(uri, uri) RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_eq(uri, uri) RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_ne(uri, uri) RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_ge(uri, uri) RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_gt(uri, uri) RETURNS boolean
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_cmp(uri, uri) RETURNS integer
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_hash(uri) RETURNS integer
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE OPERATOR < (
LEFTARG = uri,
RIGHTARG = uri,
COMMUTATOR = >,
NEGATOR = >=,
RESTRICT = scalarltsel,
JOIN = scalarltjoinsel,
PROCEDURE = uri_lt
);
CREATE OPERATOR <= (
LEFTARG = uri,
RIGHTARG = uri,
COMMUTATOR = >=,
NEGATOR = >,
RESTRICT = scalarltsel,
JOIN = scalarltjoinsel,
PROCEDURE = uri_le
);
CREATE OPERATOR = (
LEFTARG = uri,
RIGHTARG = uri,
COMMUTATOR = =,
NEGATOR = <>,
RESTRICT = eqsel,
JOIN = eqjoinsel,
HASHES,
MERGES,
PROCEDURE = uri_eq
);
CREATE OPERATOR <> (
LEFTARG = uri,
RIGHTARG = uri,
COMMUTATOR = <>,
NEGATOR = =,
RESTRICT = neqsel,
JOIN = neqjoinsel,
PROCEDURE = uri_ne
);
CREATE OPERATOR >= (
LEFTARG = uri,
RIGHTARG = uri,
COMMUTATOR = <=,
NEGATOR = <,
RESTRICT = scalargtsel,
JOIN = scalargtjoinsel,
PROCEDURE = uri_ge
);
CREATE OPERATOR > (
LEFTARG = uri,
RIGHTARG = uri,
COMMUTATOR = <,
NEGATOR = <=,
RESTRICT = scalargtsel,
JOIN = scalargtjoinsel,
PROCEDURE = uri_gt
);
CREATE OPERATOR CLASS uri_ops
DEFAULT FOR TYPE uri USING btree AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
OPERATOR 3 = ,
OPERATOR 4 >= ,
OPERATOR 5 > ,
FUNCTION 1 uri_cmp(uri, uri);
CREATE OPERATOR CLASS uri_ops_hash
DEFAULT FOR TYPE uri USING hash AS
OPERATOR 1 =,
FUNCTION 1 uri_hash(uri);
CREATE FUNCTION uri_escape(text, space_to_plus boolean DEFAULT false, normalize_breaks boolean DEFAULT false) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';
CREATE FUNCTION uri_unescape(text, plus_to_space boolean DEFAULT false, break_conversion boolean DEFAULT false) RETURNS text
IMMUTABLE
STRICT
LANGUAGE C
AS '$libdir/uri';

194
uri.c
View File

@ -1,5 +1,4 @@
#include <postgres.h>
#include <access/hash.h>
#include <catalog/pg_type.h>
#include <fmgr.h>
#include <lib/stringinfo.h>
@ -17,11 +16,9 @@ typedef struct varlena uritype;
#define DatumGetUriP(X) ((uritype *) PG_DETOAST_DATUM(X))
#define DatumGetUriPP(X) ((uritype *) PG_DETOAST_DATUM_PACKED(X))
#define UriPGetDatum(X) PointerGetDatum(X)
#define PG_GETARG_URI_P(n) DatumGetUriP(PG_GETARG_DATUM(n))
#define PG_GETARG_URI_PP(n) DatumGetUriPP(PG_GETARG_DATUM(n))
#define PG_RETURN_URI_P(x) PG_RETURN_POINTER(x)
@ -42,7 +39,6 @@ parse_uri(const char *s, UriUriA *urip)
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type uri at or near \"%s\"",
state.errorPos)));
break;
default:
elog(ERROR, "liburiparser error code %d", state.errorCode);
}
@ -171,16 +167,6 @@ uri_host_inet(PG_FUNCTION_ARGS)
}
}
static int
_uri_port_num(UriUriA *urip)
{
if (!urip->portText.first || !urip->portText.afterLast
|| urip->portText.afterLast == urip->portText.first)
return -1;
return strtol(pnstrdup(urip->portText.first, urip->portText.afterLast - urip->portText.first),
NULL, 10);
}
PG_FUNCTION_INFO_V1(uri_port);
Datum
uri_port(PG_FUNCTION_ARGS)
@ -188,14 +174,15 @@ uri_port(PG_FUNCTION_ARGS)
Datum arg = PG_GETARG_DATUM(0);
char *s = TextDatumGetCString(arg);
UriUriA uri;
int num;
const char *p;
parse_uri(s, &uri);
num = _uri_port_num(&uri);
uriFreeUriMembersA(&uri);
if (num < 0)
if (!uri.portText.first || !uri.portText.afterLast
|| uri.portText.afterLast == uri.portText.first)
PG_RETURN_NULL();
PG_RETURN_INT32(num);
p = pnstrdup(uri.portText.first, uri.portText.afterLast - uri.portText.first);
uriFreeUriMembersA(&uri);
PG_RETURN_INT32(strtol(p, NULL, 10));
}
PG_FUNCTION_INFO_V1(uri_query);
@ -234,21 +221,6 @@ uri_fragment(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
/*
* Defined in uriparser library, but not exported, so we keep a local version
* here.
*/
static bool
_is_host_set(UriUriA *uri)
{
return (uri != NULL)
&& ((uri->hostText.first != NULL)
|| (uri->hostData.ip4 != NULL)
|| (uri->hostData.ip6 != NULL)
|| (uri->hostData.ipFuture.first != NULL)
);
}
PG_FUNCTION_INFO_V1(uri_path);
Datum
uri_path(PG_FUNCTION_ARGS)
@ -263,7 +235,7 @@ uri_path(PG_FUNCTION_ARGS)
parse_uri(s, &uri);
if (uri.absolutePath || (_is_host_set(&uri) && uri.pathHead))
if (uri.absolutePath || (uriIsHostSetA(&uri) && uri.pathHead))
appendStringInfoChar(&buf, '/');
for (p = uri.pathHead; p; p = p->next)
@ -334,56 +306,6 @@ uri_normalize(PG_FUNCTION_ARGS)
PG_RETURN_URI_P((uritype *) cstring_to_text(ret));
}
static int
strcasecmp_ascii(const char *s1, const char *s2)
{
for (;;)
{
unsigned char ch1 = (unsigned char) *s1++;
unsigned char ch2 = (unsigned char) *s2++;
if (ch1 != ch2)
{
if (ch1 >= 'A' && ch1 <= 'Z')
ch1 += 'a' - 'A';
if (ch2 >= 'A' && ch2 <= 'Z')
ch2 += 'a' - 'A';
if (ch1 != ch2)
return (int) ch1 - (int) ch2;
}
if (ch1 == 0)
break;
}
return 0;
}
static int
strncasecmp_ascii(const char *s1, const char *s2, size_t n)
{
while (n-- > 0)
{
unsigned char ch1 = (unsigned char) *s1++;
unsigned char ch2 = (unsigned char) *s2++;
if (ch1 != ch2)
{
if (ch1 >= 'A' && ch1 <= 'Z')
ch1 += 'a' - 'A';
if (ch2 >= 'A' && ch2 <= 'Z')
ch2 += 'a' - 'A';
if (ch1 != ch2)
return (int) ch1 - (int) ch2;
}
if (ch1 == 0)
break;
}
return 0;
}
static int
cmp_text_range(UriTextRangeA a, UriTextRangeA b)
{
@ -398,7 +320,7 @@ cmp_text_range(UriTextRangeA a, UriTextRangeA b)
return 1;
else
{
int x = strncasecmp_ascii(a.first, b.first,
int x = strncmp(a.first, b.first,
Min(a.afterLast - a.first, b.afterLast - b.first));
if (x == 0)
return (a.afterLast - a.first) - (b.afterLast - b.first);
@ -406,44 +328,6 @@ cmp_text_range(UriTextRangeA a, UriTextRangeA b)
}
}
static int
cmp_hosts(UriUriA *uap, UriUriA *ubp)
{
if (!uap->hostText.first)
{
if (!ubp->hostText.first)
return 0;
else
return -1;
}
else if (uap->hostData.ip4)
{
if (!ubp->hostText.first)
return 1;
else if (ubp->hostData.ip4)
return memcmp(uap->hostData.ip4->data,
ubp->hostData.ip4->data,
sizeof(uap->hostData.ip4->data));
else
return -1;
}
else if (uap->hostData.ip6)
{
if (!ubp->hostText.first)
return 1;
else if (ubp->hostData.ip4)
return 1;
else if (ubp->hostData.ip6)
return memcmp(uap->hostData.ip6->data,
ubp->hostData.ip6->data,
sizeof(uap->hostData.ip6->data));
else
return -1;
}
else
return cmp_text_range(uap->hostText, ubp->hostText);
}
static int
_uri_cmp(Datum a, Datum b)
{
@ -454,18 +338,12 @@ _uri_cmp(Datum a, Datum b)
int res = 0;
parse_uri(sa, &ua);
parse_uri(sb, &ub);
parse_uri(sa, &ub);
if (res == 0)
res = cmp_text_range(ua.scheme, ub.scheme);
if (res == 0)
res = cmp_hosts(&ua, &ub);
if (res == 0)
res = _uri_port_num(&ua) - _uri_port_num(&ub);
if (res == 0)
res = cmp_text_range(ua.userInfo, ub.userInfo);
if (res == 0)
res = strcasecmp_ascii(sa, sb);
res = cmp_text_range(ua.hostText, ub.hostText);
if (res == 0)
res = strcmp(sa, sb);
uriFreeUriMembersA(&ua);
@ -543,55 +421,3 @@ uri_cmp(PG_FUNCTION_ARGS)
PG_RETURN_INT32(_uri_cmp(arg1, arg2));
}
PG_FUNCTION_INFO_V1(uri_hash);
Datum
uri_hash(PG_FUNCTION_ARGS)
{
uritype *key = PG_GETARG_URI_PP(0);
Datum result;
result = hash_any((unsigned char *) VARDATA_ANY(key),
VARSIZE_ANY_EXHDR(key));
/* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0);
return result;
}
PG_FUNCTION_INFO_V1(uri_escape);
Datum
uri_escape(PG_FUNCTION_ARGS)
{
text *arg = PG_GETARG_TEXT_PP(0);
bool space_to_plus = PG_GETARG_BOOL(1);
bool normalize_breaks = PG_GETARG_BOOL(2);
size_t chars_required;
char *ret;
chars_required = (VARSIZE(arg) - 4) * (normalize_breaks ? 6 : 3) + 1;
ret = palloc(chars_required);
uriEscapeExA(VARDATA(arg),
VARDATA(arg) + VARSIZE(arg) - 4,
ret,
space_to_plus, normalize_breaks);
PG_RETURN_TEXT_P(cstring_to_text(ret));
}
PG_FUNCTION_INFO_V1(uri_unescape);
Datum
uri_unescape(PG_FUNCTION_ARGS)
{
text *arg = PG_GETARG_TEXT_PP(0);
bool plus_to_space = PG_GETARG_BOOL(1);
bool break_conversion = PG_GETARG_BOOL(2);
char *s = text_to_cstring(arg);
uriUnescapeInPlaceExA(s, plus_to_space, break_conversion);
PG_RETURN_TEXT_P(cstring_to_text(s));
}

View File

@ -1,4 +1,4 @@
comment = 'uri type'
default_version = 1
default_version = 0
module_pathname = '$libdir/uri'
relocatable = true

View File