pax_global_header00006660000000000000000000000064134601312460014512gustar00rootroot0000000000000052 comment=0665ece3e27f36d8d800741a9871250ac54e9660 pgpcre-0.20190509/000077500000000000000000000000001346013124600134035ustar00rootroot00000000000000pgpcre-0.20190509/.gitignore000066400000000000000000000000231346013124600153660ustar00rootroot00000000000000*.o *.so /results/ pgpcre-0.20190509/.travis.yml000066400000000000000000000012741346013124600155200ustar00rootroot00000000000000dist: xenial language: c addons: apt: sources: - sourceline: 'deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main' key_url: 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' update: true packages: - libpcre3-dev env: - PGVERSION=9.1 - PGVERSION=9.2 - PGVERSION=9.3 - PGVERSION=9.4 - PGVERSION=9.5 - PGVERSION=9.6 - PGVERSION=10 - PGVERSION=11 script: | set -e PATH=/usr/lib/postgresql/$PGVERSION/bin:$PATH sudo apt-get install postgresql-$PGVERSION postgresql-server-dev-$PGVERSION sudo pg_createcluster --start $PGVERSION test -p 55435 -- -A trust make all sudo make install PGPORT=55435 make installcheck PGUSER=postgres pgpcre-0.20190509/LICENSE000066400000000000000000000020571346013124600144140ustar00rootroot00000000000000pgpcre Copyright © 2013, Peter Eisentraut (The PostgreSQL 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 AUTHOR(S) OR ANY CONTRIBUTOR(S) 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 AUTHOR(S) OR CONTRIBUTOR(S) HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHOR(S) AND CONTRIBUTOR(S) 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 AUTHOR(S) AND CONTRIBUTOR(S) HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. pgpcre-0.20190509/Makefile000066400000000000000000000007741346013124600150530ustar00rootroot00000000000000PG_CONFIG = pg_config PKG_CONFIG = pkg-config EXTENSION = pgpcre MODULE_big = pgpcre OBJS = pgpcre.o DATA = pgpcre--0.sql pgpcre--1.sql pgpcre--0--1.sql ifeq (no,$(shell $(PKG_CONFIG) libpcre || echo no)) $(warning libpcre not registed with pkg-config, build might fail) endif PG_CPPFLAGS += $(shell $(PKG_CONFIG) --cflags-only-I libpcre) SHLIB_LINK += $(shell $(PKG_CONFIG) --libs libpcre) REGRESS = init test unicode REGRESS_OPTS = --inputdir=test PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) pgpcre-0.20190509/README.md000066400000000000000000000106021346013124600146610ustar00rootroot00000000000000# pgpcre [![Build Status](https://secure.travis-ci.org/petere/pgpcre.png)](http://travis-ci.org/petere/pgpcre) This is a module for PostgreSQL that exposes Perl-compatible regular expressions (PCRE) functionality as functions and operators. It is based on the popular [PCRE library](http://www.pcre.org/). ## Installation You need to have libpcre installed. pkg-config will be used to find it. To build and install this module: make make install or selecting a specific PostgreSQL installation: make PG_CONFIG=/some/where/bin/pg_config make PG_CONFIG=/some/where/bin/pg_config install And finally inside the database: CREATE EXTENSION pgpcre; ## Using A regular expression is a separate data type, named `pcre`. (This is different from how the built-in regular expressions in PostgreSQL work, which are simply values of type `text`.) The supported regular expressions are documented on the [pcrepattern(3)](http://linux.die.net/man/3/pcrepattern) man page. ### Basic matching Boolean operators are available for checking whether a pattern matches a string. These operators return true or false, respectively. They only return null when one of the operands is null. Examples: SELECT 'foo' ~ pcre 'fo+'; SELECT 'bar' !~ pcre 'fo+'; You can also write it the other way around: SELECT pcre 'fo+' ~ 'foo'; SELECT pcre 'fo+' !~ 'bar'; This can be handy for writing things like SELECT pcre 'fo+' ~ ANY(ARRAY['foo', 'bar']); For Perl nostalgia, you can also use this operator: SELECT 'foo' =~ pcre 'fo+'; And if this operator is unique (which it should be, unless you have something else installed that uses it), you can also write: SELECT 'foo' =~ 'fo+'; (The `~` operator, by contrast, is not unique, of course, because it is used by the built-in regular expressions.) To get case-insensitive matching, set the appropriate option in the pattern, for example: SELECT 'FOO' ~ pcre '(?i)fo+'; ### Extracting the matched string To extract the substring that was matched by the pattern, use the function `pcre_match`. It returns either a value of type text, or null if the pattern did not match. Examples: SELECT pcre_match('fo+', 'foobar'); --> 'foo' SELECT pcre_match('fo+', 'barbar'); --> NULL There is no support for extracting multiple matches of a pattern in a string, because PCRE does not (easily) support that. ### Extracting captured substrings Captured substrings (parenthesized subexpressions) are extracted using the function `pcre_captured_substrings`. It returns either an array of text, or null if the pattern did not match. Examples: SELECT pcre_captured_substrings('(fo+)(b..)', 'foobar'); --> ARRAY['foo','bar'] SELECT pcre_captured_substrings('(fo+)(b..)', 'abcdef'); --> NULL Note that elements of the array can be null if a substring was not used, for example: SELECT pcre_captured_substrings('(a|(z))(bc)', 'abc'); --> ARRAY['a',NULL,'bc'] ### Storing regular expressions You can store regular expression values of type `pcre` in tables, like any other data. Note, however, that the binary representation of the `pcre` values contains the compiled regular expression, which is tied to the version of the PCRE library. If you upgrade the PCRE library and use a compiled value created by a different version, things might not work or even crash (according to the PCRE documentation; I don't know how likely that is). pgpcre will warn if you attempt to use a value that was compiled by a different version of the library. If that happens, it is advisable to recompile and rewrite all stored `pcre` values by doing something like UPDATE ... SET pcre_col = pcre_col::text::pcre (To be clear, storing regular expressions in tables is not a typical use. Normally, you store text in tables and match it against regular expressions provided by your application.) ## Discussion Some possible advantages over the regular expression support built into PostgreSQL: - richer pattern language, more familiar to Perl and Python programmers - complete Unicode support - saner operators and functions Some disadvantages: - no repeated matching (`'g'` flag) - no index optimization You can workaround the lack of index optimization by manually augmenting queries like column =~ '^foo' with AND column ~>=~ 'foo' AND column ~<~ 'fop' and creating the appropriate `text_pattern_ops` index as you would for the built-in pattern matching. pgpcre-0.20190509/pgpcre--0--1.sql000066400000000000000000000001241346013124600160260ustar00rootroot00000000000000ALTER FUNCTION pcre_in(cstring) IMMUTABLE; ALTER FUNCTION pcre_out(pcre) IMMUTABLE; pgpcre-0.20190509/pgpcre--0.sql000066400000000000000000000034271346013124600156240ustar00rootroot00000000000000SET client_min_messages = warning; CREATE TYPE pcre; CREATE FUNCTION pcre_in(cstring) RETURNS pcre AS '$libdir/pgpcre' LANGUAGE C STRICT; CREATE FUNCTION pcre_out(pcre) RETURNS cstring AS '$libdir/pgpcre' LANGUAGE C STRICT; CREATE TYPE pcre ( INTERNALLENGTH = -1, INPUT = pcre_in, OUTPUT = pcre_out, STORAGE = extended ); CREATE FUNCTION pcre_text_matches(subject text, pattern pcre) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_matches_text(pattern pcre, subject text) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_text_matches_not(subject text, pattern pcre) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_matches_text_not(pattern pcre, subject text) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE OPERATOR =~ ( PROCEDURE = pcre_text_matches, LEFTARG = text, RIGHTARG = pcre ); CREATE OPERATOR ~ ( PROCEDURE = pcre_text_matches, LEFTARG = text, RIGHTARG = pcre ); CREATE OPERATOR ~ ( PROCEDURE = pcre_matches_text, LEFTARG = pcre, RIGHTARG = text, COMMUTATOR = ~ ); CREATE OPERATOR !~ ( PROCEDURE = pcre_text_matches_not, LEFTARG = text, RIGHTARG = pcre, NEGATOR = ~ ); CREATE OPERATOR !~ ( PROCEDURE = pcre_matches_text_not, LEFTARG = pcre, RIGHTARG = text, COMMUTATOR = !~, NEGATOR = ~ ); CREATE FUNCTION pcre_match(pattern pcre, subject text) RETURNS text IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_captured_substrings(pattern pcre, subject text) RETURNS text[] IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; pgpcre-0.20190509/pgpcre--1.sql000066400000000000000000000035231346013124600156220ustar00rootroot00000000000000SET client_min_messages = warning; CREATE TYPE pcre; CREATE FUNCTION pcre_in(cstring) RETURNS pcre IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_out(pcre) RETURNS cstring IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE TYPE pcre ( INTERNALLENGTH = -1, INPUT = pcre_in, OUTPUT = pcre_out, STORAGE = extended ); CREATE FUNCTION pcre_text_matches(subject text, pattern pcre) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_matches_text(pattern pcre, subject text) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_text_matches_not(subject text, pattern pcre) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_matches_text_not(pattern pcre, subject text) RETURNS boolean IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE OPERATOR =~ ( PROCEDURE = pcre_text_matches, LEFTARG = text, RIGHTARG = pcre ); CREATE OPERATOR ~ ( PROCEDURE = pcre_text_matches, LEFTARG = text, RIGHTARG = pcre ); CREATE OPERATOR ~ ( PROCEDURE = pcre_matches_text, LEFTARG = pcre, RIGHTARG = text, COMMUTATOR = ~ ); CREATE OPERATOR !~ ( PROCEDURE = pcre_text_matches_not, LEFTARG = text, RIGHTARG = pcre, NEGATOR = ~ ); CREATE OPERATOR !~ ( PROCEDURE = pcre_matches_text_not, LEFTARG = pcre, RIGHTARG = text, COMMUTATOR = !~, NEGATOR = ~ ); CREATE FUNCTION pcre_match(pattern pcre, subject text) RETURNS text IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; CREATE FUNCTION pcre_captured_substrings(pattern pcre, subject text) RETURNS text[] IMMUTABLE RETURNS NULL ON NULL INPUT AS '$libdir/pgpcre' LANGUAGE C; pgpcre-0.20190509/pgpcre.c000066400000000000000000000173201346013124600150320ustar00rootroot00000000000000#include #include #include #include #include #include #include PG_MODULE_MAGIC; Datum pcre_in(PG_FUNCTION_ARGS); Datum pcre_out(PG_FUNCTION_ARGS); Datum pcre_text_matches(PG_FUNCTION_ARGS); Datum pcre_matches_text(PG_FUNCTION_ARGS); Datum pcre_text_matches_not(PG_FUNCTION_ARGS); Datum pcre_matches_text_not(PG_FUNCTION_ARGS); Datum pcre_match(PG_FUNCTION_ARGS); Datum pcre_captured_substrings(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(pcre_in); PG_FUNCTION_INFO_V1(pcre_out); PG_FUNCTION_INFO_V1(pcre_text_matches); PG_FUNCTION_INFO_V1(pcre_matches_text); PG_FUNCTION_INFO_V1(pcre_text_matches_not); PG_FUNCTION_INFO_V1(pcre_matches_text_not); PG_FUNCTION_INFO_V1(pcre_match); PG_FUNCTION_INFO_V1(pcre_captured_substrings); void _PG_init(void); #ifndef FLEXIBLE_ARRAY_MEMBER #define FLEXIBLE_ARRAY_MEMBER 1 #endif typedef struct { int32 vl_len_; int16 pcre_major; /* new version might invalidate compiled pattern */ int16 pcre_minor; int32 pattern_strlen; /* used to compute offset to compiled pattern */ char data[FLEXIBLE_ARRAY_MEMBER]; /* original pattern string * (null-terminated), followed by * compiled pattern */ } pgpcre; #define DatumGetPcreP(X) ((pgpcre *) PG_DETOAST_DATUM(X)) #define DatumGetPcrePCopy(X) ((pgpcre *) PG_DETOAST_DATUM_COPY(X)) #define PcrePGetDatum(X) PointerGetDatum(X) #define PG_GETARG_PCRE_P(n) DatumGetPcreP(PG_GETARG_DATUM(n)) #define PG_GETARG_PCRE_P_COPY(n) DatumGetPcrePCopy(PG_GETARG_DATUM(n)) #define PG_RETURN_PCRE_P(x) return PcrePGetDatum(x) Datum pcre_in(PG_FUNCTION_ARGS) { char *input_string = PG_GETARG_CSTRING(0); pcre *pc; const char *err; int erroffset; size_t in_strlen; int rc, total_len, pcsize; pgpcre *result; in_strlen = strlen(input_string); if (GetDatabaseEncoding() == PG_UTF8) pc = pcre_compile(input_string, PCRE_UTF8 | PCRE_UCP, &err, &erroffset, NULL); else if (GetDatabaseEncoding() == PG_SQL_ASCII) pc = pcre_compile(input_string, 0, &err, &erroffset, NULL); else { char *utf8string; utf8string = (char *) pg_do_encoding_conversion((unsigned char *) input_string, in_strlen, GetDatabaseEncoding(), PG_UTF8); pc = pcre_compile(utf8string, PCRE_UTF8 | PCRE_UCP, &err, &erroffset, NULL); if (utf8string != input_string) pfree(utf8string); } if (!pc) elog(ERROR, "PCRE compile error: %s", err); rc = pcre_fullinfo(pc, NULL, PCRE_INFO_SIZE, &pcsize); if (rc < 0) elog(ERROR, "pcre_fullinfo/PCRE_INFO_SIZE: %d", rc); total_len = offsetof(pgpcre, data) + in_strlen + 1 + pcsize; result = (pgpcre *) palloc0(total_len); SET_VARSIZE(result, total_len); result->pcre_major = PCRE_MAJOR; result->pcre_minor = PCRE_MINOR; result->pattern_strlen = in_strlen; strcpy(result->data, input_string); memcpy(result->data + in_strlen + 1, pc, pcsize); PG_RETURN_PCRE_P(result); } Datum pcre_out(PG_FUNCTION_ARGS) { pgpcre *p = PG_GETARG_PCRE_P(0); PG_RETURN_CSTRING(pstrdup(p->data)); } static bool matches_internal(text *subject, pgpcre *pattern, char ***return_matches, int *num_captured) { pcre *pc; int rc; int num_substrings = 0; int *ovector; int ovecsize; char *utf8string; static bool warned = false; if (!warned && (pattern->pcre_major != PCRE_MAJOR || pattern->pcre_minor != PCRE_MINOR)) { ereport(WARNING, (errmsg("PCRE version mismatch"), errdetail("The compiled pattern was created by PCRE version %d.%d, the current library is version %d.%d. According to the PCRE documentation, \"compiling a regular expression with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes.\" This warning is shown only once per session.", pattern->pcre_major, pattern->pcre_minor, PCRE_MAJOR, PCRE_MINOR), errhint("You might want to recompile the stored patterns by running something like UPDATE ... SET pcre_col = pcre_col::text::pcre."))); warned = true; } pc = (pcre *) (pattern->data + pattern->pattern_strlen + 1); if (num_captured) { int rc; if ((rc = pcre_fullinfo(pc, NULL, PCRE_INFO_CAPTURECOUNT, &num_substrings)) != 0) elog(ERROR, "pcre_fullinfo error: %d", rc); } if (return_matches) { ovecsize = (num_substrings + 1) * 3; ovector = palloc(ovecsize * sizeof(*ovector)); } else { ovecsize = 0; ovector = NULL; } if (GetDatabaseEncoding() == PG_UTF8 || GetDatabaseEncoding() == PG_SQL_ASCII) { utf8string = VARDATA_ANY(subject); rc = pcre_exec(pc, NULL, VARDATA_ANY(subject), VARSIZE_ANY_EXHDR(subject), 0, 0, ovector, ovecsize); } else { utf8string = (char *) pg_do_encoding_conversion((unsigned char *) VARDATA_ANY(subject), VARSIZE_ANY_EXHDR(subject), GetDatabaseEncoding(), PG_UTF8); rc = pcre_exec(pc, NULL, utf8string, strlen(utf8string), 0, 0, ovector, ovecsize); } if (rc == PCRE_ERROR_NOMATCH) return false; else if (rc < 0) elog(ERROR, "PCRE exec error: %d", rc); if (return_matches) { char **matches; if (num_captured) { int i; *num_captured = num_substrings; matches = palloc(num_substrings * sizeof(*matches)); for (i = 1; i <= num_substrings; i++) { if (ovector[i * 2] < 0) matches[i - 1] = NULL; else { const char *xmatch; pcre_get_substring(utf8string, ovector, rc, i, &xmatch); matches[i - 1] = (char *) xmatch; } } } else { const char *xmatch; matches = palloc(1 * sizeof(*matches)); pcre_get_substring(utf8string, ovector, rc, 0, &xmatch); matches[0] = (char *) xmatch; } *return_matches = matches; } return true; } Datum pcre_text_matches(PG_FUNCTION_ARGS) { text *subject = PG_GETARG_TEXT_PP(0); pgpcre *pattern = PG_GETARG_PCRE_P(1); PG_RETURN_BOOL(matches_internal(subject, pattern, NULL, NULL)); } Datum pcre_matches_text(PG_FUNCTION_ARGS) { pgpcre *pattern = PG_GETARG_PCRE_P(0); text *subject = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(matches_internal(subject, pattern, NULL, NULL)); } Datum pcre_text_matches_not(PG_FUNCTION_ARGS) { text *subject = PG_GETARG_TEXT_PP(0); pgpcre *pattern = PG_GETARG_PCRE_P(1); PG_RETURN_BOOL(!matches_internal(subject, pattern, NULL, NULL)); } Datum pcre_matches_text_not(PG_FUNCTION_ARGS) { pgpcre *pattern = PG_GETARG_PCRE_P(0); text *subject = PG_GETARG_TEXT_PP(1); PG_RETURN_BOOL(!matches_internal(subject, pattern, NULL, NULL)); } Datum pcre_match(PG_FUNCTION_ARGS) { pgpcre *pattern = PG_GETARG_PCRE_P(0); text *subject = PG_GETARG_TEXT_PP(1); char **matches; if (matches_internal(subject, pattern, &matches, NULL)) PG_RETURN_TEXT_P(cstring_to_text(matches[0])); else PG_RETURN_NULL(); } Datum pcre_captured_substrings(PG_FUNCTION_ARGS) { pgpcre *pattern = PG_GETARG_PCRE_P(0); text *subject = PG_GETARG_TEXT_PP(1); char **matches; int num_captured; if (matches_internal(subject, pattern, &matches, &num_captured)) { ArrayType *result; int dims[1]; int lbs[1]; Datum *elems; bool *nulls; int i; dims[0] = num_captured; lbs[0] = 1; elems = palloc(num_captured * sizeof(*elems)); nulls = palloc(num_captured * sizeof(*nulls)); for (i = 0; i < num_captured; i++) if (matches[i]) { elems[i] = PointerGetDatum(cstring_to_text(matches[i])); nulls[i] = false; } else nulls[i] = true; result = construct_md_array(elems, nulls, 1, dims, lbs, TEXTOID, -1, false, 'i'); PG_RETURN_ARRAYTYPE_P(result); } else PG_RETURN_NULL(); } static void * pgpcre_malloc(size_t size) { return palloc(size); } static void pgpcre_free(void *ptr) { pfree(ptr); } void _PG_init(void) { pcre_malloc = pgpcre_malloc; pcre_free = pgpcre_free; } pgpcre-0.20190509/pgpcre.control000066400000000000000000000002031346013124600162600ustar00rootroot00000000000000comment = 'Perl Compatible Regular Expression functions' default_version = 1 module_pathname = '$libdir/pgpcre' relocatable = true pgpcre-0.20190509/test/000077500000000000000000000000001346013124600143625ustar00rootroot00000000000000pgpcre-0.20190509/test/expected/000077500000000000000000000000001346013124600161635ustar00rootroot00000000000000pgpcre-0.20190509/test/expected/init.out000066400000000000000000000000311346013124600176510ustar00rootroot00000000000000CREATE EXTENSION pgpcre; pgpcre-0.20190509/test/expected/test.out000066400000000000000000000033501346013124600176740ustar00rootroot00000000000000SELECT pcre 'fo+'; pcre ------ fo+ (1 row) SELECT pcre '+'; ERROR: PCRE compile error: nothing to repeat LINE 1: SELECT pcre '+'; ^ SELECT 'foo' =~ 'fo+'; ?column? ---------- t (1 row) SELECT 'bar' =~ 'fo+'; ?column? ---------- f (1 row) SELECT 'error' =~ '+'; ERROR: PCRE compile error: nothing to repeat LINE 1: SELECT 'error' =~ '+'; ^ SELECT 'foo' ~ pcre 'fo+'; ?column? ---------- t (1 row) SELECT 'bar' ~ pcre 'fo+'; ?column? ---------- f (1 row) SELECT pcre 'fo+' ~ 'foo'; ?column? ---------- t (1 row) SELECT pcre 'fo+' ~ 'bar'; ?column? ---------- f (1 row) SELECT 'foo' !~ pcre 'fo+'; ?column? ---------- f (1 row) SELECT 'bar' !~ pcre 'fo+'; ?column? ---------- t (1 row) SELECT pcre 'fo+' !~ 'foo'; ?column? ---------- f (1 row) SELECT pcre 'fo+' !~ 'bar'; ?column? ---------- t (1 row) SELECT pcre 'fo+' ~ ANY(ARRAY['foo', 'bar']); ?column? ---------- t (1 row) SELECT 'FOO' ~ pcre 'fo+'; ?column? ---------- f (1 row) SELECT 'FOO' ~ pcre '(?i)fo+'; ?column? ---------- t (1 row) SELECT pcre_match('fo+', 'foobar'); pcre_match ------------ foo (1 row) SELECT pcre_match('fo+', 'barbar'); pcre_match ------------ (1 row) SELECT pcre_captured_substrings('(fo+)(b..)', 'foobar'); pcre_captured_substrings -------------------------- {foo,bar} (1 row) SELECT pcre_captured_substrings('(fo+)(b..)', 'abcdef'); pcre_captured_substrings -------------------------- (1 row) SELECT pcre_captured_substrings('(a|(z))(bc)', 'abc'); pcre_captured_substrings -------------------------- {a,NULL,bc} (1 row) SELECT pcre_captured_substrings('(abc)(x(yz)?)?', 'abc'); pcre_captured_substrings -------------------------- {abc,NULL,NULL} (1 row) pgpcre-0.20190509/test/expected/unicode.out000066400000000000000000000005461346013124600203470ustar00rootroot00000000000000-- check that it counts characters, not bytes SELECT 'ätsch' =~ '^.....$'; ?column? ---------- t (1 row) SELECT 'ätsch' =~ '^......$'; ?column? ---------- f (1 row) -- check Unicode properties SELECT 'ätsch' =~ '^\w+$'; ?column? ---------- t (1 row) -- check Unicode in pattern SELECT 'ätsch' =~ '^ätsch$'; ?column? ---------- t (1 row) pgpcre-0.20190509/test/expected/unicode_0.out000066400000000000000000000005461346013124600205660ustar00rootroot00000000000000-- check that it counts characters, not bytes SELECT 'ätsch' =~ '^.....$'; ?column? ---------- f (1 row) SELECT 'ätsch' =~ '^......$'; ?column? ---------- t (1 row) -- check Unicode properties SELECT 'ätsch' =~ '^\w+$'; ?column? ---------- f (1 row) -- check Unicode in pattern SELECT 'ätsch' =~ '^ätsch$'; ?column? ---------- t (1 row) pgpcre-0.20190509/test/sql/000077500000000000000000000000001346013124600151615ustar00rootroot00000000000000pgpcre-0.20190509/test/sql/init.sql000066400000000000000000000000311346013124600166370ustar00rootroot00000000000000CREATE EXTENSION pgpcre; pgpcre-0.20190509/test/sql/test.sql000066400000000000000000000013411346013124600166600ustar00rootroot00000000000000SELECT pcre 'fo+'; SELECT pcre '+'; SELECT 'foo' =~ 'fo+'; SELECT 'bar' =~ 'fo+'; SELECT 'error' =~ '+'; SELECT 'foo' ~ pcre 'fo+'; SELECT 'bar' ~ pcre 'fo+'; SELECT pcre 'fo+' ~ 'foo'; SELECT pcre 'fo+' ~ 'bar'; SELECT 'foo' !~ pcre 'fo+'; SELECT 'bar' !~ pcre 'fo+'; SELECT pcre 'fo+' !~ 'foo'; SELECT pcre 'fo+' !~ 'bar'; SELECT pcre 'fo+' ~ ANY(ARRAY['foo', 'bar']); SELECT 'FOO' ~ pcre 'fo+'; SELECT 'FOO' ~ pcre '(?i)fo+'; SELECT pcre_match('fo+', 'foobar'); SELECT pcre_match('fo+', 'barbar'); SELECT pcre_captured_substrings('(fo+)(b..)', 'foobar'); SELECT pcre_captured_substrings('(fo+)(b..)', 'abcdef'); SELECT pcre_captured_substrings('(a|(z))(bc)', 'abc'); SELECT pcre_captured_substrings('(abc)(x(yz)?)?', 'abc'); pgpcre-0.20190509/test/sql/unicode.sql000066400000000000000000000003451346013124600173320ustar00rootroot00000000000000-- check that it counts characters, not bytes SELECT 'ätsch' =~ '^.....$'; SELECT 'ätsch' =~ '^......$'; -- check Unicode properties SELECT 'ätsch' =~ '^\w+$'; -- check Unicode in pattern SELECT 'ätsch' =~ '^ätsch$';