From 59acd3726c07e1b5e569ac76129607c8a1d84b95 Mon Sep 17 00:00:00 2001 From: Emre Hasegeli Date: Thu, 18 Aug 2016 12:23:48 +0200 Subject: [PATCH] citext-regexp-match-v1 --- contrib/citext/Makefile | 4 +- contrib/citext/citext--1.3--1.4.sql | 12 +++++ .../citext/{citext--1.3.sql => citext--1.4.sql} | 10 +++- contrib/citext/citext.control | 2 +- contrib/citext/expected/citext.out | 54 ++++++++++++++++++++++ contrib/citext/sql/citext.sql | 12 +++++ doc/src/sgml/citext.sgml | 5 ++ 7 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 contrib/citext/citext--1.3--1.4.sql rename contrib/citext/{citext--1.3.sql => citext--1.4.sql} (96%) diff --git a/contrib/citext/Makefile b/contrib/citext/Makefile index e39d3ee..5df7531 100644 --- a/contrib/citext/Makefile +++ b/contrib/citext/Makefile @@ -1,17 +1,17 @@ # contrib/citext/Makefile MODULES = citext EXTENSION = citext -DATA = citext--1.3.sql citext--1.2--1.3.sql citext--1.1--1.2.sql \ - citext--1.0--1.1.sql citext--unpackaged--1.0.sql +DATA = citext--1.4.sql citext--1.3--1.4.sql citext--1.2--1.3.sql \ + citext--1.1--1.2.sql citext--1.0--1.1.sql citext--unpackaged--1.0.sql PGFILEDESC = "citext - case-insensitive character string data type" REGRESS = citext ifdef USE_PGXS PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) else subdir = contrib/citext diff --git a/contrib/citext/citext--1.3--1.4.sql b/contrib/citext/citext--1.3--1.4.sql new file mode 100644 index 0000000..7b36651 --- /dev/null +++ b/contrib/citext/citext--1.3--1.4.sql @@ -0,0 +1,12 @@ +/* contrib/citext/citext--1.3--1.4.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION citext UPDATE TO '1.4'" to load this file. \quit + +CREATE FUNCTION regexp_match( citext, citext ) RETURNS TEXT[] AS $$ + SELECT pg_catalog.regexp_match( $1::pg_catalog.text, $2::pg_catalog.text, 'i' ); +$$ LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION regexp_match( citext, citext, text ) RETURNS TEXT[] AS $$ + SELECT pg_catalog.regexp_match( $1::pg_catalog.text, $2::pg_catalog.text, CASE WHEN pg_catalog.strpos($3, 'c') = 0 THEN $3 || 'i' ELSE $3 END ); +$$ LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE; diff --git a/contrib/citext/citext--1.3.sql b/contrib/citext/citext--1.4.sql similarity index 96% rename from contrib/citext/citext--1.3.sql rename to contrib/citext/citext--1.4.sql index c2d0c0c..7b06198 100644 --- a/contrib/citext/citext--1.3.sql +++ b/contrib/citext/citext--1.4.sql @@ -1,11 +1,11 @@ -/* contrib/citext/citext--1.2.sql */ +/* contrib/citext/citext--1.4.sql */ -- complain if script is sourced in psql, rather than via CREATE EXTENSION \echo Use "CREATE EXTENSION citext" to load this file. \quit -- -- PostgreSQL code for CITEXT. -- -- Most I/O functions, and a few others, piggyback on the "text" type -- functions via the implicit cast to text. -- @@ -437,20 +437,28 @@ CREATE OPERATOR !~~* ( NEGATOR = ~~*, RESTRICT = icnlikesel, JOIN = icnlikejoinsel ); -- -- Matching citext in string comparison functions. -- XXX TODO Ideally these would be implemented in C. -- +CREATE FUNCTION regexp_match( citext, citext ) RETURNS TEXT[] AS $$ + SELECT pg_catalog.regexp_match( $1::pg_catalog.text, $2::pg_catalog.text, 'i' ); +$$ LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION regexp_match( citext, citext, text ) RETURNS TEXT[] AS $$ + SELECT pg_catalog.regexp_match( $1::pg_catalog.text, $2::pg_catalog.text, CASE WHEN pg_catalog.strpos($3, 'c') = 0 THEN $3 || 'i' ELSE $3 END ); +$$ LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE; + CREATE FUNCTION regexp_matches( citext, citext ) RETURNS SETOF TEXT[] AS $$ SELECT pg_catalog.regexp_matches( $1::pg_catalog.text, $2::pg_catalog.text, 'i' ); $$ LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE ROWS 1; CREATE FUNCTION regexp_matches( citext, citext, text ) RETURNS SETOF TEXT[] AS $$ SELECT pg_catalog.regexp_matches( $1::pg_catalog.text, $2::pg_catalog.text, CASE WHEN pg_catalog.strpos($3, 'c') = 0 THEN $3 || 'i' ELSE $3 END ); $$ LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE ROWS 10; CREATE FUNCTION regexp_replace( citext, citext, text ) returns TEXT AS $$ SELECT pg_catalog.regexp_replace( $1::pg_catalog.text, $2::pg_catalog.text, $3, 'i'); diff --git a/contrib/citext/citext.control b/contrib/citext/citext.control index 5f080df..17fce4e 100644 --- a/contrib/citext/citext.control +++ b/contrib/citext/citext.control @@ -1,5 +1,5 @@ # citext extension comment = 'data type for case-insensitive character strings' -default_version = '1.3' +default_version = '1.4' module_pathname = '$libdir/citext' relocatable = true diff --git a/contrib/citext/expected/citext.out b/contrib/citext/expected/citext.out index 6541b24..1a1e6c8 100644 --- a/contrib/citext/expected/citext.out +++ b/contrib/citext/expected/citext.out @@ -1763,20 +1763,74 @@ SELECT quote_ident( name ) = quote_ident( name::text ) AS t FROM srt; SELECT quote_literal( name ) = quote_literal( name::text ) AS t FROM srt; t --- t t t t (4 rows) +SELECT regexp_match('foobarbequebaz'::citext, '(bar)(beque)') = ARRAY[ 'bar', 'beque' ] AS t; + t +--- + t +(1 row) + +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)') = ARRAY[ 'bar', 'beque' ] AS t; + t +--- + t +(1 row) + +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext) = ARRAY[ 'bar', 'beque' ] AS t; + t +--- + t +(1 row) + +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, '') = ARRAY[ 'bar', 'beque' ] AS t; + t +--- + t +(1 row) + +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)', '') = ARRAY[ 'bar', 'beque' ] AS t; + t +--- + t +(1 row) + +SELECT regexp_match('foobarbequebaz', '(BAR)(BEQUE)'::citext, '') = ARRAY[ 'bar', 'beque' ] AS t; + t +--- + t +(1 row) + +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, ''::citext) = ARRAY[ 'bar', 'beque' ] AS t; + t +--- + t +(1 row) + +-- c forces case-sensitive +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, 'c'::citext) = ARRAY[ 'bar', 'beque' ] AS "no result"; + no result +----------- + +(1 row) + +-- g is not allowed +SELECT regexp_match('foobarbequebazmorebarbequetoo'::citext, '(BAR)(BEQUE)'::citext, 'g') AS "error"; +ERROR: regexp_match does not support the global option +HINT: Use the regexp_matches function instead. +CONTEXT: SQL function "regexp_match" statement 1 SELECT regexp_matches('foobarbequebaz'::citext, '(bar)(beque)') = ARRAY[ 'bar', 'beque' ] AS t; t --- t (1 row) SELECT regexp_matches('foobarbequebaz'::citext, '(BAR)(BEQUE)') = ARRAY[ 'bar', 'beque' ] AS t; t --- t diff --git a/contrib/citext/sql/citext.sql b/contrib/citext/sql/citext.sql index 2df1b4a..a802484 100644 --- a/contrib/citext/sql/citext.sql +++ b/contrib/citext/sql/citext.sql @@ -585,20 +585,32 @@ SELECT lpad('hi'::citext, 5, 'xy'::text ) = 'xyxhi' AS t; SELECT ltrim(' trim'::citext ) = 'trim' AS t; SELECT ltrim('zzzytrim'::citext, 'xyz'::citext) = 'trim' AS t; SELECT ltrim('zzzytrim'::text, 'xyz'::citext) = 'trim' AS t; SELECT ltrim('zzzytrim'::citext, 'xyz'::text ) = 'trim' AS t; SELECT md5( name ) = md5( name::text ) AS t FROM srt; -- pg_client_encoding() takes no args and returns name. SELECT quote_ident( name ) = quote_ident( name::text ) AS t FROM srt; SELECT quote_literal( name ) = quote_literal( name::text ) AS t FROM srt; +SELECT regexp_match('foobarbequebaz'::citext, '(bar)(beque)') = ARRAY[ 'bar', 'beque' ] AS t; +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)') = ARRAY[ 'bar', 'beque' ] AS t; +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext) = ARRAY[ 'bar', 'beque' ] AS t; +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, '') = ARRAY[ 'bar', 'beque' ] AS t; +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)', '') = ARRAY[ 'bar', 'beque' ] AS t; +SELECT regexp_match('foobarbequebaz', '(BAR)(BEQUE)'::citext, '') = ARRAY[ 'bar', 'beque' ] AS t; +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, ''::citext) = ARRAY[ 'bar', 'beque' ] AS t; +-- c forces case-sensitive +SELECT regexp_match('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, 'c'::citext) = ARRAY[ 'bar', 'beque' ] AS "no result"; +-- g is not allowed +SELECT regexp_match('foobarbequebazmorebarbequetoo'::citext, '(BAR)(BEQUE)'::citext, 'g') AS "error"; + SELECT regexp_matches('foobarbequebaz'::citext, '(bar)(beque)') = ARRAY[ 'bar', 'beque' ] AS t; SELECT regexp_matches('foobarbequebaz'::citext, '(BAR)(BEQUE)') = ARRAY[ 'bar', 'beque' ] AS t; SELECT regexp_matches('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext) = ARRAY[ 'bar', 'beque' ] AS t; SELECT regexp_matches('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, '') = ARRAY[ 'bar', 'beque' ] AS t; SELECT regexp_matches('foobarbequebaz'::citext, '(BAR)(BEQUE)', '') = ARRAY[ 'bar', 'beque' ] AS t; SELECT regexp_matches('foobarbequebaz', '(BAR)(BEQUE)'::citext, '') = ARRAY[ 'bar', 'beque' ] AS t; SELECT regexp_matches('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, ''::citext) = ARRAY[ 'bar', 'beque' ] AS t; -- c forces case-sensitive SELECT regexp_matches('foobarbequebaz'::citext, '(BAR)(BEQUE)'::citext, 'c'::citext) = ARRAY[ 'bar', 'beque' ] AS "no rows"; -- g allows multiple output rows diff --git a/doc/src/sgml/citext.sgml b/doc/src/sgml/citext.sgml index 7fdf302..9b4c68f 100644 --- a/doc/src/sgml/citext.sgml +++ b/doc/src/sgml/citext.sgml @@ -119,20 +119,25 @@ SELECT * FROM users WHERE nick = 'Larry'; Similarly, all of the following functions perform matching case-insensitively if their arguments are citext: + regexp_match() + + + + regexp_matches() regexp_replace() -- 2.7.4 (Apple Git-66)