Code Monkey home page Code Monkey logo

prefix's Introduction

Prefix Opclass

This module is written by Dimitri Fontaine with a great amount of help from RhodiumToad (formely known as AndrewSN), who was the one advising for a GiST opclass to solve the prefix matching problem.

Presentation

Prefix matching is both very common and important in telephony applications, where call routing and costs depend on matching caller/callee phone number to an operator prefix.

Let's say the prefixes table is called prefixes, a typical query will try to match a phone number to the longest prefix in the table:

SELECT * 
  FROM prefixes
 WHERE prefix @> '0123456789'
ORDER BY length(prefix) DESC
  LIMIT 1;

Installation

debian and ubuntu packages

Replace the PostgreSQL major version number here by the one you're running (pick either 9.1 or 9.2):

apt-get install postgresql-9.2-prefix
psql ...
=# create extension prefix;

fedora, red hat, centos and scientific linux packages

Replace the PostgreSQL major version number here by the one you're running (pick either 91 or 92):

yum install prefix92
psql ...
=# create extension prefix;

from sources

Check $PATH, then

make
make install
psql <connection string> -c 'CREATE EXTENSION prefix;'

The make install step might have to be done as root, and the psql one has to be done as a PostgreSQL superuser.

before 9.1 (consider an upgrade)

If you're running a very old PostgreSQL version such as 8.3, 8.4 of 9.0 you can still install this extension manually:

psql ...
=# \i /usr/share/postgresql/X.Y/extension/prefix--1.2.0.sql

You still have to edit this example to replace X.Y with your local PostgreSQL version number, such as 8.4.

Uninstall

It's as easy as:

DROP TYPE prefix_range CASCADE;

Usage

Table and index creation

create table prefixes (
       prefix    prefix_range primary key,
       name      text not null,
       shortname text,
       status    char default 'S',

       check( status in ('S', 'R') )
);
comment on column prefixes.status is 'S:   - R: reserved';

\copy prefixes from 'prefixes.fr.csv' with delimiter ; csv quote '"'

create index idx_prefix on prefixes using gist(prefix);

Simple tests

dim=# select '123'::prefix_range @> '123456';
 ?column?
----------
 t
(1 row)

Please note earlier versions of prefix didn't use any restriction nor join selectivity estimator functions for the @> operator, so you had to set enable_seqscan to off to use the index. That's no more the case, the @> operator uses contsel and contjoinsel and the planner is able to figure out by itself when to use the index or not.

If you don't understand previous mention, ignore it and use a more recent version of prefix than 0.2.

Forcing seqcan

dim=# select * from ranges where prefix @> '0146640123';
 prefix |      name      | shortname | state
--------+----------------+-----------+-------
 0146[] | FRANCE TELECOM | FRTE      | S
(1 row)

Time: 4,071 ms

dim=# select * from ranges where prefix @> '0100091234';
  prefix  |    name    | shortname | state
----------+------------+-----------+-------
 010009[] | LONG PHONE | LGPH      | S
(1 row)

Time: 4,110 ms

Using the Index

dim=# select * from ranges where prefix @> '0146640123';
 prefix |      name      | shortname | state
--------+----------------+-----------+-------
 0146[] | FRANCE TELECOM | FRTE      | S
(1 row)

Time: 1,036 ms

dim=# select * from ranges where prefix @> '0100091234';
  prefix  |    name    | shortname | state
----------+------------+-----------+-------
 010009[] | LONG PHONE | LGPH      | S
(1 row)

Time: 0,771 ms

As of version 1.0, prefix_range GiST index supports also queries using the <@, && and = operators (see below).

creating prefix_range, cast to and from text

There's a constructor function:

prefix=# select prefix_range('123');
 prefix_range 
--------------
 123
(1 row)

prefix=# select prefix_range('123', '4', '5');
 prefix_range 
--------------
 123[4-5]
(1 row)

Casting from unknown literal or text is as easy as usual:

prefix=# select '123'::prefix_range;
 prefix_range 
--------------
 123
(1 row)

prefix=# select x, x::prefix_range from (values('123'), ('123[4-5]'), ('[2-3]')) as t(x);
    x     |    x     
----------+----------
 123      | 123
 123[4-5] | 123[4-5]
 [2-3]    | [2-3]
(3 rows)

And two casts are provided:

CREATE CAST (text as prefix_range) WITH FUNCTION prefix_range(text) AS IMPLICIT;
CREATE CAST (prefix_range as text) WITH FUNCTION text(prefix_range);

Which means you can use text expression in a context where a prefix_range is expected and it'll get implicit casting, but prefix_range to text has to be asked explicitely, so that you don't get strange behavior.

Provided operators

The prefix module is all about indexing prefix lookups, but in order to be able to do this with some efficiency, it has to know a lot about prefix ranges, such as basic comparing, containment, union, intersection and overlapping.

The operators <=, <, =, <>, >= and > are read as usual, @> is read contains, <@ is read is contained by, && is read overlaps, and | is union and & is intersect.

prefix=# select a, b,
  a <= b as "<=", a < b as "<", a = b as "=", a <> b as "<>", a >= b as ">=", a > b as ">",
  a @> b as "@>", a <@ b as "<@", a && b as "&&"
from  (select a::prefix_range, b::prefix_range
         from (values('123', '123'),
                     ('123', '124'),
                     ('123', '123[4-5]'),
                     ('123[4-5]', '123[2-7]'),
                     ('123', '[2-3]')) as t(a, b)
      ) as x;
    a     |    b     | <= | < | = | <> | >= | > | @> | <@ | && 
----------+----------+----+---+---+----+----+---+----+----+----
 123      | 123      | t  | f | t | f  | t  | f | t  | t  | t
 123      | 124      | t  | t | f | t  | f  | f | f  | f  | f
 123      | 123[4-5] | t  | t | f | t  | f  | f | t  | f  | t
 123[4-5] | 123[2-7] | f  | f | f | t  | t  | t | f  | t  | t
 123      | [2-3]    | t  | t | f | t  | f  | f | f  | f  | f
(5 rows)

prefix=# select a, b, a | b as union, a & b as intersect 
  from  (select a::prefix_range, b::prefix_range
           from (values('123', '123'), 
                       ('123', '124'), 
                       ('123', '123[4-5]'),
                       ('123[4-5]', '123[2-7]'), 
                       ('123', '[2-3]')) as t(a, b)
        ) as x;
    a     |    b     |  union   | intersect 
----------+----------+----------+-----------
 123      | 123      | 123      | 123
 123      | 124      | 12[3-4]  | 
 123      | 123[4-5] | 123      | 123
 123[4-5] | 123[2-7] | 123[2-7] | 123[4-5]
 123      | [2-3]    | [1-3]    | 
(5 rows)

See also

This TESTS.md page is more developper oriented material, but still of interest.

prefix's People

Contributors

debian-janitor avatar df7cb avatar dimitri avatar dmitry-sinina avatar funny-falcon avatar martinos avatar rodo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

prefix's Issues

cast(prefix_range as text) as implicit

There are is a cast to/from text, but only one of them is implicit. We're using text and prefix_range interchangeably in our DB and it would be convenient to have the second cast implicit as well. Any specific reason for why it is not?

CREATE CAST (text as prefix_range) WITH FUNCTION prefix_range(text) AS IMPLICIT;
CREATE CAST (prefix_range as text) WITH FUNCTION text(prefix_range);

(possible) memory leak at pr_overlaps

in prefix.c around line 700, function pr_overlaps

static inline
bool pr_overlaps(prefix_range *a, prefix_range *b) {
  prefix_range *inter = pr_inter(a, b);

  return strlen(inter->prefix) > 0 || (inter->first != 0 && inter->last != 0);
}

it calls pr_inter, who palloc a prefix_range variable as intersect result, but seems to forget to pfree it.

errors trying to install into posrtgresql 9.4.0

downloaded an compiled ok

the make install
/bin/sh /usr/lib64/pgsql/pgxs/src/makefiles/../../config/install-sh -c -m 644 ./prefix--1.2.0.sql '/usr/share/pgsql/contrib'
/bin/sh /usr/lib64/pgsql/pgxs/src/makefiles/../../config/install-sh -c -m 644 ./prefix--unpackaged--1.2.0.sql '/usr/share/pgsql/contrib'
/bin/sh /usr/lib64/pgsql/pgxs/src/makefiles/../../config/install-sh -c -m 644 ./prefix--1.1--1.2.0.sql '/usr/share/pgsql/contrib'
/bin/sh /usr/lib64/pgsql/pgxs/src/makefiles/../../config/install-sh -c -m 755 prefix.so '/usr/lib64/pgsql'
/bin/sh /usr/lib64/pgsql/pgxs/src/makefiles/../../config/install-sh -c -m 644 ./README.md '/usr/share/doc/pgsql/contrib'
/bin/sh /usr/lib64/pgsql/pgxs/src/makefiles/../../config/install-sh -c -m 644 ./TESTS.md '/usr/share/doc/pgsql/contrib
puts the file in /usr/share/pgsql/contrib'

then tried
psql -c 'CREATE EXTENSION prefix;'
this failed

A bit of googlng later i put the file in /usr/local/pgsql/share/extension
now it fails with
ERROR: could not access file "$libdir/prefix": No such file or directory

ANy hints to what is going wrong

pg_config --pkglibdir

/usr/lib64/pgsql

\dx shows incorrect version number

Prefix still shows version as v1.2.0:

postgres=# \dx
                    List of installed extensions
  Name   | Version |   Schema   |            Description
---------+---------+------------+------------------------------------
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
 prefix  | 1.2.0   | public     | Prefix Range module for PostgreSQL
(2 rows)

When I check the control file, it still shows v1.2.0.

https://github.com/dimitri/prefix/blob/master/prefix.control

# prefix extension
comment = 'Prefix Range module for PostgreSQL'
default_version = '1.2.0'
module_pathname = '$libdir/prefix'
relocatable = true

It'd be great if \dx shows the correct version i.e. v.1.2.9.

strange length calculation

I tried using prefixes in range notation(with brackets) but I am a bit confused because length() works incorrectly in this case

yeti=# SELECT *, length(prefix) from (values('12345'::prefix_range), ('123[3-4]'::prefix_range)) as data(prefix)  where prefix@>'123456789' order by length(prefix);
  prefix  | length 
----------+--------
 12345    |      5
 123[3-4] |      5

Using this query I can't find best prefix for number 123456789, because length comparison does not work. I think length('123[3-4]'::prefix_range) must return 4 instead of 5

TESTS.html does not exists

At the end of README.md there is a link to TESTS.html which does not exists, when TESTS.md is, maybe a PR is not necessary to fix this :-)

any update for postgresql 9.3 ?

I tried to install prefix for pgsql 9.3 but when I do
psql -c 'CREATE EXTENSION prefix;'

it says
Server is version 9.3, library is version 9.2

I tried to change prefix.c without success.
btw it compiles fine.

thanks

Cannot make it work on Postgresql 10

I have installed the prefix extension:

make 
PG_CONFIG=/opt/PostgreSQL/10/bin/pg_config make install

When I create the extension:

psql  -c 'CREATE EXTENSION prefix;' my_db

I get the following error:

ERROR:  could not load library "/opt/PostgreSQL/10/lib/postgresql/prefix.so": /opt/PostgreSQL/10/lib/postgresql/prefix.so: undefined symbol: Float4GetDatum

I am wondering if the prefix extension is working on postgresql 10.

incorrent gist index result on <@

create table tst (
  pref prefix_range
);

insert into tst
select trim(to_char(i, '00000')) from generate_series(1, 99999) as i;

select count(*)
from tst
where pref <@ '55';

create index tst_ix on tst using gist ( pref );

set enable_seqscan = off;

select count(*)
from tst
where pref <@ '55';

does not compile on 16

does not compile on 16

gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wshadow=compatible-local -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -fno-omit-frame-pointer -Werror-implicit-function-declaration -Werror -fPIC -fvisibility=hidden -I. -I./ -I/usr/local/include/postgresql/server -I/usr/local/include/postgresql/internal  -D_GNU_SOURCE -I/usr/include/libxml2  -I/usr/local/include  -c -o prefix.o prefix.c
clang-15 -Wno-ignored-attributes -fno-strict-aliasing -fwrapv -Xclang -no-opaque-pointers -Wno-unused-command-line-argument -Wno-compound-token-split-by-macro -O2  -I. -I./ -I/usr/local/include/postgresql/server -I/usr/local/include/postgresql/internal  -D_GNU_SOURCE -I/usr/include/libxml2  -I/usr/local/include -flto=thin -emit-llvm -c -o prefix.bc prefix.c
prefix.c: In function 'make_varlena':
prefix.c:371:5: error: implicit declaration of function 'SET_VARSIZE' [-Werror=implicit-function-declaration]
  371 |     SET_VARSIZE(vdat, size);
      |     ^~~~~~~~~~~
prefix.c:372:12: error: implicit declaration of function 'VARDATA' [-Werror=implicit-function-declaration]
  372 |     memcpy(VARDATA(vdat), pr, (size - VARHDRSZ));
      |            ^~~~~~~
prefix.c:372:12: error: passing argument 1 of 'memcpy' makes pointer from integer without a cast [-Werror=int-conversion]
  372 |     memcpy(VARDATA(vdat), pr, (size - VARHDRSZ));
      |            ^~~~~~~~~~~~~
      |            |
      |            int
In file included from /usr/include/fortify/string.h:23,
                 from /usr/local/include/postgresql/server/c.h:61,
                 from /usr/local/include/postgresql/server/postgres.h:45,
                 from prefix.c:16:
/usr/include/string.h:27:15: note: expected 'void * restrict' but argument is of type 'int'
   27 | void *memcpy (void *__restrict, const void *__restrict, size_t);
prefix.c: In function 'pr_contains_prefix':
prefix.c:539:14: error: implicit declaration of function 'VARSIZE_ANY_EXHDR' [-Werror=implicit-function-declaration]
  539 |   int qlen = VARSIZE_ANY_EXHDR(query);
      |              ^~~~~~~~~~~~~~~~~
prefix.c:541:22: error: implicit declaration of function 'VARDATA_ANY' [-Werror=implicit-function-declaration]
  541 |   char *q  = (char *)VARDATA_ANY(query);
      |                      ^~~~~~~~~~~
prefix.c:541:14: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
  541 |   char *q  = (char *)VARDATA_ANY(query);
      |              ^
prefix.c: In function 'prefix_range_out':
/usr/local/include/postgresql/server/fmgr.h:241:9: error: passing argument 1 of 'DatumGetPointer' makes integer from pointer without a cast [-Werror=int-conversion]
  241 |         pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |         |
      |         struct varlena *
prefix.c:91:89: note: in definition of macro 'DatumGetPrefixRange'
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                                                                         ^
prefix.c:93:63: note: in expansion of macro 'PG_DETOAST_DATUM'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                                               ^~~~~~~~~~~~~~~~
prefix.c:765:22: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  765 |   prefix_range *pr = PG_GETARG_PREFIX_RANGE_P(0);
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/postgres.h:312:23: note: expected 'Datum' {aka 'long unsigned int'} but argument is of type 'struct varlena *'
  312 | DatumGetPointer(Datum X)
      |                 ~~~~~~^
prefix.c:91:44: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                            ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:765:22: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  765 |   prefix_range *pr = PG_GETARG_PREFIX_RANGE_P(0);
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~
prefix.c: In function 'prefix_range_send':
/usr/local/include/postgresql/server/fmgr.h:241:9: error: passing argument 1 of 'DatumGetPointer' makes integer from pointer without a cast [-Werror=int-conversion]
  241 |         pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |         |
      |         struct varlena *
prefix.c:91:89: note: in definition of macro 'DatumGetPrefixRange'
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                                                                         ^
prefix.c:93:63: note: in expansion of macro 'PG_DETOAST_DATUM'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                                               ^~~~~~~~~~~~~~~~
prefix.c:797:24: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  797 |     prefix_range *pr = PG_GETARG_PREFIX_RANGE_P(0);
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/postgres.h:312:23: note: expected 'Datum' {aka 'long unsigned int'} but argument is of type 'struct varlena *'
  312 | DatumGetPointer(Datum X)
      |                 ~~~~~~^
prefix.c:91:44: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                            ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:797:24: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  797 |     prefix_range *pr = PG_GETARG_PREFIX_RANGE_P(0);
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~
prefix.c: In function 'prefix_range_cast_to_text':
/usr/local/include/postgresql/server/fmgr.h:241:9: error: passing argument 1 of 'DatumGetPointer' makes integer from pointer without a cast [-Werror=int-conversion]
  241 |         pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |         |
      |         struct varlena *
prefix.c:91:89: note: in definition of macro 'DatumGetPrefixRange'
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                                                                         ^
prefix.c:93:63: note: in expansion of macro 'PG_DETOAST_DATUM'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                                               ^~~~~~~~~~~~~~~~
prefix.c:821:22: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  821 |   prefix_range *pr = PG_GETARG_PREFIX_RANGE_P(0);
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/postgres.h:312:23: note: expected 'Datum' {aka 'long unsigned int'} but argument is of type 'struct varlena *'
  312 | DatumGetPointer(Datum X)
      |                 ~~~~~~^
prefix.c:91:44: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                            ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:821:22: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  821 |   prefix_range *pr = PG_GETARG_PREFIX_RANGE_P(0);
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/include/postgresql/server/access/skey.h:19,
                 from prefix.c:19:
prefix.c: In function 'prefix_range_length':
/usr/local/include/postgresql/server/fmgr.h:241:9: error: passing argument 1 of 'DatumGetPointer' makes integer from pointer without a cast [-Werror=int-conversion]
  241 |         pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |         |
      |         struct varlena *
/usr/local/include/postgresql/server/fmgr.h:354:55: note: in definition of macro 'PG_RETURN_INT32'
  354 | #define PG_RETURN_INT32(x)       return Int32GetDatum(x)
      |                                                       ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:93:63: note: in expansion of macro 'PG_DETOAST_DATUM'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                                               ^~~~~~~~~~~~~~~~
prefix.c:838:30: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  838 |   PG_RETURN_INT32( pr_length(PG_GETARG_PREFIX_RANGE_P(0)) );
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/postgres.h:312:23: note: expected 'Datum' {aka 'long unsigned int'} but argument is of type 'struct varlena *'
  312 | DatumGetPointer(Datum X)
      |                 ~~~~~~^
prefix.c:91:44: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                            ^
/usr/local/include/postgresql/server/fmgr.h:354:55: note: in definition of macro 'PG_RETURN_INT32'
  354 | #define PG_RETURN_INT32(x)       return Int32GetDatum(x)
      |                                                       ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:838:30: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  838 |   PG_RETURN_INT32( pr_length(PG_GETARG_PREFIX_RANGE_P(0)) );
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~
prefix.c: In function 'prefix_range_eq':
/usr/local/include/postgresql/server/fmgr.h:241:9: error: passing argument 1 of 'DatumGetPointer' makes integer from pointer without a cast [-Werror=int-conversion]
  241 |         pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |         |
      |         struct varlena *
/usr/local/include/postgresql/server/fmgr.h:359:54: note: in definition of macro 'PG_RETURN_BOOL'
  359 | #define PG_RETURN_BOOL(x)        return BoolGetDatum(x)
      |                                                      ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:93:63: note: in expansion of macro 'PG_DETOAST_DATUM'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                                               ^~~~~~~~~~~~~~~~
prefix.c:845:25: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  845 |   PG_RETURN_BOOL( pr_eq(PG_GETARG_PREFIX_RANGE_P(0),
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/postgres.h:312:23: note: expected 'Datum' {aka 'long unsigned int'} but argument is of type 'struct varlena *'
  312 | DatumGetPointer(Datum X)
      |                 ~~~~~~^
prefix.c:91:44: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                            ^
/usr/local/include/postgresql/server/fmgr.h:359:54: note: in definition of macro 'PG_RETURN_BOOL'
  359 | #define PG_RETURN_BOOL(x)        return BoolGetDatum(x)
      |                                                      ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:845:25: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  845 |   PG_RETURN_BOOL( pr_eq(PG_GETARG_PREFIX_RANGE_P(0),
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/fmgr.h:241:9: error: passing argument 1 of 'DatumGetPointer' makes integer from pointer without a cast [-Werror=int-conversion]
  241 |         pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |         |
      |         struct varlena *
/usr/local/include/postgresql/server/fmgr.h:359:54: note: in definition of macro 'PG_RETURN_BOOL'
  359 | #define PG_RETURN_BOOL(x)        return BoolGetDatum(x)
      |                                                      ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:93:63: note: in expansion of macro 'PG_DETOAST_DATUM'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                                               ^~~~~~~~~~~~~~~~
prefix.c:846:25: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  846 |                         PG_GETARG_PREFIX_RANGE_P(1)) );
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/postgres.h:312:23: note: expected 'Datum' {aka 'long unsigned int'} but argument is of type 'struct varlena *'
  312 | DatumGetPointer(Datum X)
      |                 ~~~~~~^
prefix.c:91:44: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                            ^
/usr/local/include/postgresql/server/fmgr.h:359:54: note: in definition of macro 'PG_RETURN_BOOL'
  359 | #define PG_RETURN_BOOL(x)        return BoolGetDatum(x)
      |                                                      ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:846:25: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  846 |                         PG_GETARG_PREFIX_RANGE_P(1)) );
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~
prefix.c: In function 'prefix_range_neq':
/usr/local/include/postgresql/server/fmgr.h:241:9: error: passing argument 1 of 'DatumGetPointer' makes integer from pointer without a cast [-Werror=int-conversion]
  241 |         pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |         |
      |         struct varlena *
/usr/local/include/postgresql/server/fmgr.h:359:54: note: in definition of macro 'PG_RETURN_BOOL'
  359 | #define PG_RETURN_BOOL(x)        return BoolGetDatum(x)
      |                                                      ^
prefix.c:93:43: note: in expansion of macro 'DatumGetPrefixRange'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                           ^~~~~~~~~~~~~~~~~~~
prefix.c:93:63: note: in expansion of macro 'PG_DETOAST_DATUM'
   93 | #define PG_GETARG_PREFIX_RANGE_P(n)       DatumGetPrefixRange(PG_DETOAST_DATUM(PG_GETARG_DATUM(n)))
      |                                                               ^~~~~~~~~~~~~~~~
prefix.c:853:27: note: in expansion of macro 'PG_GETARG_PREFIX_RANGE_P'
  853 |   PG_RETURN_BOOL( ! pr_eq(PG_GETARG_PREFIX_RANGE_P(0),
      |                           ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/postgresql/server/postgres.h:312:23: note: expected 'Datum' {aka 'long unsigned int'} but argument is of type 'struct varlena *'
  312 | DatumGetPointer(Datum X)
      |                 ~~~~~~^
prefix.c:91:44: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
   91 | #define DatumGetPrefixRange(X)            ((prefix_range *) VARDATA_ANY(DatumGetPointer(X)) )
      |                                            ^
/usr/local/include/postgresql/server/fmgr.h:359:54: note: in definition of macro 'PG_RETURN_BOOL'
  359 | #define PG_RETURN_BOOL(x)        return BoolGetDatum(x)
      |                                                      ^
...

prefix92 conflict with another version of prefix

If I can have several postgresql versions running is same machine (testing purpose), why can't I have also prefix installed in every version of postgresql?

I would like to install both: prefix92 and prefix94 in the same server.

yum install prefix92.x86_64 prefix94.x86_64

Loaded plugins: fastestmirror, priorities, security
Setting up Install Process
Loading mirror speeds from cached hostfile

  • base: ftp.udl.es
  • epel: fedora.aau.at
  • extras: ftp.udl.es
  • rpmforge: mirror1.hs-esslingen.de
  • updates: ftp.dei.uc.pt
    Resolving Dependencies
    --> Running transaction check
    ---> Package prefix92.x86_64 0:1.2.0-1.rhel6 will be installed
    ---> Package prefix94.x86_64 0:1.2.3-1.rhel6 will be installed
    --> Finished Dependency Resolution

Dependencies Resolved

Package Arch Version Repository Size

Installing:
prefix92 x86_64 1.2.0-1.rhel6 pgdg92 20 k
prefix94 x86_64 1.2.3-1.rhel6 pgdg94 20 k

Transaction Summary

Install 2 Package(s)

Total download size: 41 k
Installed size: 113 k
Is this ok [y/N]: y
Downloading Packages:
(1/2): prefix92-1.2.0-1.rhel6.x86_64.rpm | 20 kB 00:00

(2/2): prefix94-1.2.3-1.rhel6.x86_64.rpm | 20 kB 00:00

Total 28 kB/s | 41 kB 00:01
Running rpm_check_debug
Running Transaction Test

Transaction Check Error:
file /usr/share/doc/pgsql/extension/README.md conflicts between attempted installs of prefix92-1.2.0-1.rhel6.x86_64 and prefix94-1.2.3-1.rhel6.x86_6

Support for PostgreSQL 9.2

Prefix doesn't support being built against/support postgresql 9.2:

$cd prefix
$make
gcc -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -fpic -DPREFIX_PGVER=902 -I. -I. -I/usr/include/postgresql/server -I/usr/include/postgresql/internal -D_GNU_SOURCE -I/usr/include/libxml2 -c -o prefix.o prefix.c
prefix.c:62:2: error: #error "Unknown or unsupported postgresql version"
prefix.c: In function ‘pr_presort’:
prefix.c:1435:15: warning: variable ‘maxlen’ set but not used [-Wunused-but-set-variable]
prefix.c: In function ‘gpr_union’:
prefix.c:1868:31: warning: variable ‘old’ set but not used [-Wunused-but-set-variable]
make: *** [prefix.o] Error 1

cppcheck find bug

prefix.c:1273:12: style: Redundant initialization for 'maxoff'. The initialized value is overwritten before it is read. [redundantInitialization]
    maxoff = entryvec->n - 1;
           ^
prefix.c:1260:25: note: maxoff is initialized
    OffsetNumber maxoff = entryvec->n - 1;
                        ^
prefix.c:1273:12: note: maxoff is overwritten
    maxoff = entryvec->n - 1;
           ^

doesn't build with PostgreSQL 9.4

Maybe this check can be downgraded to a warning:

prefix.c:63:2: error: #error "Unknown or unsupported postgresql version"

Otherwise it's hard to test newer versions.

Actually, I'd just remove it. If a version is not supported, you'll presumably be told be a compiler error or test failure.

<@ seems working incorrect

Dmitri,
Looks there is misbehavior of @> and <@ operators, please take a look at the output
I use pgsql 9.1 with this latest git of your module.

Attempt to match
select '441873'::public.prefix_range <@ '4418731234'::public.prefix_range

is false while 'is contained by' should be true.

It seems have worked in previous PG versions, but i currently do not have 8.x installs to check.

select a, b,
a <= b as "<=", a < b as "<", a = b as "=", a <> b as "<>", a >= b as ">=", a > b as ">",
a @> b as "@>", a <@ b as "<@", a && b as "&&"
from (select a::prefix_range, b::prefix_range
from (values('441873', '4418731234'),
('441873', '4418731234')
) as t(a, b)
) as x;

a | b | <= | < | = | <> | >= | > | @> | <@ | &&
--------+------------+----+---+---+----+----+---+----+----+----
441873 | 4418731234 | f | f | f | t | t | t | t | f | t
441873 | 4418731234 | f | f | f | t | t | t | t | f | t
(2 rows)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.