1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-08 00:47:37 +03:00

Move test modules from contrib to src/test/modules

This is advance preparation for introducing even more test modules; the
easy solution is to add them to contrib, but that's bloated enough that
it seems a good time to think of something different.

Moved modules are dummy_seclabel, test_shm_mq, test_parser and
worker_spi.

(test_decoding was also a candidate, but there was too much opposition
to moving that one.  We can always reconsider later.)
This commit is contained in:
Alvaro Herrera
2014-11-29 23:55:00 -03:00
parent 5b12987b2e
commit 22dfd116a1
38 changed files with 212 additions and 280 deletions

View File

@@ -0,0 +1,4 @@
# Generated subdirectories
/log/
/results/
/tmp_check/

View File

@@ -0,0 +1,21 @@
# src/test/modules/test_parser/Makefile
MODULE_big = test_parser
OBJS = test_parser.o $(WIN32RES)
PGFILEDESC = "test_parser - example of a custom parser for full-text search"
EXTENSION = test_parser
DATA = test_parser--1.0.sql test_parser--unpackaged--1.0.sql
REGRESS = test_parser
ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
else
subdir = src/test/modules/test_parser
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@@ -0,0 +1,61 @@
test_parser is an example of a custom parser for full-text
search. It doesn't do anything especially useful, but can serve as
a starting point for developing your own parser.
test_parser recognizes words separated by white space,
and returns just two token types:
mydb=# SELECT * FROM ts_token_type('testparser');
tokid | alias | description
-------+-------+---------------
3 | word | Word
12 | blank | Space symbols
(2 rows)
These token numbers have been chosen to be compatible with the default
parser's numbering. This allows us to use its headline()
function, thus keeping the example simple.
Usage
=====
Installing the test_parser extension creates a text search
parser testparser. It has no user-configurable parameters.
You can test the parser with, for example,
mydb=# SELECT * FROM ts_parse('testparser', 'That''s my first own parser');
tokid | token
-------+--------
3 | That's
12 |
3 | my
12 |
3 | first
12 |
3 | own
12 |
3 | parser
Real-world use requires setting up a text search configuration
that uses the parser. For example,
mydb=# CREATE TEXT SEARCH CONFIGURATION testcfg ( PARSER = testparser );
CREATE TEXT SEARCH CONFIGURATION
mydb=# ALTER TEXT SEARCH CONFIGURATION testcfg
mydb-# ADD MAPPING FOR word WITH english_stem;
ALTER TEXT SEARCH CONFIGURATION
mydb=# SELECT to_tsvector('testcfg', 'That''s my first own parser');
to_tsvector
-------------------------------
'that':1 'first':3 'parser':5
(1 row)
mydb=# SELECT ts_headline('testcfg', 'Supernovae stars are the brightest phenomena in galaxies',
mydb(# to_tsquery('testcfg', 'star'));
ts_headline
-----------------------------------------------------------------
Supernovae <b>stars</b> are the brightest phenomena in galaxies
(1 row)

View File

@@ -0,0 +1,44 @@
CREATE EXTENSION test_parser;
-- make test configuration using parser
CREATE TEXT SEARCH CONFIGURATION testcfg (PARSER = testparser);
ALTER TEXT SEARCH CONFIGURATION testcfg ADD MAPPING FOR word WITH simple;
-- ts_parse
SELECT * FROM ts_parse('testparser', 'That''s simple parser can''t parse urls like http://some.url/here/');
tokid | token
-------+-----------------------
3 | That's
12 |
3 | simple
12 |
3 | parser
12 |
3 | can't
12 |
3 | parse
12 |
3 | urls
12 |
3 | like
12 |
3 | http://some.url/here/
(15 rows)
SELECT to_tsvector('testcfg','That''s my first own parser');
to_tsvector
-------------------------------------------------
'first':3 'my':2 'own':4 'parser':5 'that''s':1
(1 row)
SELECT to_tsquery('testcfg', 'star');
to_tsquery
------------
'star'
(1 row)
SELECT ts_headline('testcfg','Supernovae stars are the brightest phenomena in galaxies',
to_tsquery('testcfg', 'stars'));
ts_headline
-----------------------------------------------------------------
Supernovae <b>stars</b> are the brightest phenomena in galaxies
(1 row)

View File

@@ -0,0 +1,18 @@
CREATE EXTENSION test_parser;
-- make test configuration using parser
CREATE TEXT SEARCH CONFIGURATION testcfg (PARSER = testparser);
ALTER TEXT SEARCH CONFIGURATION testcfg ADD MAPPING FOR word WITH simple;
-- ts_parse
SELECT * FROM ts_parse('testparser', 'That''s simple parser can''t parse urls like http://some.url/here/');
SELECT to_tsvector('testcfg','That''s my first own parser');
SELECT to_tsquery('testcfg', 'star');
SELECT ts_headline('testcfg','Supernovae stars are the brightest phenomena in galaxies',
to_tsquery('testcfg', 'stars'));

View File

@@ -0,0 +1,32 @@
/* src/test/modules/test_parser/test_parser--1.0.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION test_parser" to load this file. \quit
CREATE FUNCTION testprs_start(internal, int4)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
CREATE FUNCTION testprs_getlexeme(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
CREATE FUNCTION testprs_end(internal)
RETURNS void
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
CREATE FUNCTION testprs_lextype(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
CREATE TEXT SEARCH PARSER testparser (
START = testprs_start,
GETTOKEN = testprs_getlexeme,
END = testprs_end,
HEADLINE = pg_catalog.prsd_headline,
LEXTYPES = testprs_lextype
);

View File

@@ -0,0 +1,10 @@
/* src/test/modules/test_parser/test_parser--unpackaged--1.0.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION test_parser FROM unpackaged" to load this file. \quit
ALTER EXTENSION test_parser ADD function testprs_start(internal,integer);
ALTER EXTENSION test_parser ADD function testprs_getlexeme(internal,internal,internal);
ALTER EXTENSION test_parser ADD function testprs_end(internal);
ALTER EXTENSION test_parser ADD function testprs_lextype(internal);
ALTER EXTENSION test_parser ADD text search parser testparser;

View File

@@ -0,0 +1,128 @@
/*-------------------------------------------------------------------------
*
* test_parser.c
* Simple example of a text search parser
*
* Copyright (c) 2007-2014, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/test/modules/test_parser/test_parser.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
/*
* types
*/
/* self-defined type */
typedef struct
{
char *buffer; /* text to parse */
int len; /* length of the text in buffer */
int pos; /* position of the parser */
} ParserState;
/* copy-paste from wparser.h of tsearch2 */
typedef struct
{
int lexid;
char *alias;
char *descr;
} LexDescr;
/*
* functions
*/
PG_FUNCTION_INFO_V1(testprs_start);
PG_FUNCTION_INFO_V1(testprs_getlexeme);
PG_FUNCTION_INFO_V1(testprs_end);
PG_FUNCTION_INFO_V1(testprs_lextype);
Datum
testprs_start(PG_FUNCTION_ARGS)
{
ParserState *pst = (ParserState *) palloc0(sizeof(ParserState));
pst->buffer = (char *) PG_GETARG_POINTER(0);
pst->len = PG_GETARG_INT32(1);
pst->pos = 0;
PG_RETURN_POINTER(pst);
}
Datum
testprs_getlexeme(PG_FUNCTION_ARGS)
{
ParserState *pst = (ParserState *) PG_GETARG_POINTER(0);
char **t = (char **) PG_GETARG_POINTER(1);
int *tlen = (int *) PG_GETARG_POINTER(2);
int startpos = pst->pos;
int type;
*t = pst->buffer + pst->pos;
if (pst->pos < pst->len &&
(pst->buffer)[pst->pos] == ' ')
{
/* blank type */
type = 12;
/* go to the next non-space character */
while (pst->pos < pst->len &&
(pst->buffer)[pst->pos] == ' ')
(pst->pos)++;
}
else
{
/* word type */
type = 3;
/* go to the next space character */
while (pst->pos < pst->len &&
(pst->buffer)[pst->pos] != ' ')
(pst->pos)++;
}
*tlen = pst->pos - startpos;
/* we are finished if (*tlen == 0) */
if (*tlen == 0)
type = 0;
PG_RETURN_INT32(type);
}
Datum
testprs_end(PG_FUNCTION_ARGS)
{
ParserState *pst = (ParserState *) PG_GETARG_POINTER(0);
pfree(pst);
PG_RETURN_VOID();
}
Datum
testprs_lextype(PG_FUNCTION_ARGS)
{
/*
* Remarks: - we have to return the blanks for headline reason - we use
* the same lexids like Teodor in the default word parser; in this way we
* can reuse the headline function of the default word parser.
*/
LexDescr *descr = (LexDescr *) palloc(sizeof(LexDescr) * (2 + 1));
/* there are only two types in this parser */
descr[0].lexid = 3;
descr[0].alias = pstrdup("word");
descr[0].descr = pstrdup("Word");
descr[1].lexid = 12;
descr[1].alias = pstrdup("blank");
descr[1].descr = pstrdup("Space symbols");
descr[2].lexid = 0;
PG_RETURN_POINTER(descr);
}

View File

@@ -0,0 +1,5 @@
# test_parser extension
comment = 'example of a custom parser for full-text search'
default_version = '1.0'
module_pathname = '$libdir/test_parser'
relocatable = true