summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorMichael P2011-07-05 03:16:11 +0000
committerMichael P2011-07-06 03:40:35 +0000
commit0bbfc1e6338b5d98d6cb83fa75f2c38f527d4d4b (patch)
tree46fa412a31d08ea6e53d488ae7bc231df0b273da /contrib
parent091b0e828cf0fd5bbd1f9ae58ab96fc983e55d77 (diff)
parenta4bebdd92624e018108c2610fc3f2c1584b6c687 (diff)
Merge commit 'a4bebdd92624e018108c2610fc3f2c1584b6c687' into master
This is the commit merge of Postgres-XC with the intersection of PostgreSQL REL9_1_STABLE and master branches. Conflicts: COPYRIGHT contrib/pgbench/pgbench.c src/Makefile src/backend/access/transam/recovery.conf.sample src/backend/access/transam/varsup.c src/backend/access/transam/xlog.c src/backend/catalog/Makefile src/backend/catalog/dependency.c src/backend/catalog/system_views.sql src/backend/commands/copy.c src/backend/commands/explain.c src/backend/commands/sequence.c src/backend/commands/tablecmds.c src/backend/commands/vacuum.c src/backend/executor/nodeAgg.c src/backend/nodes/copyfuncs.c src/backend/nodes/equalfuncs.c src/backend/nodes/outfuncs.c src/backend/nodes/readfuncs.c src/backend/optimizer/path/allpaths.c src/backend/optimizer/plan/createplan.c src/backend/optimizer/plan/setrefs.c src/backend/parser/gram.y src/backend/parser/parse_utilcmd.c src/backend/postmaster/postmaster.c src/backend/rewrite/rewriteHandler.c src/backend/storage/lmgr/proc.c src/backend/tcop/postgres.c src/backend/utils/adt/ruleutils.c src/backend/utils/init/postinit.c src/backend/utils/misc/guc.c src/backend/utils/misc/postgresql.conf.sample src/backend/utils/sort/tuplesort.c src/bin/initdb/initdb.c src/bin/pg_ctl/pg_ctl.c src/bin/pg_dump/pg_dump.c src/include/access/xlog.h src/include/catalog/catversion.h src/include/catalog/indexing.h src/include/catalog/pg_aggregate.h src/include/catalog/pg_proc.h src/include/commands/copy.h src/include/nodes/parsenodes.h src/include/nodes/primnodes.h src/include/optimizer/pathnode.h src/include/parser/kwlist.h src/include/storage/procarray.h src/test/regress/expected/.gitignore src/test/regress/expected/aggregates.out src/test/regress/expected/alter_table.out src/test/regress/expected/bit.out src/test/regress/expected/box.out src/test/regress/expected/delete.out src/test/regress/expected/float4.out src/test/regress/expected/float8.out src/test/regress/expected/int2.out src/test/regress/expected/int8.out src/test/regress/expected/interval.out src/test/regress/expected/numeric.out src/test/regress/expected/point.out src/test/regress/expected/polygon.out src/test/regress/expected/sequence.out src/test/regress/expected/timestamp.out src/test/regress/expected/timestamptz.out src/test/regress/expected/transactions.out src/test/regress/expected/window.out src/test/regress/input/misc.source src/test/regress/output/create_misc_1.source src/test/regress/output/misc.source src/test/regress/sql/aggregates.sql src/test/regress/sql/alter_table.sql src/test/regress/sql/bit.sql src/test/regress/sql/box.sql src/test/regress/sql/delete.sql src/test/regress/sql/domain.sql src/test/regress/sql/float4.sql src/test/regress/sql/float8.sql src/test/regress/sql/int2.sql src/test/regress/sql/int8.sql src/test/regress/sql/interval.sql src/test/regress/sql/lseg.sql src/test/regress/sql/numeric.sql src/test/regress/sql/path.sql src/test/regress/sql/point.sql src/test/regress/sql/polygon.sql src/test/regress/sql/portals.sql src/test/regress/sql/sequence.sql src/test/regress/sql/timestamp.sql src/test/regress/sql/timestamptz.sql src/test/regress/sql/transactions.sql src/test/regress/sql/window.sql src/test/regress/sql/with.sql
Diffstat (limited to 'contrib')
-rw-r--r--contrib/Makefile22
-rw-r--r--contrib/README27
-rw-r--r--contrib/adminpack/Makefile9
-rw-r--r--contrib/adminpack/adminpack--1.0.sql (renamed from contrib/adminpack/adminpack.sql.in)18
-rw-r--r--contrib/adminpack/adminpack.c45
-rw-r--r--contrib/adminpack/adminpack.control6
-rw-r--r--contrib/adminpack/uninstall_adminpack.sql10
-rw-r--r--contrib/auth_delay/Makefile14
-rw-r--r--contrib/auth_delay/auth_delay.c71
-rw-r--r--contrib/auto_explain/Makefile2
-rw-r--r--contrib/auto_explain/auto_explain.c38
-rw-r--r--contrib/btree_gin/.gitignore4
-rw-r--r--contrib/btree_gin/Makefile9
-rw-r--r--contrib/btree_gin/btree_gin--1.0.sql (renamed from contrib/btree_gin/btree_gin.sql.in)141
-rw-r--r--contrib/btree_gin/btree_gin--unpackaged--1.0.sql116
-rw-r--r--contrib/btree_gin/btree_gin.c14
-rw-r--r--contrib/btree_gin/btree_gin.control5
-rw-r--r--contrib/btree_gin/expected/cidr.out2
-rw-r--r--contrib/btree_gin/expected/date.out2
-rw-r--r--contrib/btree_gin/expected/inet.out2
-rw-r--r--contrib/btree_gin/expected/install_btree_gin.out4
-rw-r--r--contrib/btree_gin/expected/interval.out2
-rw-r--r--contrib/btree_gin/expected/macaddr.out2
-rw-r--r--contrib/btree_gin/expected/time.out2
-rw-r--r--contrib/btree_gin/expected/timestamp.out2
-rw-r--r--contrib/btree_gin/expected/timestamptz.out2
-rw-r--r--contrib/btree_gin/expected/timetz.out2
-rw-r--r--contrib/btree_gin/sql/cidr.sql2
-rw-r--r--contrib/btree_gin/sql/date.sql2
-rw-r--r--contrib/btree_gin/sql/inet.sql2
-rw-r--r--contrib/btree_gin/sql/install_btree_gin.sql6
-rw-r--r--contrib/btree_gin/sql/interval.sql2
-rw-r--r--contrib/btree_gin/sql/macaddr.sql2
-rw-r--r--contrib/btree_gin/sql/time.sql2
-rw-r--r--contrib/btree_gin/sql/timestamp.sql2
-rw-r--r--contrib/btree_gin/sql/timestamptz.sql2
-rw-r--r--contrib/btree_gin/sql/timetz.sql2
-rw-r--r--contrib/btree_gin/uninstall_btree_gin.sql98
-rw-r--r--contrib/btree_gist/.gitignore4
-rw-r--r--contrib/btree_gist/Makefile24
-rw-r--r--contrib/btree_gist/btree_bit.c59
-rw-r--r--contrib/btree_gist/btree_bytea.c55
-rw-r--r--contrib/btree_gist/btree_cash.c54
-rw-r--r--contrib/btree_gist/btree_date.c51
-rw-r--r--contrib/btree_gist/btree_float4.c48
-rw-r--r--contrib/btree_gist/btree_float8.c54
-rw-r--r--contrib/btree_gist/btree_gist--1.0.sql (renamed from contrib/btree_gist/btree_gist.sql.in)632
-rw-r--r--contrib/btree_gist/btree_gist--unpackaged--1.0.sql476
-rw-r--r--contrib/btree_gist/btree_gist.c2
-rw-r--r--contrib/btree_gist/btree_gist.control5
-rw-r--r--contrib/btree_gist/btree_gist.h4
-rw-r--r--contrib/btree_gist/btree_inet.c5
-rw-r--r--contrib/btree_gist/btree_int2.c51
-rw-r--r--contrib/btree_gist/btree_int4.c55
-rw-r--r--contrib/btree_gist/btree_int8.c55
-rw-r--r--contrib/btree_gist/btree_interval.c59
-rw-r--r--contrib/btree_gist/btree_macaddr.c5
-rw-r--r--contrib/btree_gist/btree_numeric.c58
-rw-r--r--contrib/btree_gist/btree_oid.c55
-rw-r--r--contrib/btree_gist/btree_text.c62
-rw-r--r--contrib/btree_gist/btree_time.c51
-rw-r--r--contrib/btree_gist/btree_ts.c123
-rw-r--r--contrib/btree_gist/btree_utils_num.c53
-rw-r--r--contrib/btree_gist/btree_utils_num.h41
-rw-r--r--contrib/btree_gist/btree_utils_var.c157
-rw-r--r--contrib/btree_gist/btree_utils_var.h40
-rw-r--r--contrib/btree_gist/data/interval.data2
-rw-r--r--contrib/btree_gist/data/macaddr.data2
-rw-r--r--contrib/btree_gist/data/numeric.data2
-rw-r--r--contrib/btree_gist/data/text.data2
-rw-r--r--contrib/btree_gist/data/timetz.data2
-rw-r--r--contrib/btree_gist/data/varbit.data2
-rw-r--r--contrib/btree_gist/expected/cash.out25
-rw-r--r--contrib/btree_gist/expected/date.out25
-rw-r--r--contrib/btree_gist/expected/float4.out25
-rw-r--r--contrib/btree_gist/expected/float8.out25
-rw-r--r--contrib/btree_gist/expected/init.out8
-rw-r--r--contrib/btree_gist/expected/int2.out25
-rw-r--r--contrib/btree_gist/expected/int4.out25
-rw-r--r--contrib/btree_gist/expected/int8.out25
-rw-r--r--contrib/btree_gist/expected/interval.out25
-rw-r--r--contrib/btree_gist/expected/not_equal.out40
-rw-r--r--contrib/btree_gist/expected/time.out25
-rw-r--r--contrib/btree_gist/expected/timestamp.out25
-rw-r--r--contrib/btree_gist/expected/timestamptz.out25
-rw-r--r--contrib/btree_gist/sql/cash.sql6
-rw-r--r--contrib/btree_gist/sql/cidr.sql1
-rw-r--r--contrib/btree_gist/sql/date.sql5
-rw-r--r--contrib/btree_gist/sql/float4.sql6
-rw-r--r--contrib/btree_gist/sql/float8.sql6
-rw-r--r--contrib/btree_gist/sql/inet.sql1
-rw-r--r--contrib/btree_gist/sql/init.sql10
-rw-r--r--contrib/btree_gist/sql/int2.sql5
-rw-r--r--contrib/btree_gist/sql/int4.sql5
-rw-r--r--contrib/btree_gist/sql/int8.sql5
-rw-r--r--contrib/btree_gist/sql/interval.sql5
-rw-r--r--contrib/btree_gist/sql/macaddr.sql1
-rw-r--r--contrib/btree_gist/sql/not_equal.sql32
-rw-r--r--contrib/btree_gist/sql/time.sql5
-rw-r--r--contrib/btree_gist/sql/timestamp.sql5
-rw-r--r--contrib/btree_gist/sql/timestamptz.sql6
-rw-r--r--contrib/btree_gist/uninstall_btree_gist.sql280
-rw-r--r--contrib/chkpass/Makefile8
-rw-r--r--contrib/chkpass/chkpass--1.0.sql (renamed from contrib/chkpass/chkpass.sql.in)16
-rw-r--r--contrib/chkpass/chkpass--unpackaged--1.0.sql10
-rw-r--r--contrib/chkpass/chkpass.c2
-rw-r--r--contrib/chkpass/chkpass.control5
-rw-r--r--contrib/chkpass/uninstall_chkpass.sql16
-rw-r--r--contrib/citext/.gitignore4
-rw-r--r--contrib/citext/Makefile8
-rw-r--r--contrib/citext/citext--1.0.sql (renamed from contrib/citext/citext.sql.in)84
-rw-r--r--contrib/citext/citext--unpackaged--1.0.sql88
-rw-r--r--contrib/citext/citext.c46
-rw-r--r--contrib/citext/citext.control5
-rw-r--r--contrib/citext/expected/citext.out11
-rw-r--r--contrib/citext/expected/citext_1.out11
-rw-r--r--contrib/citext/sql/citext.sql14
-rw-r--r--contrib/citext/uninstall_citext.sql80
-rw-r--r--contrib/contrib-global.mk2
-rw-r--r--contrib/cube/.cvsignore2
-rw-r--r--contrib/cube/.gitignore6
-rw-r--r--contrib/cube/CHANGES4
-rw-r--r--contrib/cube/Makefile7
-rw-r--r--contrib/cube/cube--1.0.sql (renamed from contrib/cube/cube.sql.in)84
-rw-r--r--contrib/cube/cube--unpackaged--1.0.sql53
-rw-r--r--contrib/cube/cube.c10
-rw-r--r--contrib/cube/cube.control5
-rw-r--r--contrib/cube/cubedata.h2
-rw-r--r--contrib/cube/cubeparse.y34
-rw-r--r--contrib/cube/cubescan.l8
-rw-r--r--contrib/cube/expected/cube.out20
-rw-r--r--contrib/cube/expected/cube_1.out20
-rw-r--r--contrib/cube/expected/cube_2.out20
-rw-r--r--contrib/cube/expected/cube_3.out1128
-rw-r--r--contrib/cube/sql/cube.sql22
-rw-r--r--contrib/cube/uninstall_cube.sql98
-rw-r--r--contrib/dblink/.gitignore4
-rw-r--r--contrib/dblink/Makefile11
-rw-r--r--contrib/dblink/dblink--1.0.sql (renamed from contrib/dblink/dblink.sql.in)89
-rw-r--r--contrib/dblink/dblink--unpackaged--1.0.sql43
-rw-r--r--contrib/dblink/dblink.c28
-rw-r--r--contrib/dblink/dblink.control5
-rw-r--r--contrib/dblink/dblink.h4
-rw-r--r--contrib/dblink/expected/dblink.out20
-rw-r--r--contrib/dblink/sql/dblink.sql23
-rw-r--r--contrib/dblink/uninstall_dblink.sql86
-rw-r--r--contrib/dict_int/.gitignore4
-rw-r--r--contrib/dict_int/Makefile8
-rw-r--r--contrib/dict_int/dict_int--1.0.sql (renamed from contrib/dict_int/dict_int.sql.in)9
-rw-r--r--contrib/dict_int/dict_int--unpackaged--1.0.sql6
-rw-r--r--contrib/dict_int/dict_int.c4
-rw-r--r--contrib/dict_int/dict_int.control5
-rw-r--r--contrib/dict_int/expected/dict_int.out8
-rw-r--r--contrib/dict_int/sql/dict_int.sql10
-rw-r--r--contrib/dict_int/uninstall_dict_int.sql12
-rw-r--r--contrib/dict_xsyn/.gitignore4
-rw-r--r--contrib/dict_xsyn/Makefile8
-rw-r--r--contrib/dict_xsyn/dict_xsyn--1.0.sql (renamed from contrib/dict_xsyn/dict_xsyn.sql.in)9
-rw-r--r--contrib/dict_xsyn/dict_xsyn--unpackaged--1.0.sql6
-rw-r--r--contrib/dict_xsyn/dict_xsyn.c4
-rw-r--r--contrib/dict_xsyn/dict_xsyn.control5
-rw-r--r--contrib/dict_xsyn/expected/dict_xsyn.out8
-rw-r--r--contrib/dict_xsyn/sql/dict_xsyn.sql10
-rw-r--r--contrib/dict_xsyn/uninstall_dict_xsyn.sql12
-rw-r--r--contrib/dummy_seclabel/Makefile14
-rw-r--r--contrib/dummy_seclabel/dummy_seclabel.c49
-rw-r--r--contrib/earthdistance/.gitignore4
-rw-r--r--contrib/earthdistance/Makefile9
-rw-r--r--contrib/earthdistance/earthdistance--1.0.sql (renamed from contrib/earthdistance/earthdistance.sql.in)29
-rw-r--r--contrib/earthdistance/earthdistance--unpackaged--1.0.sql13
-rw-r--r--contrib/earthdistance/earthdistance.c2
-rw-r--r--contrib/earthdistance/earthdistance.control6
-rw-r--r--contrib/earthdistance/expected/earthdistance.out9
-rw-r--r--contrib/earthdistance/sql/earthdistance.sql12
-rw-r--r--contrib/earthdistance/uninstall_earthdistance.sql26
-rw-r--r--contrib/file_fdw/.gitignore4
-rw-r--r--contrib/file_fdw/Makefile21
-rw-r--r--contrib/file_fdw/data/agg.bad4
-rw-r--r--contrib/file_fdw/data/agg.csv4
-rw-r--r--contrib/file_fdw/data/agg.data4
-rw-r--r--contrib/file_fdw/expected/.gitignore1
-rw-r--r--contrib/file_fdw/file_fdw--1.0.sql15
-rw-r--r--contrib/file_fdw/file_fdw.c536
-rw-r--r--contrib/file_fdw/file_fdw.control5
-rw-r--r--contrib/file_fdw/input/file_fdw.source131
-rw-r--r--contrib/file_fdw/output/file_fdw.source225
-rw-r--r--contrib/file_fdw/sql/.gitignore1
-rw-r--r--contrib/fuzzystrmatch/Makefile10
-rw-r--r--contrib/fuzzystrmatch/dmetaphone.c2
-rw-r--r--contrib/fuzzystrmatch/fuzzystrmatch--1.0.sql41
-rw-r--r--contrib/fuzzystrmatch/fuzzystrmatch--unpackaged--1.0.sql20
-rw-r--r--contrib/fuzzystrmatch/fuzzystrmatch.c167
-rw-r--r--contrib/fuzzystrmatch/fuzzystrmatch.control5
-rw-r--r--contrib/fuzzystrmatch/fuzzystrmatch.sql.in36
-rw-r--r--contrib/fuzzystrmatch/levenshtein.c403
-rw-r--r--contrib/fuzzystrmatch/uninstall_fuzzystrmatch.sql20
-rw-r--r--contrib/hstore/.gitignore4
-rw-r--r--contrib/hstore/Makefile20
-rw-r--r--contrib/hstore/crc32.c2
-rw-r--r--contrib/hstore/crc32.h2
-rw-r--r--contrib/hstore/expected/hstore.out22
-rw-r--r--contrib/hstore/hstore--1.0.sql (renamed from contrib/hstore/hstore.sql.in)109
-rw-r--r--contrib/hstore/hstore--unpackaged--1.0.sql89
-rw-r--r--contrib/hstore/hstore.control5
-rw-r--r--contrib/hstore/hstore.h2
-rw-r--r--contrib/hstore/hstore_compat.c5
-rw-r--r--contrib/hstore/hstore_gin.c115
-rw-r--r--contrib/hstore/hstore_gist.c26
-rw-r--r--contrib/hstore/hstore_io.c10
-rw-r--r--contrib/hstore/hstore_op.c42
-rw-r--r--contrib/hstore/sql/hstore.sql20
-rw-r--r--contrib/hstore/uninstall_hstore.sql86
-rw-r--r--contrib/intagg/Makefile5
-rw-r--r--contrib/intagg/intagg--1.0.sql (renamed from contrib/intagg/int_aggregate.sql)11
-rw-r--r--contrib/intagg/intagg--unpackaged--1.0.sql6
-rw-r--r--contrib/intagg/intagg.control4
-rw-r--r--contrib/intagg/uninstall_int_aggregate.sql12
-rw-r--r--contrib/intarray/.gitignore4
-rw-r--r--contrib/intarray/Makefile10
-rw-r--r--contrib/intarray/_int.h82
-rw-r--r--contrib/intarray/_int_bool.c319
-rw-r--r--contrib/intarray/_int_gin.c123
-rw-r--r--contrib/intarray/_int_gist.c33
-rw-r--r--contrib/intarray/_int_op.c111
-rw-r--r--contrib/intarray/_int_tool.c117
-rw-r--r--contrib/intarray/_intbig_gist.c19
-rwxr-xr-xcontrib/intarray/bench/bench.pl23
-rwxr-xr-xcontrib/intarray/bench/create_test.pl6
-rw-r--r--contrib/intarray/expected/_int.out8
-rw-r--r--contrib/intarray/intarray--1.0.sql (renamed from contrib/intarray/_int.sql.in)101
-rw-r--r--contrib/intarray/intarray--unpackaged--1.0.sql108
-rw-r--r--contrib/intarray/intarray.control5
-rw-r--r--contrib/intarray/sql/_int.sql10
-rw-r--r--contrib/intarray/uninstall__int.sql128
-rw-r--r--contrib/isn/EAN13.h2
-rw-r--r--contrib/isn/ISBN.h376
-rw-r--r--contrib/isn/ISMN.h2
-rw-r--r--contrib/isn/ISSN.h2
-rw-r--r--contrib/isn/Makefile7
-rw-r--r--contrib/isn/UPC.h2
-rw-r--r--contrib/isn/isn--1.0.sql (renamed from contrib/isn/isn.sql.in)495
-rw-r--r--contrib/isn/isn--unpackaged--1.0.sql461
-rw-r--r--contrib/isn/isn.c23
-rw-r--r--contrib/isn/isn.control5
-rw-r--r--contrib/isn/isn.h4
-rw-r--r--contrib/isn/uninstall_isn.sql24
-rw-r--r--contrib/lo/Makefile7
-rw-r--r--contrib/lo/lo--1.0.sql (renamed from contrib/lo/lo.sql.in)9
-rw-r--r--contrib/lo/lo--unpackaged--1.0.sql5
-rw-r--r--contrib/lo/lo.c2
-rw-r--r--contrib/lo/lo.control5
-rw-r--r--contrib/lo/lo_test.sql2
-rw-r--r--contrib/lo/uninstall_lo.sql17
-rw-r--r--contrib/ltree/.gitignore4
-rw-r--r--contrib/ltree/Makefile10
-rw-r--r--contrib/ltree/_ltree_gist.c6
-rw-r--r--contrib/ltree/_ltree_op.c8
-rw-r--r--contrib/ltree/crc32.c2
-rw-r--r--contrib/ltree/crc32.h2
-rw-r--r--contrib/ltree/expected/ltree.out8
-rw-r--r--contrib/ltree/lquery_op.c9
-rw-r--r--contrib/ltree/ltree--1.0.sql (renamed from contrib/ltree/ltree.sql.in)151
-rw-r--r--contrib/ltree/ltree--unpackaged--1.0.sql131
-rw-r--r--contrib/ltree/ltree.control5
-rw-r--r--contrib/ltree/ltree.h2
-rw-r--r--contrib/ltree/ltree_gist.c6
-rw-r--r--contrib/ltree/ltree_io.c2
-rw-r--r--contrib/ltree/ltree_op.c10
-rw-r--r--contrib/ltree/ltreetest.sql2
-rw-r--r--contrib/ltree/ltxtquery_io.c6
-rw-r--r--contrib/ltree/ltxtquery_op.c2
-rw-r--r--contrib/ltree/sql/ltree.sql11
-rw-r--r--contrib/ltree/uninstall_ltree.sql240
-rw-r--r--contrib/oid2name/.gitignore1
-rw-r--r--contrib/oid2name/Makefile4
-rw-r--r--contrib/oid2name/oid2name.c2
-rw-r--r--contrib/pageinspect/Makefile14
-rw-r--r--contrib/pageinspect/btreefuncs.c2
-rw-r--r--contrib/pageinspect/fsmfuncs.c6
-rw-r--r--contrib/pageinspect/heapfuncs.c8
-rw-r--r--contrib/pageinspect/pageinspect--1.0.sql (renamed from contrib/pageinspect/pageinspect.sql.in)25
-rw-r--r--contrib/pageinspect/pageinspect--unpackaged--1.0.sql28
-rw-r--r--contrib/pageinspect/pageinspect.control5
-rw-r--r--contrib/pageinspect/rawpage.c9
-rw-r--r--contrib/pageinspect/uninstall_pageinspect.sql13
-rw-r--r--contrib/passwordcheck/Makefile2
-rw-r--r--contrib/passwordcheck/passwordcheck.c4
-rw-r--r--contrib/pg_archivecleanup/.gitignore1
-rw-r--r--contrib/pg_archivecleanup/Makefile4
-rw-r--r--contrib/pg_archivecleanup/pg_archivecleanup.c34
-rw-r--r--contrib/pg_buffercache/Makefile8
-rw-r--r--contrib/pg_buffercache/pg_buffercache--1.0.sql (renamed from contrib/pg_buffercache/pg_buffercache.sql.in)13
-rw-r--r--contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql4
-rw-r--r--contrib/pg_buffercache/pg_buffercache.control5
-rw-r--r--contrib/pg_buffercache/pg_buffercache_pages.c2
-rw-r--r--contrib/pg_buffercache/uninstall_pg_buffercache.sql8
-rw-r--r--contrib/pg_freespacemap/Makefile8
-rw-r--r--contrib/pg_freespacemap/pg_freespacemap--1.0.sql (renamed from contrib/pg_freespacemap/pg_freespacemap.sql.in)10
-rw-r--r--contrib/pg_freespacemap/pg_freespacemap--unpackaged--1.0.sql4
-rw-r--r--contrib/pg_freespacemap/pg_freespacemap.c2
-rw-r--r--contrib/pg_freespacemap/pg_freespacemap.control5
-rw-r--r--contrib/pg_freespacemap/uninstall_pg_freespacemap.sql7
-rw-r--r--contrib/pg_standby/.gitignore1
-rw-r--r--contrib/pg_standby/Makefile4
-rw-r--r--contrib/pg_standby/pg_standby.c34
-rw-r--r--contrib/pg_stat_statements/Makefile7
-rw-r--r--contrib/pg_stat_statements/pg_stat_statements--1.0.sql (renamed from contrib/pg_stat_statements/pg_stat_statements.sql.in)5
-rw-r--r--contrib/pg_stat_statements/pg_stat_statements--unpackaged--1.0.sql5
-rw-r--r--contrib/pg_stat_statements/pg_stat_statements.c38
-rw-r--r--contrib/pg_stat_statements/pg_stat_statements.control5
-rw-r--r--contrib/pg_stat_statements/uninstall_pg_stat_statements.sql8
-rw-r--r--contrib/pg_test_fsync/.gitignore1
-rw-r--r--contrib/pg_test_fsync/Makefile18
-rw-r--r--contrib/pg_test_fsync/pg_test_fsync.c527
-rw-r--r--contrib/pg_trgm/.gitignore4
-rw-r--r--contrib/pg_trgm/Makefile7
-rw-r--r--contrib/pg_trgm/expected/pg_trgm.out121
-rw-r--r--contrib/pg_trgm/pg_trgm--1.0.sql163
-rw-r--r--contrib/pg_trgm/pg_trgm--unpackaged--1.0.sql95
-rw-r--r--contrib/pg_trgm/pg_trgm.control5
-rw-r--r--contrib/pg_trgm/pg_trgm.sql.in132
-rw-r--r--contrib/pg_trgm/sql/pg_trgm.sql38
-rw-r--r--contrib/pg_trgm/trgm.h31
-rw-r--r--contrib/pg_trgm/trgm_gin.c165
-rw-r--r--contrib/pg_trgm/trgm_gist.c225
-rw-r--r--contrib/pg_trgm/trgm_op.c311
-rw-r--r--contrib/pg_trgm/uninstall_pg_trgm.sql42
-rw-r--r--contrib/pg_upgrade/.gitignore1
-rw-r--r--contrib/pg_upgrade/IMPLEMENTATION4
-rw-r--r--contrib/pg_upgrade/Makefile5
-rw-r--r--contrib/pg_upgrade/TESTING27
-rw-r--r--contrib/pg_upgrade/check.c540
-rw-r--r--contrib/pg_upgrade/controldata.c251
-rw-r--r--contrib/pg_upgrade/dump.c35
-rw-r--r--contrib/pg_upgrade/exec.c339
-rw-r--r--contrib/pg_upgrade/file.c145
-rw-r--r--contrib/pg_upgrade/function.c208
-rw-r--r--contrib/pg_upgrade/info.c485
-rw-r--r--contrib/pg_upgrade/option.c231
-rw-r--r--contrib/pg_upgrade/page.c33
-rw-r--r--contrib/pg_upgrade/pg_upgrade.c356
-rw-r--r--contrib/pg_upgrade/pg_upgrade.h249
-rw-r--r--contrib/pg_upgrade/relfilenode.c188
-rw-r--r--contrib/pg_upgrade/server.c349
-rw-r--r--contrib/pg_upgrade/tablespace.c52
-rw-r--r--contrib/pg_upgrade/util.c144
-rw-r--r--contrib/pg_upgrade/version.c40
-rw-r--r--contrib/pg_upgrade/version_old_8_3.c342
-rw-r--r--contrib/pg_upgrade_support/Makefile5
-rw-r--r--contrib/pg_upgrade_support/pg_upgrade_support.c167
-rw-r--r--contrib/pgbench/.gitignore1
-rw-r--r--contrib/pgbench/Makefile4
-rw-r--r--contrib/pgbench/pgbench.c434
-rw-r--r--contrib/pgcrypto/.gitignore4
-rw-r--r--contrib/pgcrypto/Makefile11
-rw-r--r--contrib/pgcrypto/blf.c2
-rw-r--r--contrib/pgcrypto/blf.h2
-rw-r--r--contrib/pgcrypto/crypt-blowfish.c2
-rw-r--r--contrib/pgcrypto/crypt-des.c2
-rw-r--r--contrib/pgcrypto/crypt-gensalt.c2
-rw-r--r--contrib/pgcrypto/crypt-md5.c2
-rw-r--r--contrib/pgcrypto/expected/blowfish.out8
-rw-r--r--contrib/pgcrypto/expected/crypt-blowfish.out2
-rw-r--r--contrib/pgcrypto/expected/init.out8
-rw-r--r--contrib/pgcrypto/expected/rijndael.out8
-rw-r--r--contrib/pgcrypto/fortuna.c2
-rw-r--r--contrib/pgcrypto/fortuna.h2
-rw-r--r--contrib/pgcrypto/imath.c2
-rw-r--r--contrib/pgcrypto/imath.h2
-rw-r--r--contrib/pgcrypto/internal-sha2.c2
-rw-r--r--contrib/pgcrypto/internal.c2
-rw-r--r--contrib/pgcrypto/mbuf.c2
-rw-r--r--contrib/pgcrypto/mbuf.h2
-rw-r--r--contrib/pgcrypto/md5.c2
-rw-r--r--contrib/pgcrypto/md5.h2
-rw-r--r--contrib/pgcrypto/openssl.c2
-rw-r--r--contrib/pgcrypto/pgcrypto--1.0.sql (renamed from contrib/pgcrypto/pgcrypto.sql.in)72
-rw-r--r--contrib/pgcrypto/pgcrypto--unpackaged--1.0.sql35
-rw-r--r--contrib/pgcrypto/pgcrypto.c2
-rw-r--r--contrib/pgcrypto/pgcrypto.control5
-rw-r--r--contrib/pgcrypto/pgcrypto.h2
-rw-r--r--contrib/pgcrypto/pgp-armor.c2
-rw-r--r--contrib/pgcrypto/pgp-cfb.c2
-rw-r--r--contrib/pgcrypto/pgp-compress.c2
-rw-r--r--contrib/pgcrypto/pgp-decrypt.c2
-rw-r--r--contrib/pgcrypto/pgp-encrypt.c2
-rw-r--r--contrib/pgcrypto/pgp-info.c2
-rw-r--r--contrib/pgcrypto/pgp-mpi-internal.c2
-rw-r--r--contrib/pgcrypto/pgp-mpi-openssl.c2
-rw-r--r--contrib/pgcrypto/pgp-mpi.c2
-rw-r--r--contrib/pgcrypto/pgp-pgsql.c2
-rw-r--r--contrib/pgcrypto/pgp-pubdec.c2
-rw-r--r--contrib/pgcrypto/pgp-pubenc.c6
-rw-r--r--contrib/pgcrypto/pgp-pubkey.c2
-rw-r--r--contrib/pgcrypto/pgp-s2k.c14
-rw-r--r--contrib/pgcrypto/pgp.c2
-rw-r--r--contrib/pgcrypto/pgp.h2
-rw-r--r--contrib/pgcrypto/px-crypt.c2
-rw-r--r--contrib/pgcrypto/px-crypt.h2
-rw-r--r--contrib/pgcrypto/px-hmac.c4
-rw-r--r--contrib/pgcrypto/px.c8
-rw-r--r--contrib/pgcrypto/px.h2
-rw-r--r--contrib/pgcrypto/random.c2
-rw-r--r--contrib/pgcrypto/rijndael.c2
-rw-r--r--contrib/pgcrypto/rijndael.h2
-rw-r--r--contrib/pgcrypto/rijndael.tbl3
-rw-r--r--contrib/pgcrypto/sha1.c2
-rw-r--r--contrib/pgcrypto/sha1.h2
-rw-r--r--contrib/pgcrypto/sha2.c2
-rw-r--r--contrib/pgcrypto/sha2.h2
-rw-r--r--contrib/pgcrypto/sql/3des.sql1
-rw-r--r--contrib/pgcrypto/sql/blowfish.sql9
-rw-r--r--contrib/pgcrypto/sql/cast5.sql1
-rw-r--r--contrib/pgcrypto/sql/crypt-blowfish.sql3
-rw-r--r--contrib/pgcrypto/sql/crypt-des.sql1
-rw-r--r--contrib/pgcrypto/sql/crypt-md5.sql1
-rw-r--r--contrib/pgcrypto/sql/crypt-xdes.sql1
-rw-r--r--contrib/pgcrypto/sql/des.sql1
-rw-r--r--contrib/pgcrypto/sql/hmac-md5.sql2
-rw-r--r--contrib/pgcrypto/sql/hmac-sha1.sql2
-rw-r--r--contrib/pgcrypto/sql/init.sql11
-rw-r--r--contrib/pgcrypto/sql/md5.sql1
-rw-r--r--contrib/pgcrypto/sql/pgp-compression.sql1
-rw-r--r--contrib/pgcrypto/sql/pgp-encrypt-DISABLED.sql2
-rw-r--r--contrib/pgcrypto/sql/pgp-encrypt.sql1
-rw-r--r--contrib/pgcrypto/sql/pgp-info.sql1
-rw-r--r--contrib/pgcrypto/sql/pgp-pubkey-DISABLED.sql2
-rw-r--r--contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql1
-rw-r--r--contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql2
-rw-r--r--contrib/pgcrypto/sql/pgp-zlib-DISABLED.sql2
-rw-r--r--contrib/pgcrypto/sql/rijndael.sql9
-rw-r--r--contrib/pgcrypto/sql/sha1.sql1
-rw-r--r--contrib/pgcrypto/sql/sha2.sql2
-rw-r--r--contrib/pgcrypto/uninstall_pgcrypto.sql46
-rw-r--r--contrib/pgrowlocks/Makefile13
-rw-r--r--contrib/pgrowlocks/pgrowlocks--1.0.sql (renamed from contrib/pgrowlocks/pgrowlocks.sql.in)7
-rw-r--r--contrib/pgrowlocks/pgrowlocks--unpackaged--1.0.sql3
-rw-r--r--contrib/pgrowlocks/pgrowlocks.c2
-rw-r--r--contrib/pgrowlocks/pgrowlocks.control5
-rw-r--r--contrib/pgrowlocks/uninstall_pgrowlocks.sql6
-rw-r--r--contrib/pgstattuple/Makefile13
-rw-r--r--contrib/pgstattuple/pgstatindex.c2
-rw-r--r--contrib/pgstattuple/pgstattuple--1.0.sql (renamed from contrib/pgstattuple/pgstattuple.sql.in)13
-rw-r--r--contrib/pgstattuple/pgstattuple--unpackaged--1.0.sql6
-rw-r--r--contrib/pgstattuple/pgstattuple.c5
-rw-r--r--contrib/pgstattuple/pgstattuple.control5
-rw-r--r--contrib/pgstattuple/uninstall_pgstattuple.sql9
-rw-r--r--contrib/seg/.cvsignore2
-rw-r--r--contrib/seg/.gitignore6
-rw-r--r--contrib/seg/Makefile8
-rw-r--r--contrib/seg/expected/seg.out12
-rw-r--r--contrib/seg/expected/seg_1.out12
-rw-r--r--contrib/seg/seg--1.0.sql (renamed from contrib/seg/seg.sql.in)74
-rw-r--r--contrib/seg/seg--unpackaged--1.0.sql51
-rw-r--r--contrib/seg/seg.c199
-rw-r--r--contrib/seg/seg.control5
-rw-r--r--contrib/seg/segdata.h2
-rw-r--r--contrib/seg/segparse.y6
-rw-r--r--contrib/seg/segscan.l6
-rwxr-xr-xcontrib/seg/sort-segments.pl2
-rw-r--r--contrib/seg/sql/seg.sql14
-rw-r--r--contrib/seg/uninstall_seg.sql94
-rw-r--r--contrib/sepgsql/.gitignore7
-rw-r--r--contrib/sepgsql/Makefile22
-rw-r--r--contrib/sepgsql/dml.c367
-rw-r--r--contrib/sepgsql/expected/dml.out183
-rw-r--r--contrib/sepgsql/expected/label.out117
-rw-r--r--contrib/sepgsql/expected/misc.out5
-rw-r--r--contrib/sepgsql/hooks.c462
-rw-r--r--contrib/sepgsql/label.c528
-rwxr-xr-xcontrib/sepgsql/launcher52
-rw-r--r--contrib/sepgsql/proc.c159
-rw-r--r--contrib/sepgsql/relation.c276
-rw-r--r--contrib/sepgsql/schema.c99
-rw-r--r--contrib/sepgsql/selinux.c939
-rw-r--r--contrib/sepgsql/sepgsql-regtest.te85
-rw-r--r--contrib/sepgsql/sepgsql.h291
-rw-r--r--contrib/sepgsql/sepgsql.sql.in36
-rw-r--r--contrib/sepgsql/sql/dml.sql119
-rw-r--r--contrib/sepgsql/sql/label.sql81
-rw-r--r--contrib/sepgsql/sql/misc.sql5
-rw-r--r--contrib/spi/Makefile12
-rw-r--r--contrib/spi/autoinc--1.0.sql6
-rw-r--r--contrib/spi/autoinc--unpackaged--1.0.sql3
-rw-r--r--contrib/spi/autoinc.c8
-rw-r--r--contrib/spi/autoinc.control5
-rw-r--r--contrib/spi/autoinc.example10
-rw-r--r--contrib/spi/autoinc.sql.in9
-rw-r--r--contrib/spi/insert_username--1.0.sql6
-rw-r--r--contrib/spi/insert_username--unpackaged--1.0.sql3
-rw-r--r--contrib/spi/insert_username.c8
-rw-r--r--contrib/spi/insert_username.control5
-rw-r--r--contrib/spi/insert_username.example3
-rw-r--r--contrib/spi/insert_username.sql.in9
-rw-r--r--contrib/spi/moddatetime--1.0.sql6
-rw-r--r--contrib/spi/moddatetime--unpackaged--1.0.sql3
-rw-r--r--contrib/spi/moddatetime.c46
-rw-r--r--contrib/spi/moddatetime.control5
-rw-r--r--contrib/spi/moddatetime.example2
-rw-r--r--contrib/spi/moddatetime.sql.in9
-rw-r--r--contrib/spi/refint--1.0.sql11
-rw-r--r--contrib/spi/refint--unpackaged--1.0.sql4
-rw-r--r--contrib/spi/refint.c10
-rw-r--r--contrib/spi/refint.control5
-rw-r--r--contrib/spi/refint.example10
-rw-r--r--contrib/spi/refint.sql.in14
-rw-r--r--contrib/spi/timetravel--1.0.sql16
-rw-r--r--contrib/spi/timetravel--unpackaged--1.0.sql5
-rw-r--r--contrib/spi/timetravel.c10
-rw-r--r--contrib/spi/timetravel.control5
-rw-r--r--contrib/spi/timetravel.example18
-rw-r--r--contrib/spi/timetravel.sql.in19
-rw-r--r--contrib/sslinfo/Makefile7
-rw-r--r--contrib/sslinfo/sslinfo--1.0.sql37
-rw-r--r--contrib/sslinfo/sslinfo--unpackaged--1.0.sql19
-rw-r--r--contrib/sslinfo/sslinfo.c30
-rw-r--r--contrib/sslinfo/sslinfo.control5
-rw-r--r--contrib/sslinfo/sslinfo.sql.in32
-rw-r--r--contrib/sslinfo/uninstall_sslinfo.sql12
-rw-r--r--contrib/start-scripts/freebsd2
-rw-r--r--contrib/start-scripts/linux2
-rwxr-xr-xcontrib/start-scripts/osx/PostgreSQL4
-rw-r--r--contrib/tablefunc/.gitignore4
-rw-r--r--contrib/tablefunc/Makefile8
-rw-r--r--contrib/tablefunc/expected/tablefunc.out8
-rw-r--r--contrib/tablefunc/sql/tablefunc.sql11
-rw-r--r--contrib/tablefunc/tablefunc--1.0.sql (renamed from contrib/tablefunc/tablefunc.sql.in)27
-rw-r--r--contrib/tablefunc/tablefunc--unpackaged--1.0.sql16
-rw-r--r--contrib/tablefunc/tablefunc.c24
-rw-r--r--contrib/tablefunc/tablefunc.control5
-rw-r--r--contrib/tablefunc/tablefunc.h4
-rw-r--r--contrib/tablefunc/uninstall_tablefunc.sql32
-rw-r--r--contrib/test_parser/.gitignore4
-rw-r--r--contrib/test_parser/Makefile8
-rw-r--r--contrib/test_parser/expected/test_parser.out10
-rw-r--r--contrib/test_parser/sql/test_parser.sql12
-rw-r--r--contrib/test_parser/test_parser--1.0.sql (renamed from contrib/test_parser/test_parser.sql.in)13
-rw-r--r--contrib/test_parser/test_parser--unpackaged--1.0.sql7
-rw-r--r--contrib/test_parser/test_parser.c4
-rw-r--r--contrib/test_parser/test_parser.control5
-rw-r--r--contrib/test_parser/uninstall_test_parser.sql14
-rw-r--r--contrib/tsearch2/.gitignore4
-rw-r--r--contrib/tsearch2/Makefile8
-rw-r--r--contrib/tsearch2/expected/tsearch2.out16
-rw-r--r--contrib/tsearch2/expected/tsearch2_1.out16
-rw-r--r--contrib/tsearch2/sql/tsearch2.sql21
-rw-r--r--contrib/tsearch2/tsearch2--1.0.sql (renamed from contrib/tsearch2/tsearch2.sql.in)59
-rw-r--r--contrib/tsearch2/tsearch2--unpackaged--1.0.sql141
-rw-r--r--contrib/tsearch2/tsearch2.c10
-rw-r--r--contrib/tsearch2/tsearch2.control7
-rw-r--r--contrib/tsearch2/uninstall_tsearch2.sql96
-rw-r--r--contrib/unaccent/.gitignore4
-rw-r--r--contrib/unaccent/Makefile12
-rw-r--r--contrib/unaccent/expected/unaccent.out4
-rw-r--r--contrib/unaccent/sql/unaccent.sql6
-rw-r--r--contrib/unaccent/unaccent--1.0.sql31
-rw-r--r--contrib/unaccent/unaccent--unpackaged--1.0.sql13
-rw-r--r--contrib/unaccent/unaccent.c6
-rw-r--r--contrib/unaccent/unaccent.control5
-rw-r--r--contrib/unaccent/unaccent.sql.in34
-rw-r--r--contrib/unaccent/uninstall_unaccent.sql11
-rw-r--r--contrib/uuid-ossp/Makefile7
-rw-r--r--contrib/uuid-ossp/uninstall_uuid-ossp.sql16
-rw-r--r--contrib/uuid-ossp/uuid-ossp--1.0.sql (renamed from contrib/uuid-ossp/uuid-ossp.sql.in)25
-rw-r--r--contrib/uuid-ossp/uuid-ossp--unpackaged--1.0.sql12
-rw-r--r--contrib/uuid-ossp/uuid-ossp.c4
-rw-r--r--contrib/uuid-ossp/uuid-ossp.control5
-rw-r--r--contrib/vacuumlo/.gitignore1
-rw-r--r--contrib/vacuumlo/Makefile4
-rw-r--r--contrib/vacuumlo/vacuumlo.c4
-rw-r--r--contrib/xml2/.gitignore4
-rw-r--r--contrib/xml2/Makefile10
-rw-r--r--contrib/xml2/expected/xml2.out78
-rw-r--r--contrib/xml2/expected/xml2_1.out60
-rw-r--r--contrib/xml2/pgxml.sql.in77
-rw-r--r--contrib/xml2/sql/xml2.sql62
-rw-r--r--contrib/xml2/uninstall_pgxml.sql33
-rw-r--r--contrib/xml2/xml2--1.0.sql70
-rw-r--r--contrib/xml2/xml2--unpackaged--1.0.sql26
-rw-r--r--contrib/xml2/xml2.control6
-rw-r--r--contrib/xml2/xpath.c173
-rw-r--r--contrib/xml2/xslt_proc.c52
582 files changed, 17630 insertions, 7741 deletions
diff --git a/contrib/Makefile b/contrib/Makefile
index a1b7d913f5..696776795e 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/contrib/Makefile,v 1.93 2010/06/14 16:17:56 sriggs Exp $
+# contrib/Makefile
subdir = contrib
top_builddir = ..
@@ -6,6 +6,7 @@ include $(top_builddir)/src/Makefile.global
SUBDIRS = \
adminpack \
+ auth_delay \
auto_explain \
btree_gin \
btree_gist \
@@ -15,7 +16,9 @@ SUBDIRS = \
dblink \
dict_int \
dict_xsyn \
+ dummy_seclabel \
earthdistance \
+ file_fdw \
fuzzystrmatch \
hstore \
intagg \
@@ -31,6 +34,7 @@ SUBDIRS = \
pg_freespacemap \
pg_standby \
pg_stat_statements \
+ pg_test_fsync \
pg_trgm \
pg_upgrade \
pg_upgrade_support \
@@ -58,18 +62,12 @@ ifeq ($(with_libxml),yes)
SUBDIRS += xml2
endif
+ifeq ($(with_selinux),yes)
+SUBDIRS += sepgsql
+endif
+
# Missing:
# start-scripts \ (does not have a makefile)
-all install installdirs uninstall distprep clean distclean maintainer-clean:
- @for dir in $(SUBDIRS); do \
- $(MAKE) -C $$dir $@ || exit; \
- done
-
-# We'd like check operations to run all the subtests before failing.
-check installcheck:
- @CHECKERR=0; for dir in $(SUBDIRS); do \
- $(MAKE) -C $$dir $@ || CHECKERR=$$?; \
- done; \
- exit $$CHECKERR
+$(recurse)
diff --git a/contrib/README b/contrib/README
index a04c04346e..a1d42a11cb 100644
--- a/contrib/README
+++ b/contrib/README
@@ -28,6 +28,11 @@ adminpack -
File and log manipulation routines, used by pgAdmin
by Dave Page <dpage@vale-housing.co.uk>
+auth_delay
+ Add a short delay after a failed authentication attempt, to make
+ brute-force attacks on database passwords a bit harder.
+ by KaiGai Kohei <kaigai@ak.jp.nec.com>
+
auto_explain -
Log EXPLAIN output for long-running queries
by Takahiro Itagaki <itagaki.takahiro@oss.ntt.co.jp>
@@ -66,7 +71,11 @@ dict_xsyn -
earthdistance -
Functions for computing distances between two points on Earth
- by Bruno Wolff III <bruno@wolff.to> and Hal Snyder <hal@vailsys.com>
+ by Bruno Wolff III <bruno@wolff.to> and Hal Snyder <hal@vailsys.com>
+
+file_fdw
+ Foreign-data wrapper for server-side CSV/TEXT files
+ by Shigeru Hanada <hanada@metrosystems.co.jp>
fuzzystrmatch -
Levenshtein, metaphone, and soundex fuzzy string matching
@@ -86,17 +95,17 @@ intarray -
isn -
PostgreSQL type extensions for ISBN, ISSN, ISMN, EAN13 product numbers
- by Germán Méndez Bravo (Kronuz) <kronuz@hotmail.com>
+ by Germán Méndez Bravo (Kronuz) <kronuz@hotmail.com>
lo -
Large Object maintenance
- by Peter Mount <peter@retep.org.uk>
+ by Peter Mount <peter@retep.org.uk>
ltree -
Tree-like data structures
by Teodor Sigaev <teodor@sigaev.ru> and Oleg Bartunov <oleg@sai.msu.su>
-oid2name -
+oid2name -
Maps numeric files to table names
by B Palmer <bpalmer@crimelabs.net>
@@ -124,6 +133,10 @@ pg_stat_statements -
Track statement execution times across a whole database cluster
by Takahiro Itagaki <itagaki.takahiro@oss.ntt.co.jp>
+pg_test_fsync -
+ Test different wal_sync_method settings
+ by Bruce Momjian <bruce@momjian.us>
+
pg_trgm -
Functions for determining the similarity of text based on trigram
matching.
@@ -154,6 +167,10 @@ seg -
Confidence-interval datatype (GiST indexing example)
by Gene Selkov, Jr. <selkovjr@mcs.anl.gov>
+sepgsql -
+ External security provider using SELinux
+ by KaiGai Kohei <kaigai@ak.jp.nec.com>
+
spi -
Various trigger functions, examples for using SPI.
@@ -161,7 +178,7 @@ sslinfo -
Functions to get information about SSL certificates
by Victor Wagner <vitus@cryptocom.ru>
-start-scripts -
+start-scripts -
Scripts for starting the server at boot time on various platforms.
tablefunc -
diff --git a/contrib/adminpack/Makefile b/contrib/adminpack/Makefile
index e1262fb2e9..5cbc8f0c71 100644
--- a/contrib/adminpack/Makefile
+++ b/contrib/adminpack/Makefile
@@ -1,10 +1,11 @@
-# $PostgreSQL: pgsql/contrib/adminpack/Makefile,v 1.6 2007/11/10 23:59:50 momjian Exp $
+# contrib/adminpack/Makefile
MODULE_big = adminpack
-PG_CPPFLAGS = -I$(libpq_srcdir)
-DATA_built = adminpack.sql
-DATA = uninstall_adminpack.sql
OBJS = adminpack.o
+PG_CPPFLAGS = -I$(libpq_srcdir)
+
+EXTENSION = adminpack
+DATA = adminpack--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/adminpack/adminpack.sql.in b/contrib/adminpack/adminpack--1.0.sql
index de29bacd51..090702231c 100644
--- a/contrib/adminpack/adminpack.sql.in
+++ b/contrib/adminpack/adminpack--1.0.sql
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/adminpack/adminpack.sql.in,v 1.6 2007/11/13 04:24:27 momjian Exp $ */
+/* contrib/adminpack/adminpack--1.0.sql */
/* ***********************************************
* Administrative functions for PostgreSQL
@@ -6,27 +6,27 @@
/* generic file access functions */
-CREATE OR REPLACE FUNCTION pg_catalog.pg_file_write(text, text, bool)
+CREATE FUNCTION pg_catalog.pg_file_write(text, text, bool)
RETURNS bigint
AS 'MODULE_PATHNAME', 'pg_file_write'
LANGUAGE C VOLATILE STRICT;
-CREATE OR REPLACE FUNCTION pg_catalog.pg_file_rename(text, text, text)
+CREATE FUNCTION pg_catalog.pg_file_rename(text, text, text)
RETURNS bool
AS 'MODULE_PATHNAME', 'pg_file_rename'
LANGUAGE C VOLATILE;
-CREATE OR REPLACE FUNCTION pg_catalog.pg_file_rename(text, text)
+CREATE FUNCTION pg_catalog.pg_file_rename(text, text)
RETURNS bool
AS 'SELECT pg_catalog.pg_file_rename($1, $2, NULL::pg_catalog.text);'
LANGUAGE SQL VOLATILE STRICT;
-CREATE OR REPLACE FUNCTION pg_catalog.pg_file_unlink(text)
+CREATE FUNCTION pg_catalog.pg_file_unlink(text)
RETURNS bool
AS 'MODULE_PATHNAME', 'pg_file_unlink'
LANGUAGE C VOLATILE STRICT;
-CREATE OR REPLACE FUNCTION pg_catalog.pg_logdir_ls()
+CREATE FUNCTION pg_catalog.pg_logdir_ls()
RETURNS setof record
AS 'MODULE_PATHNAME', 'pg_logdir_ls'
LANGUAGE C VOLATILE STRICT;
@@ -34,17 +34,17 @@ LANGUAGE C VOLATILE STRICT;
/* Renaming of existing backend functions for pgAdmin compatibility */
-CREATE OR REPLACE FUNCTION pg_catalog.pg_file_read(text, bigint, bigint)
+CREATE FUNCTION pg_catalog.pg_file_read(text, bigint, bigint)
RETURNS text
AS 'pg_read_file'
LANGUAGE INTERNAL VOLATILE STRICT;
-CREATE OR REPLACE FUNCTION pg_catalog.pg_file_length(text)
+CREATE FUNCTION pg_catalog.pg_file_length(text)
RETURNS bigint
AS 'SELECT size FROM pg_catalog.pg_stat_file($1)'
LANGUAGE SQL VOLATILE STRICT;
-CREATE OR REPLACE FUNCTION pg_catalog.pg_logfile_rotate()
+CREATE FUNCTION pg_catalog.pg_logfile_rotate()
RETURNS int4
AS 'pg_rotate_logfile'
LANGUAGE INTERNAL VOLATILE STRICT;
diff --git a/contrib/adminpack/adminpack.c b/contrib/adminpack/adminpack.c
index 5271ef6ea2..99fa02e813 100644
--- a/contrib/adminpack/adminpack.c
+++ b/contrib/adminpack/adminpack.c
@@ -3,12 +3,12 @@
* adminpack.c
*
*
- * Copyright (c) 2002-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2002-2011, PostgreSQL Global Development Group
*
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.13 2010/01/02 16:57:32 momjian Exp $
+ * contrib/adminpack/adminpack.c
*
*-------------------------------------------------------------------------
*/
@@ -73,32 +73,31 @@ convert_and_check_filename(text *arg, bool logAllowed)
canonicalize_path(filename); /* filename can change length here */
- /* Disallow ".." in the path */
- if (path_contains_parent_reference(filename))
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("reference to parent directory (\"..\") not allowed"))));
-
if (is_absolute_path(filename))
{
- /* Allow absolute references within DataDir */
- if (path_is_prefix_of_path(DataDir, filename))
- return filename;
- /* The log directory might be outside our datadir, but allow it */
- if (logAllowed &&
- is_absolute_path(Log_directory) &&
- path_is_prefix_of_path(Log_directory, filename))
- return filename;
+ /* Disallow '/a/b/data/..' */
+ if (path_contains_parent_reference(filename))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("reference to parent directory (\"..\") not allowed"))));
+ /*
+ * Allow absolute paths if within DataDir or Log_directory, even
+ * though Log_directory might be outside DataDir.
+ */
+ if (!path_is_prefix_of_path(DataDir, filename) &&
+ (!logAllowed || !is_absolute_path(Log_directory) ||
+ !path_is_prefix_of_path(Log_directory, filename)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("absolute path not allowed"))));
+ }
+ else if (!path_is_relative_and_below_cwd(filename))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("absolute path not allowed"))));
- return NULL; /* keep compiler quiet */
- }
- else
- {
- return filename;
- }
+ (errmsg("path must be in or below the current directory"))));
+
+ return filename;
}
diff --git a/contrib/adminpack/adminpack.control b/contrib/adminpack/adminpack.control
new file mode 100644
index 0000000000..c79413f378
--- /dev/null
+++ b/contrib/adminpack/adminpack.control
@@ -0,0 +1,6 @@
+# adminpack extension
+comment = 'administrative functions for PostgreSQL'
+default_version = '1.0'
+module_pathname = '$libdir/adminpack'
+relocatable = false
+schema = pg_catalog
diff --git a/contrib/adminpack/uninstall_adminpack.sql b/contrib/adminpack/uninstall_adminpack.sql
deleted file mode 100644
index 893f081461..0000000000
--- a/contrib/adminpack/uninstall_adminpack.sql
+++ /dev/null
@@ -1,10 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/adminpack/uninstall_adminpack.sql,v 1.4 2007/11/13 04:24:27 momjian Exp $ */
-
-DROP FUNCTION pg_catalog.pg_file_write(text, text, bool) ;
-DROP FUNCTION pg_catalog.pg_file_rename(text, text, text) ;
-DROP FUNCTION pg_catalog.pg_file_rename(text, text) ;
-DROP FUNCTION pg_catalog.pg_file_unlink(text) ;
-DROP FUNCTION pg_catalog.pg_logdir_ls() ;
-DROP FUNCTION pg_catalog.pg_file_read(text, bigint, bigint) ;
-DROP FUNCTION pg_catalog.pg_file_length(text) ;
-DROP FUNCTION pg_catalog.pg_logfile_rotate() ;
diff --git a/contrib/auth_delay/Makefile b/contrib/auth_delay/Makefile
new file mode 100644
index 0000000000..09d2d5418c
--- /dev/null
+++ b/contrib/auth_delay/Makefile
@@ -0,0 +1,14 @@
+# contrib/auth_delay/Makefile
+
+MODULES = auth_delay
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/auth_delay
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/auth_delay/auth_delay.c b/contrib/auth_delay/auth_delay.c
new file mode 100644
index 0000000000..4e0d5959d1
--- /dev/null
+++ b/contrib/auth_delay/auth_delay.c
@@ -0,0 +1,71 @@
+/* -------------------------------------------------------------------------
+ *
+ * auth_delay.c
+ *
+ * Copyright (C) 2010-2011, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * contrib/auth_delay/auth_delay.c
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "libpq/auth.h"
+#include "port.h"
+#include "utils/guc.h"
+#include "utils/timestamp.h"
+
+PG_MODULE_MAGIC;
+
+void _PG_init(void);
+
+/* GUC Variables */
+static int auth_delay_milliseconds;
+
+/* Original Hook */
+static ClientAuthentication_hook_type original_client_auth_hook = NULL;
+
+/*
+ * Check authentication
+ */
+static void
+auth_delay_checks(Port *port, int status)
+{
+ /*
+ * Any other plugins which use ClientAuthentication_hook.
+ */
+ if (original_client_auth_hook)
+ original_client_auth_hook(port, status);
+
+ /*
+ * Inject a short delay if authentication failed.
+ */
+ if (status != STATUS_OK)
+ {
+ pg_usleep(1000L * auth_delay_milliseconds);
+ }
+}
+
+/*
+ * Module Load Callback
+ */
+void
+_PG_init(void)
+{
+ /* Define custom GUC variables */
+ DefineCustomIntVariable("auth_delay.milliseconds",
+ "Milliseconds to delay before reporting authentication failure",
+ NULL,
+ &auth_delay_milliseconds,
+ 0,
+ 0, INT_MAX,
+ PGC_SIGHUP,
+ GUC_UNIT_MS,
+ NULL,
+ NULL,
+ NULL);
+ /* Install Hooks */
+ original_client_auth_hook = ClientAuthentication_hook;
+ ClientAuthentication_hook = auth_delay_checks;
+}
diff --git a/contrib/auto_explain/Makefile b/contrib/auto_explain/Makefile
index e9eaae0ece..2d1443fe48 100644
--- a/contrib/auto_explain/Makefile
+++ b/contrib/auto_explain/Makefile
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/contrib/auto_explain/Makefile,v 1.1 2008/11/19 02:59:28 tgl Exp $
+# contrib/auto_explain/Makefile
MODULE_big = auto_explain
OBJS = auto_explain.o
diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c
index ffc1a4a106..b320698748 100644
--- a/contrib/auto_explain/auto_explain.c
+++ b/contrib/auto_explain/auto_explain.c
@@ -3,10 +3,10 @@
* auto_explain.c
*
*
- * Copyright (c) 2008-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2008-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/auto_explain/auto_explain.c,v 1.14 2010/02/26 02:00:31 momjian Exp $
+ * contrib/auto_explain/auto_explain.c
*
*-------------------------------------------------------------------------
*/
@@ -40,6 +40,7 @@ static int nesting_level = 0;
/* Saved hook values in case of unload */
static ExecutorStart_hook_type prev_ExecutorStart = NULL;
static ExecutorRun_hook_type prev_ExecutorRun = NULL;
+static ExecutorFinish_hook_type prev_ExecutorFinish = NULL;
static ExecutorEnd_hook_type prev_ExecutorEnd = NULL;
#define auto_explain_enabled() \
@@ -53,6 +54,7 @@ static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags);
static void explain_ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction,
long count);
+static void explain_ExecutorFinish(QueryDesc *queryDesc);
static void explain_ExecutorEnd(QueryDesc *queryDesc);
@@ -72,6 +74,7 @@ _PG_init(void)
PGC_SUSET,
GUC_UNIT_MS,
NULL,
+ NULL,
NULL);
DefineCustomBoolVariable("auto_explain.log_analyze",
@@ -82,6 +85,7 @@ _PG_init(void)
PGC_SUSET,
0,
NULL,
+ NULL,
NULL);
DefineCustomBoolVariable("auto_explain.log_verbose",
@@ -92,6 +96,7 @@ _PG_init(void)
PGC_SUSET,
0,
NULL,
+ NULL,
NULL);
DefineCustomBoolVariable("auto_explain.log_buffers",
@@ -102,6 +107,7 @@ _PG_init(void)
PGC_SUSET,
0,
NULL,
+ NULL,
NULL);
DefineCustomEnumVariable("auto_explain.log_format",
@@ -113,6 +119,7 @@ _PG_init(void)
PGC_SUSET,
0,
NULL,
+ NULL,
NULL);
DefineCustomBoolVariable("auto_explain.log_nested_statements",
@@ -123,6 +130,7 @@ _PG_init(void)
PGC_SUSET,
0,
NULL,
+ NULL,
NULL);
EmitWarningsOnPlaceholders("auto_explain");
@@ -132,6 +140,8 @@ _PG_init(void)
ExecutorStart_hook = explain_ExecutorStart;
prev_ExecutorRun = ExecutorRun_hook;
ExecutorRun_hook = explain_ExecutorRun;
+ prev_ExecutorFinish = ExecutorFinish_hook;
+ ExecutorFinish_hook = explain_ExecutorFinish;
prev_ExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = explain_ExecutorEnd;
}
@@ -145,6 +155,7 @@ _PG_fini(void)
/* Uninstall hooks. */
ExecutorStart_hook = prev_ExecutorStart;
ExecutorRun_hook = prev_ExecutorRun;
+ ExecutorFinish_hook = prev_ExecutorFinish;
ExecutorEnd_hook = prev_ExecutorEnd;
}
@@ -212,6 +223,29 @@ explain_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long count)
}
/*
+ * ExecutorFinish hook: all we need do is track nesting depth
+ */
+static void
+explain_ExecutorFinish(QueryDesc *queryDesc)
+{
+ nesting_level++;
+ PG_TRY();
+ {
+ if (prev_ExecutorFinish)
+ prev_ExecutorFinish(queryDesc);
+ else
+ standard_ExecutorFinish(queryDesc);
+ nesting_level--;
+ }
+ PG_CATCH();
+ {
+ nesting_level--;
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+}
+
+/*
* ExecutorEnd hook: log results if needed
*/
static void
diff --git a/contrib/btree_gin/.gitignore b/contrib/btree_gin/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/btree_gin/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/btree_gin/Makefile b/contrib/btree_gin/Makefile
index e6b6394c23..09fd3e6e11 100644
--- a/contrib/btree_gin/Makefile
+++ b/contrib/btree_gin/Makefile
@@ -1,10 +1,11 @@
-# $PostgreSQL: pgsql/contrib/btree_gin/Makefile,v 1.1 2009/03/25 23:20:01 tgl Exp $
+# contrib/btree_gin/Makefile
MODULE_big = btree_gin
-OBJS = btree_gin.o
+OBJS = btree_gin.o
+
+EXTENSION = btree_gin
+DATA = btree_gin--1.0.sql btree_gin--unpackaged--1.0.sql
-DATA_built = btree_gin.sql
-DATA = uninstall_btree_gin.sql
REGRESS = install_btree_gin int2 int4 int8 float4 float8 money oid \
timestamp timestamptz time timetz date interval \
macaddr inet cidr text varchar char bytea bit varbit \
diff --git a/contrib/btree_gin/btree_gin.sql.in b/contrib/btree_gin/btree_gin--1.0.sql
index bc7ec3bbcb..07f93640f3 100644
--- a/contrib/btree_gin/btree_gin.sql.in
+++ b/contrib/btree_gin/btree_gin--1.0.sql
@@ -1,24 +1,21 @@
-/* $PostgreSQL: pgsql/contrib/btree_gin/btree_gin.sql.in,v 1.1 2009/03/25 23:20:01 tgl Exp $ */
+/* contrib/btree_gin/btree_gin--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION gin_btree_consistent(internal, int2, anyelement, int4, internal, internal)
+CREATE FUNCTION gin_btree_consistent(internal, int2, anyelement, int4, internal, internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_value_int2(int2, internal)
+CREATE FUNCTION gin_extract_value_int2(int2, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_int2(int2, int2, int2, internal)
+CREATE FUNCTION gin_compare_prefix_int2(int2, int2, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_int2(int2, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_int2(int2, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -38,17 +35,17 @@ AS
FUNCTION 5 gin_compare_prefix_int2(int2,int2,int2, internal),
STORAGE int2;
-CREATE OR REPLACE FUNCTION gin_extract_value_int4(int4, internal)
+CREATE FUNCTION gin_extract_value_int4(int4, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_int4(int4, int4, int2, internal)
+CREATE FUNCTION gin_compare_prefix_int4(int4, int4, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_int4(int4, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_int4(int4, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -68,17 +65,17 @@ AS
FUNCTION 5 gin_compare_prefix_int4(int4,int4,int2, internal),
STORAGE int4;
-CREATE OR REPLACE FUNCTION gin_extract_value_int8(int8, internal)
+CREATE FUNCTION gin_extract_value_int8(int8, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_int8(int8, int8, int2, internal)
+CREATE FUNCTION gin_compare_prefix_int8(int8, int8, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_int8(int8, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_int8(int8, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -98,17 +95,17 @@ AS
FUNCTION 5 gin_compare_prefix_int8(int8,int8,int2, internal),
STORAGE int8;
-CREATE OR REPLACE FUNCTION gin_extract_value_float4(float4, internal)
+CREATE FUNCTION gin_extract_value_float4(float4, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_float4(float4, float4, int2, internal)
+CREATE FUNCTION gin_compare_prefix_float4(float4, float4, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_float4(float4, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_float4(float4, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -128,17 +125,17 @@ AS
FUNCTION 5 gin_compare_prefix_float4(float4,float4,int2, internal),
STORAGE float4;
-CREATE OR REPLACE FUNCTION gin_extract_value_float8(float8, internal)
+CREATE FUNCTION gin_extract_value_float8(float8, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_float8(float8, float8, int2, internal)
+CREATE FUNCTION gin_compare_prefix_float8(float8, float8, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_float8(float8, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_float8(float8, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -158,17 +155,17 @@ AS
FUNCTION 5 gin_compare_prefix_float8(float8,float8,int2, internal),
STORAGE float8;
-CREATE OR REPLACE FUNCTION gin_extract_value_money(money, internal)
+CREATE FUNCTION gin_extract_value_money(money, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_money(money, money, int2, internal)
+CREATE FUNCTION gin_compare_prefix_money(money, money, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_money(money, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_money(money, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -188,17 +185,17 @@ AS
FUNCTION 5 gin_compare_prefix_money(money,money,int2, internal),
STORAGE money;
-CREATE OR REPLACE FUNCTION gin_extract_value_oid(oid, internal)
+CREATE FUNCTION gin_extract_value_oid(oid, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_oid(oid, oid, int2, internal)
+CREATE FUNCTION gin_compare_prefix_oid(oid, oid, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_oid(oid, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_oid(oid, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -218,17 +215,17 @@ AS
FUNCTION 5 gin_compare_prefix_oid(oid,oid,int2, internal),
STORAGE oid;
-CREATE OR REPLACE FUNCTION gin_extract_value_timestamp(timestamp, internal)
+CREATE FUNCTION gin_extract_value_timestamp(timestamp, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_timestamp(timestamp, timestamp, int2, internal)
+CREATE FUNCTION gin_compare_prefix_timestamp(timestamp, timestamp, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_timestamp(timestamp, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_timestamp(timestamp, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -248,17 +245,17 @@ AS
FUNCTION 5 gin_compare_prefix_timestamp(timestamp,timestamp,int2, internal),
STORAGE timestamp;
-CREATE OR REPLACE FUNCTION gin_extract_value_timestamptz(timestamptz, internal)
+CREATE FUNCTION gin_extract_value_timestamptz(timestamptz, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_timestamptz(timestamptz, timestamptz, int2, internal)
+CREATE FUNCTION gin_compare_prefix_timestamptz(timestamptz, timestamptz, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_timestamptz(timestamptz, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_timestamptz(timestamptz, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -278,17 +275,17 @@ AS
FUNCTION 5 gin_compare_prefix_timestamptz(timestamptz,timestamptz,int2, internal),
STORAGE timestamptz;
-CREATE OR REPLACE FUNCTION gin_extract_value_time(time, internal)
+CREATE FUNCTION gin_extract_value_time(time, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_time(time, time, int2, internal)
+CREATE FUNCTION gin_compare_prefix_time(time, time, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_time(time, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_time(time, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -308,17 +305,17 @@ AS
FUNCTION 5 gin_compare_prefix_time(time,time,int2, internal),
STORAGE time;
-CREATE OR REPLACE FUNCTION gin_extract_value_timetz(timetz, internal)
+CREATE FUNCTION gin_extract_value_timetz(timetz, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_timetz(timetz, timetz, int2, internal)
+CREATE FUNCTION gin_compare_prefix_timetz(timetz, timetz, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_timetz(timetz, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_timetz(timetz, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -338,17 +335,17 @@ AS
FUNCTION 5 gin_compare_prefix_timetz(timetz,timetz,int2, internal),
STORAGE timetz;
-CREATE OR REPLACE FUNCTION gin_extract_value_date(date, internal)
+CREATE FUNCTION gin_extract_value_date(date, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_date(date, date, int2, internal)
+CREATE FUNCTION gin_compare_prefix_date(date, date, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_date(date, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_date(date, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -368,17 +365,17 @@ AS
FUNCTION 5 gin_compare_prefix_date(date,date,int2, internal),
STORAGE date;
-CREATE OR REPLACE FUNCTION gin_extract_value_interval(interval, internal)
+CREATE FUNCTION gin_extract_value_interval(interval, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_interval(interval, interval, int2, internal)
+CREATE FUNCTION gin_compare_prefix_interval(interval, interval, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_interval(interval, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_interval(interval, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -398,17 +395,17 @@ AS
FUNCTION 5 gin_compare_prefix_interval(interval,interval,int2, internal),
STORAGE interval;
-CREATE OR REPLACE FUNCTION gin_extract_value_macaddr(macaddr, internal)
+CREATE FUNCTION gin_extract_value_macaddr(macaddr, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_macaddr(macaddr, macaddr, int2, internal)
+CREATE FUNCTION gin_compare_prefix_macaddr(macaddr, macaddr, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_macaddr(macaddr, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_macaddr(macaddr, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -428,17 +425,17 @@ AS
FUNCTION 5 gin_compare_prefix_macaddr(macaddr,macaddr,int2, internal),
STORAGE macaddr;
-CREATE OR REPLACE FUNCTION gin_extract_value_inet(inet, internal)
+CREATE FUNCTION gin_extract_value_inet(inet, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_inet(inet, inet, int2, internal)
+CREATE FUNCTION gin_compare_prefix_inet(inet, inet, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_inet(inet, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_inet(inet, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -458,17 +455,17 @@ AS
FUNCTION 5 gin_compare_prefix_inet(inet,inet,int2, internal),
STORAGE inet;
-CREATE OR REPLACE FUNCTION gin_extract_value_cidr(cidr, internal)
+CREATE FUNCTION gin_extract_value_cidr(cidr, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_cidr(cidr, cidr, int2, internal)
+CREATE FUNCTION gin_compare_prefix_cidr(cidr, cidr, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_cidr(cidr, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_cidr(cidr, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -488,17 +485,17 @@ AS
FUNCTION 5 gin_compare_prefix_cidr(cidr,cidr,int2, internal),
STORAGE cidr;
-CREATE OR REPLACE FUNCTION gin_extract_value_text(text, internal)
+CREATE FUNCTION gin_extract_value_text(text, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_text(text, text, int2, internal)
+CREATE FUNCTION gin_compare_prefix_text(text, text, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_text(text, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_text(text, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -533,17 +530,17 @@ AS
FUNCTION 5 gin_compare_prefix_text(text,text,int2, internal),
STORAGE varchar;
-CREATE OR REPLACE FUNCTION gin_extract_value_char("char", internal)
+CREATE FUNCTION gin_extract_value_char("char", internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_char("char", "char", int2, internal)
+CREATE FUNCTION gin_compare_prefix_char("char", "char", int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_char("char", internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_char("char", internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -563,17 +560,17 @@ AS
FUNCTION 5 gin_compare_prefix_char("char","char",int2, internal),
STORAGE "char";
-CREATE OR REPLACE FUNCTION gin_extract_value_bytea(bytea, internal)
+CREATE FUNCTION gin_extract_value_bytea(bytea, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_bytea(bytea, bytea, int2, internal)
+CREATE FUNCTION gin_compare_prefix_bytea(bytea, bytea, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_bytea(bytea, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_bytea(bytea, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -593,17 +590,17 @@ AS
FUNCTION 5 gin_compare_prefix_bytea(bytea,bytea,int2, internal),
STORAGE bytea;
-CREATE OR REPLACE FUNCTION gin_extract_value_bit(bit, internal)
+CREATE FUNCTION gin_extract_value_bit(bit, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_bit(bit, bit, int2, internal)
+CREATE FUNCTION gin_compare_prefix_bit(bit, bit, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_bit(bit, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_bit(bit, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -623,17 +620,17 @@ AS
FUNCTION 5 gin_compare_prefix_bit(bit,bit,int2, internal),
STORAGE bit;
-CREATE OR REPLACE FUNCTION gin_extract_value_varbit(varbit, internal)
+CREATE FUNCTION gin_extract_value_varbit(varbit, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_varbit(varbit, varbit, int2, internal)
+CREATE FUNCTION gin_compare_prefix_varbit(varbit, varbit, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_varbit(varbit, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_varbit(varbit, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -653,22 +650,22 @@ AS
FUNCTION 5 gin_compare_prefix_varbit(varbit,varbit,int2, internal),
STORAGE varbit;
-CREATE OR REPLACE FUNCTION gin_extract_value_numeric(numeric, internal)
+CREATE FUNCTION gin_extract_value_numeric(numeric, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_compare_prefix_numeric(numeric, numeric, int2, internal)
+CREATE FUNCTION gin_compare_prefix_numeric(numeric, numeric, int2, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_extract_query_numeric(numeric, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_query_numeric(numeric, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION gin_numeric_cmp(numeric, numeric)
+CREATE FUNCTION gin_numeric_cmp(numeric, numeric)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
diff --git a/contrib/btree_gin/btree_gin--unpackaged--1.0.sql b/contrib/btree_gin/btree_gin--unpackaged--1.0.sql
new file mode 100644
index 0000000000..fe1ddeab87
--- /dev/null
+++ b/contrib/btree_gin/btree_gin--unpackaged--1.0.sql
@@ -0,0 +1,116 @@
+/* contrib/btree_gin/btree_gin--unpackaged--1.0.sql */
+
+ALTER EXTENSION btree_gin ADD function gin_btree_consistent(internal,smallint,anyelement,integer,internal,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_value_int2(smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_int2(smallint,smallint,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_int2(smallint,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family int2_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class int2_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_int4(integer,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_int4(integer,integer,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_int4(integer,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family int4_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class int4_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_int8(bigint,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_int8(bigint,bigint,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_int8(bigint,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family int8_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class int8_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_float4(real,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_float4(real,real,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_float4(real,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family float4_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class float4_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_float8(double precision,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_float8(double precision,double precision,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_float8(double precision,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family float8_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class float8_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_money(money,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_money(money,money,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_money(money,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family money_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class money_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_oid(oid,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_oid(oid,oid,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_oid(oid,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family oid_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class oid_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_timestamp(timestamp without time zone,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_timestamp(timestamp without time zone,timestamp without time zone,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_timestamp(timestamp without time zone,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family timestamp_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class timestamp_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_timestamptz(timestamp with time zone,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_timestamptz(timestamp with time zone,timestamp with time zone,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_timestamptz(timestamp with time zone,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family timestamptz_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class timestamptz_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_time(time without time zone,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_time(time without time zone,time without time zone,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_time(time without time zone,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family time_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class time_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_timetz(time with time zone,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_timetz(time with time zone,time with time zone,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_timetz(time with time zone,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family timetz_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class timetz_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_date(date,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_date(date,date,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_date(date,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family date_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class date_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_interval(interval,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_interval(interval,interval,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_interval(interval,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family interval_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class interval_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_macaddr(macaddr,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_macaddr(macaddr,macaddr,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_macaddr(macaddr,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family macaddr_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class macaddr_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_inet(inet,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_inet(inet,inet,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_inet(inet,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family inet_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class inet_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_cidr(cidr,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_cidr(cidr,cidr,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_cidr(cidr,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family cidr_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class cidr_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_text(text,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_text(text,text,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_text(text,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family text_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class text_ops using gin;
+ALTER EXTENSION btree_gin ADD operator family varchar_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class varchar_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_char("char",internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_char("char","char",smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_char("char",internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family char_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class char_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_bytea(bytea,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_bytea(bytea,bytea,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_bytea(bytea,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family bytea_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class bytea_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_bit(bit,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_bit(bit,bit,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_bit(bit,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family bit_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class bit_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_varbit(bit varying,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_varbit(bit varying,bit varying,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_varbit(bit varying,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD operator family varbit_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class varbit_ops using gin;
+ALTER EXTENSION btree_gin ADD function gin_extract_value_numeric(numeric,internal);
+ALTER EXTENSION btree_gin ADD function gin_compare_prefix_numeric(numeric,numeric,smallint,internal);
+ALTER EXTENSION btree_gin ADD function gin_extract_query_numeric(numeric,internal,smallint,internal,internal);
+ALTER EXTENSION btree_gin ADD function gin_numeric_cmp(numeric,numeric);
+ALTER EXTENSION btree_gin ADD operator family numeric_ops using gin;
+ALTER EXTENSION btree_gin ADD operator class numeric_ops using gin;
diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index c05f8ebbfc..5c4f58b8b1 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gin/btree_gin.c,v 1.4 2010/01/07 04:53:34 tgl Exp $
+ * contrib/btree_gin/btree_gin.c
*/
#include "postgres.h"
@@ -120,8 +120,9 @@ gin_compare_prefix_##type(PG_FUNCTION_ARGS) \
int32 res, \
cmp; \
\
- cmp = DatumGetInt32(DirectFunctionCall2( \
+ cmp = DatumGetInt32(DirectFunctionCall2Coll( \
TypeInfo_##type.typecmp, \
+ PG_GET_COLLATION(), \
(data->strategy == BTLessStrategyNumber || \
data->strategy == BTLessEqualStrategyNumber) \
? data->datum : a, \
@@ -394,10 +395,11 @@ static TypeInfo TypeInfo_varbit = {true, leftmostvalue_varbit, bitcmp};
GIN_SUPPORT(varbit)
/*
- * Numeric type hasn't applicable left-most value, so NULL
- * is used for that. NULL will never be an argument for a C-level
- * numeric function except gin_numeric_cmp and it will not be stored
- * somewhere and it could not be returned in any user SQL query.
+ * Numeric type hasn't a real left-most value, so we use PointerGetDatum(NULL)
+ * (*not* a SQL NULL) to represent that. We can get away with that because
+ * the value returned by our leftmostvalue function will never be stored in
+ * the index nor passed to anything except our compare and prefix-comparison
+ * functions. The same trick could be used for other pass-by-reference types.
*/
#define NUMERIC_IS_LEFTMOST(x) ((x) == NULL)
diff --git a/contrib/btree_gin/btree_gin.control b/contrib/btree_gin/btree_gin.control
new file mode 100644
index 0000000000..3b2cb2d709
--- /dev/null
+++ b/contrib/btree_gin/btree_gin.control
@@ -0,0 +1,5 @@
+# btree_gin extension
+comment = 'support for indexing common datatypes in GIN'
+default_version = '1.0'
+module_pathname = '$libdir/btree_gin'
+relocatable = true
diff --git a/contrib/btree_gin/expected/cidr.out b/contrib/btree_gin/expected/cidr.out
index 28ff9195b1..3d1198a4d7 100644
--- a/contrib/btree_gin/expected/cidr.out
+++ b/contrib/btree_gin/expected/cidr.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_cidr (
i cidr
);
-INSERT INTO test_cidr VALUES
+INSERT INTO test_cidr VALUES
( '1.2.3.4' ),
( '1.2.4.4' ),
( '1.2.5.4' ),
diff --git a/contrib/btree_gin/expected/date.out b/contrib/btree_gin/expected/date.out
index 8da6ee4843..40dfa308cf 100644
--- a/contrib/btree_gin/expected/date.out
+++ b/contrib/btree_gin/expected/date.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_date (
i date
);
-INSERT INTO test_date VALUES
+INSERT INTO test_date VALUES
( '2004-10-23' ),
( '2004-10-24' ),
( '2004-10-25' ),
diff --git a/contrib/btree_gin/expected/inet.out b/contrib/btree_gin/expected/inet.out
index bb2eaafc7f..aa6147fb7d 100644
--- a/contrib/btree_gin/expected/inet.out
+++ b/contrib/btree_gin/expected/inet.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_inet (
i inet
);
-INSERT INTO test_inet VALUES
+INSERT INTO test_inet VALUES
( '1.2.3.4/16' ),
( '1.2.4.4/16' ),
( '1.2.5.4/16' ),
diff --git a/contrib/btree_gin/expected/install_btree_gin.out b/contrib/btree_gin/expected/install_btree_gin.out
index 43f11fa263..0fae4c5bfe 100644
--- a/contrib/btree_gin/expected/install_btree_gin.out
+++ b/contrib/btree_gin/expected/install_btree_gin.out
@@ -1,3 +1 @@
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION btree_gin;
diff --git a/contrib/btree_gin/expected/interval.out b/contrib/btree_gin/expected/interval.out
index a3b99c1f28..1f6ef54070 100644
--- a/contrib/btree_gin/expected/interval.out
+++ b/contrib/btree_gin/expected/interval.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_interval (
i interval
);
-INSERT INTO test_interval VALUES
+INSERT INTO test_interval VALUES
( '03:55:08' ),
( '04:55:08' ),
( '05:55:08' ),
diff --git a/contrib/btree_gin/expected/macaddr.out b/contrib/btree_gin/expected/macaddr.out
index d26d1f9ad3..ebceb01862 100644
--- a/contrib/btree_gin/expected/macaddr.out
+++ b/contrib/btree_gin/expected/macaddr.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_macaddr (
i macaddr
);
-INSERT INTO test_macaddr VALUES
+INSERT INTO test_macaddr VALUES
( '22:00:5c:03:55:08' ),
( '22:00:5c:04:55:08' ),
( '22:00:5c:05:55:08' ),
diff --git a/contrib/btree_gin/expected/time.out b/contrib/btree_gin/expected/time.out
index bf65946835..be6b084038 100644
--- a/contrib/btree_gin/expected/time.out
+++ b/contrib/btree_gin/expected/time.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_time (
i time
);
-INSERT INTO test_time VALUES
+INSERT INTO test_time VALUES
( '03:55:08' ),
( '04:55:08' ),
( '05:55:08' ),
diff --git a/contrib/btree_gin/expected/timestamp.out b/contrib/btree_gin/expected/timestamp.out
index 00b0b66106..a236cdc94a 100644
--- a/contrib/btree_gin/expected/timestamp.out
+++ b/contrib/btree_gin/expected/timestamp.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_timestamp (
i timestamp
);
-INSERT INTO test_timestamp VALUES
+INSERT INTO test_timestamp VALUES
( '2004-10-26 03:55:08' ),
( '2004-10-26 04:55:08' ),
( '2004-10-26 05:55:08' ),
diff --git a/contrib/btree_gin/expected/timestamptz.out b/contrib/btree_gin/expected/timestamptz.out
index 8550d6b4d9..d53963d2a0 100644
--- a/contrib/btree_gin/expected/timestamptz.out
+++ b/contrib/btree_gin/expected/timestamptz.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_timestamptz (
i timestamptz
);
-INSERT INTO test_timestamptz VALUES
+INSERT INTO test_timestamptz VALUES
( '2004-10-26 03:55:08' ),
( '2004-10-26 04:55:08' ),
( '2004-10-26 05:55:08' ),
diff --git a/contrib/btree_gin/expected/timetz.out b/contrib/btree_gin/expected/timetz.out
index 184bc310f6..45aee71371 100644
--- a/contrib/btree_gin/expected/timetz.out
+++ b/contrib/btree_gin/expected/timetz.out
@@ -2,7 +2,7 @@ set enable_seqscan=off;
CREATE TABLE test_timetz (
i timetz
);
-INSERT INTO test_timetz VALUES
+INSERT INTO test_timetz VALUES
( '03:55:08 GMT+2' ),
( '04:55:08 GMT+2' ),
( '05:55:08 GMT+2' ),
diff --git a/contrib/btree_gin/sql/cidr.sql b/contrib/btree_gin/sql/cidr.sql
index a608a3ec78..4a76e5f10b 100644
--- a/contrib/btree_gin/sql/cidr.sql
+++ b/contrib/btree_gin/sql/cidr.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_cidr (
i cidr
);
-INSERT INTO test_cidr VALUES
+INSERT INTO test_cidr VALUES
( '1.2.3.4' ),
( '1.2.4.4' ),
( '1.2.5.4' ),
diff --git a/contrib/btree_gin/sql/date.sql b/contrib/btree_gin/sql/date.sql
index c486f272a4..35086f6b81 100644
--- a/contrib/btree_gin/sql/date.sql
+++ b/contrib/btree_gin/sql/date.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_date (
i date
);
-INSERT INTO test_date VALUES
+INSERT INTO test_date VALUES
( '2004-10-23' ),
( '2004-10-24' ),
( '2004-10-25' ),
diff --git a/contrib/btree_gin/sql/inet.sql b/contrib/btree_gin/sql/inet.sql
index fadc1c47ec..e5ec087856 100644
--- a/contrib/btree_gin/sql/inet.sql
+++ b/contrib/btree_gin/sql/inet.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_inet (
i inet
);
-INSERT INTO test_inet VALUES
+INSERT INTO test_inet VALUES
( '1.2.3.4/16' ),
( '1.2.4.4/16' ),
( '1.2.5.4/16' ),
diff --git a/contrib/btree_gin/sql/install_btree_gin.sql b/contrib/btree_gin/sql/install_btree_gin.sql
index f54c8b4a0f..0fae4c5bfe 100644
--- a/contrib/btree_gin/sql/install_btree_gin.sql
+++ b/contrib/btree_gin/sql/install_btree_gin.sql
@@ -1,5 +1 @@
-SET client_min_messages = warning;
-\set ECHO none
-\i btree_gin.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION btree_gin;
diff --git a/contrib/btree_gin/sql/interval.sql b/contrib/btree_gin/sql/interval.sql
index f245e4d4b3..e385158783 100644
--- a/contrib/btree_gin/sql/interval.sql
+++ b/contrib/btree_gin/sql/interval.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_interval (
i interval
);
-INSERT INTO test_interval VALUES
+INSERT INTO test_interval VALUES
( '03:55:08' ),
( '04:55:08' ),
( '05:55:08' ),
diff --git a/contrib/btree_gin/sql/macaddr.sql b/contrib/btree_gin/sql/macaddr.sql
index e0402869a8..66566aa604 100644
--- a/contrib/btree_gin/sql/macaddr.sql
+++ b/contrib/btree_gin/sql/macaddr.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_macaddr (
i macaddr
);
-INSERT INTO test_macaddr VALUES
+INSERT INTO test_macaddr VALUES
( '22:00:5c:03:55:08' ),
( '22:00:5c:04:55:08' ),
( '22:00:5c:05:55:08' ),
diff --git a/contrib/btree_gin/sql/time.sql b/contrib/btree_gin/sql/time.sql
index afb1e16ebf..62d709a846 100644
--- a/contrib/btree_gin/sql/time.sql
+++ b/contrib/btree_gin/sql/time.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_time (
i time
);
-INSERT INTO test_time VALUES
+INSERT INTO test_time VALUES
( '03:55:08' ),
( '04:55:08' ),
( '05:55:08' ),
diff --git a/contrib/btree_gin/sql/timestamp.sql b/contrib/btree_gin/sql/timestamp.sql
index 6e00cd7e40..56727e81c4 100644
--- a/contrib/btree_gin/sql/timestamp.sql
+++ b/contrib/btree_gin/sql/timestamp.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_timestamp (
i timestamp
);
-INSERT INTO test_timestamp VALUES
+INSERT INTO test_timestamp VALUES
( '2004-10-26 03:55:08' ),
( '2004-10-26 04:55:08' ),
( '2004-10-26 05:55:08' ),
diff --git a/contrib/btree_gin/sql/timestamptz.sql b/contrib/btree_gin/sql/timestamptz.sql
index 26c01ef804..e6cfdb1b07 100644
--- a/contrib/btree_gin/sql/timestamptz.sql
+++ b/contrib/btree_gin/sql/timestamptz.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_timestamptz (
i timestamptz
);
-INSERT INTO test_timestamptz VALUES
+INSERT INTO test_timestamptz VALUES
( '2004-10-26 03:55:08' ),
( '2004-10-26 04:55:08' ),
( '2004-10-26 05:55:08' ),
diff --git a/contrib/btree_gin/sql/timetz.sql b/contrib/btree_gin/sql/timetz.sql
index a72b105fc1..ca947b753e 100644
--- a/contrib/btree_gin/sql/timetz.sql
+++ b/contrib/btree_gin/sql/timetz.sql
@@ -4,7 +4,7 @@ CREATE TABLE test_timetz (
i timetz
);
-INSERT INTO test_timetz VALUES
+INSERT INTO test_timetz VALUES
( '03:55:08 GMT+2' ),
( '04:55:08 GMT+2' ),
( '05:55:08 GMT+2' ),
diff --git a/contrib/btree_gin/uninstall_btree_gin.sql b/contrib/btree_gin/uninstall_btree_gin.sql
deleted file mode 100644
index 0b79c6037b..0000000000
--- a/contrib/btree_gin/uninstall_btree_gin.sql
+++ /dev/null
@@ -1,98 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/btree_gin/uninstall_btree_gin.sql,v 1.1 2009/03/25 23:20:01 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR FAMILY int2_ops USING gin CASCADE;
-DROP OPERATOR FAMILY int4_ops USING gin CASCADE;
-DROP OPERATOR FAMILY int8_ops USING gin CASCADE;
-DROP OPERATOR FAMILY float4_ops USING gin CASCADE;
-DROP OPERATOR FAMILY float8_ops USING gin CASCADE;
-DROP OPERATOR FAMILY money_ops USING gin CASCADE;
-DROP OPERATOR FAMILY oid_ops USING gin CASCADE;
-DROP OPERATOR FAMILY timestamp_ops USING gin CASCADE;
-DROP OPERATOR FAMILY timestamptz_ops USING gin CASCADE;
-DROP OPERATOR FAMILY time_ops USING gin CASCADE;
-DROP OPERATOR FAMILY timetz_ops USING gin CASCADE;
-DROP OPERATOR FAMILY date_ops USING gin CASCADE;
-DROP OPERATOR FAMILY interval_ops USING gin CASCADE;
-DROP OPERATOR FAMILY macaddr_ops USING gin CASCADE;
-DROP OPERATOR FAMILY inet_ops USING gin CASCADE;
-DROP OPERATOR FAMILY cidr_ops USING gin CASCADE;
-DROP OPERATOR FAMILY text_ops USING gin CASCADE;
-DROP OPERATOR FAMILY varchar_ops USING gin CASCADE;
-DROP OPERATOR FAMILY char_ops USING gin CASCADE;
-DROP OPERATOR FAMILY bytea_ops USING gin CASCADE;
-DROP OPERATOR FAMILY bit_ops USING gin CASCADE;
-DROP OPERATOR FAMILY varbit_ops USING gin CASCADE;
-DROP OPERATOR FAMILY numeric_ops USING gin CASCADE;
-
-DROP FUNCTION gin_btree_consistent(internal, int2, anyelement, int4, internal, internal);
-
-DROP FUNCTION gin_extract_value_int2(int2, internal);
-DROP FUNCTION gin_compare_prefix_int2(int2, int2, int2, internal);
-DROP FUNCTION gin_extract_query_int2(int2, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_int4(int4, internal);
-DROP FUNCTION gin_compare_prefix_int4(int4, int4, int2, internal);
-DROP FUNCTION gin_extract_query_int4(int4, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_int8(int8, internal);
-DROP FUNCTION gin_compare_prefix_int8(int8, int8, int2, internal);
-DROP FUNCTION gin_extract_query_int8(int8, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_float4(float4, internal);
-DROP FUNCTION gin_compare_prefix_float4(float4, float4, int2, internal);
-DROP FUNCTION gin_extract_query_float4(float4, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_float8(float8, internal);
-DROP FUNCTION gin_compare_prefix_float8(float8, float8, int2, internal);
-DROP FUNCTION gin_extract_query_float8(float8, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_money(money, internal);
-DROP FUNCTION gin_compare_prefix_money(money, money, int2, internal);
-DROP FUNCTION gin_extract_query_money(money, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_oid(oid, internal);
-DROP FUNCTION gin_compare_prefix_oid(oid, oid, int2, internal);
-DROP FUNCTION gin_extract_query_oid(oid, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_timestamp(timestamp, internal);
-DROP FUNCTION gin_compare_prefix_timestamp(timestamp, timestamp, int2, internal);
-DROP FUNCTION gin_extract_query_timestamp(timestamp, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_timestamptz(timestamptz, internal);
-DROP FUNCTION gin_compare_prefix_timestamptz(timestamptz, timestamptz, int2, internal);
-DROP FUNCTION gin_extract_query_timestamptz(timestamptz, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_time(time, internal);
-DROP FUNCTION gin_compare_prefix_time(time, time, int2, internal);
-DROP FUNCTION gin_extract_query_time(time, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_timetz(timetz, internal);
-DROP FUNCTION gin_compare_prefix_timetz(timetz, timetz, int2, internal);
-DROP FUNCTION gin_extract_query_timetz(timetz, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_date(date, internal);
-DROP FUNCTION gin_compare_prefix_date(date, date, int2, internal);
-DROP FUNCTION gin_extract_query_date(date, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_interval(interval, internal);
-DROP FUNCTION gin_compare_prefix_interval(interval, interval, int2, internal);
-DROP FUNCTION gin_extract_query_interval(interval, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_macaddr(macaddr, internal);
-DROP FUNCTION gin_compare_prefix_macaddr(macaddr, macaddr, int2, internal);
-DROP FUNCTION gin_extract_query_macaddr(macaddr, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_inet(inet, internal);
-DROP FUNCTION gin_compare_prefix_inet(inet, inet, int2, internal);
-DROP FUNCTION gin_extract_query_inet(inet, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_cidr(cidr, internal);
-DROP FUNCTION gin_compare_prefix_cidr(cidr, cidr, int2, internal);
-DROP FUNCTION gin_extract_query_cidr(cidr, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_text(text, internal);
-DROP FUNCTION gin_compare_prefix_text(text, text, int2, internal);
-DROP FUNCTION gin_extract_query_text(text, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_char("char", internal);
-DROP FUNCTION gin_compare_prefix_char("char", "char", int2, internal);
-DROP FUNCTION gin_extract_query_char("char", internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_bytea(bytea, internal);
-DROP FUNCTION gin_compare_prefix_bytea(bytea, bytea, int2, internal);
-DROP FUNCTION gin_extract_query_bytea(bytea, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_bit(bit, internal);
-DROP FUNCTION gin_compare_prefix_bit(bit, bit, int2, internal);
-DROP FUNCTION gin_extract_query_bit(bit, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_varbit(varbit, internal);
-DROP FUNCTION gin_compare_prefix_varbit(varbit, varbit, int2, internal);
-DROP FUNCTION gin_extract_query_varbit(varbit, internal, int2, internal, internal);
-DROP FUNCTION gin_extract_value_numeric(numeric, internal);
-DROP FUNCTION gin_compare_prefix_numeric(numeric, numeric, int2, internal);
-DROP FUNCTION gin_extract_query_numeric(numeric, internal, int2, internal, internal);
-DROP FUNCTION gin_numeric_cmp(numeric, numeric);
diff --git a/contrib/btree_gist/.gitignore b/contrib/btree_gist/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/btree_gist/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/btree_gist/Makefile b/contrib/btree_gist/Makefile
index 8c779c4d06..ba4af14658 100644
--- a/contrib/btree_gist/Makefile
+++ b/contrib/btree_gist/Makefile
@@ -1,17 +1,21 @@
-# $PostgreSQL: pgsql/contrib/btree_gist/Makefile,v 1.12 2007/11/10 23:59:50 momjian Exp $
+# contrib/btree_gist/Makefile
-MODULE_big = btree_gist
+MODULE_big = btree_gist
-OBJS = btree_gist.o btree_utils_num.o btree_utils_var.o btree_int2.o btree_int4.o btree_int8.o \
- btree_float4.o btree_float8.o btree_cash.o btree_oid.o btree_ts.o btree_time.o \
- btree_date.o btree_interval.o btree_macaddr.o btree_inet.o btree_text.o \
- btree_bytea.o btree_bit.o btree_numeric.o
+OBJS = btree_gist.o btree_utils_num.o btree_utils_var.o btree_int2.o \
+ btree_int4.o btree_int8.o btree_float4.o btree_float8.o btree_cash.o \
+ btree_oid.o btree_ts.o btree_time.o btree_date.o btree_interval.o \
+ btree_macaddr.o btree_inet.o btree_text.o btree_bytea.o btree_bit.o \
+ btree_numeric.o
-DATA_built = btree_gist.sql
-DATA = uninstall_btree_gist.sql
+EXTENSION = btree_gist
+DATA = btree_gist--1.0.sql btree_gist--unpackaged--1.0.sql
-REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz time timetz \
- date interval macaddr inet cidr text varchar char bytea bit varbit numeric
+REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz \
+ time timetz date interval macaddr inet cidr text varchar char bytea \
+ bit varbit numeric not_equal
+
+SHLIB_LINK += $(filter -lm, $(LIBS))
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/btree_gist/btree_bit.c b/contrib/btree_gist/btree_bit.c
index f78134f443..8675d2488d 100644
--- a/contrib/btree_gist/btree_bit.c
+++ b/contrib/btree_gist/btree_bit.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_bit.c,v 1.11 2009/08/04 18:49:50 tgl Exp $
+ * contrib/btree_gist/btree_bit.c
*/
#include "btree_gist.h"
#include "btree_utils_var.h"
@@ -29,40 +29,51 @@ Datum gbt_bit_same(PG_FUNCTION_ARGS);
/* define for comparison */
static bool
-gbt_bitgt(const void *a, const void *b)
+gbt_bitgt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(bitgt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(bitgt,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_bitge(const void *a, const void *b)
+gbt_bitge(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(bitge, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(bitge,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_biteq(const void *a, const void *b)
+gbt_biteq(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(biteq, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(biteq,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_bitle(const void *a, const void *b)
+gbt_bitle(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(bitle, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(bitle,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_bitlt(const void *a, const void *b)
+gbt_bitlt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(bitlt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(bitlt,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static int32
-gbt_bitcmp(const bytea *a, const bytea *b)
+gbt_bitcmp(const void *a, const void *b, Oid collation)
{
- return
- (DatumGetInt32(DirectFunctionCall2(byteacmp, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetInt32(DirectFunctionCall2(byteacmp,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
@@ -134,7 +145,7 @@ gbt_bit_consistent(PG_FUNCTION_ARGS)
/* Oid subtype = PG_GETARG_OID(3); */
bool *recheck = (bool *) PG_GETARG_POINTER(4);
- bool retval = FALSE;
+ bool retval;
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
GBT_VARKEY_R r = gbt_var_key_readable(key);
@@ -142,12 +153,14 @@ gbt_bit_consistent(PG_FUNCTION_ARGS)
*recheck = false;
if (GIST_LEAF(entry))
- retval = gbt_var_consistent(&r, query, &strategy, TRUE, &tinfo);
+ retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
+ TRUE, &tinfo);
else
{
bytea *q = gbt_bit_xfrm((bytea *) query);
- retval = gbt_var_consistent(&r, (void *) q, &strategy, FALSE, &tinfo);
+ retval = gbt_var_consistent(&r, q, strategy, PG_GET_COLLATION(),
+ FALSE, &tinfo);
}
PG_RETURN_BOOL(retval);
}
@@ -160,7 +173,8 @@ gbt_bit_union(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int32 *size = (int *) PG_GETARG_POINTER(1);
- PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
+ PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
+ &tinfo));
}
@@ -170,7 +184,8 @@ gbt_bit_picksplit(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
- gbt_var_picksplit(entryvec, v, &tinfo);
+ gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
+ &tinfo);
PG_RETURN_POINTER(v);
}
@@ -181,7 +196,8 @@ gbt_bit_same(PG_FUNCTION_ARGS)
Datum d2 = PG_GETARG_DATUM(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
- PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
+ *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+ PG_RETURN_POINTER(result);
}
@@ -192,5 +208,6 @@ gbt_bit_penalty(PG_FUNCTION_ARGS)
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
float *result = (float *) PG_GETARG_POINTER(2);
- PG_RETURN_POINTER(gbt_var_penalty(result, o, n, &tinfo));
+ PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
+ &tinfo));
}
diff --git a/contrib/btree_gist/btree_bytea.c b/contrib/btree_gist/btree_bytea.c
index 88b4a380e8..e45509d15c 100644
--- a/contrib/btree_gist/btree_bytea.c
+++ b/contrib/btree_gist/btree_bytea.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_bytea.c,v 1.10 2009/08/04 18:49:50 tgl Exp $
+ * contrib/btree_gist/btree_bytea.c
*/
#include "btree_gist.h"
#include "btree_utils_var.h"
@@ -27,41 +27,51 @@ Datum gbt_bytea_same(PG_FUNCTION_ARGS);
/* define for comparison */
static bool
-gbt_byteagt(const void *a, const void *b)
+gbt_byteagt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(byteagt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(byteagt,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_byteage(const void *a, const void *b)
+gbt_byteage(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(byteage, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(byteage,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_byteaeq(const void *a, const void *b)
+gbt_byteaeq(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(byteaeq, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(byteaeq,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_byteale(const void *a, const void *b)
+gbt_byteale(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(byteale, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(byteale,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_bytealt(const void *a, const void *b)
+gbt_bytealt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(bytealt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(bytealt,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
-
static int32
-gbt_byteacmp(const bytea *a, const bytea *b)
+gbt_byteacmp(const void *a, const void *b, Oid collation)
{
- return
- (DatumGetInt32(DirectFunctionCall2(byteacmp, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetInt32(DirectFunctionCall2(byteacmp,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
@@ -111,7 +121,8 @@ gbt_bytea_consistent(PG_FUNCTION_ARGS)
/* All cases served by this function are exact */
*recheck = false;
- retval = gbt_var_consistent(&r, query, &strategy, GIST_LEAF(entry), &tinfo);
+ retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
+ GIST_LEAF(entry), &tinfo);
PG_RETURN_BOOL(retval);
}
@@ -123,7 +134,8 @@ gbt_bytea_union(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int32 *size = (int *) PG_GETARG_POINTER(1);
- PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
+ PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
+ &tinfo));
}
@@ -133,7 +145,8 @@ gbt_bytea_picksplit(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
- gbt_var_picksplit(entryvec, v, &tinfo);
+ gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
+ &tinfo);
PG_RETURN_POINTER(v);
}
@@ -144,7 +157,8 @@ gbt_bytea_same(PG_FUNCTION_ARGS)
Datum d2 = PG_GETARG_DATUM(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
- PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
+ *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+ PG_RETURN_POINTER(result);
}
@@ -155,5 +169,6 @@ gbt_bytea_penalty(PG_FUNCTION_ARGS)
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
float *result = (float *) PG_GETARG_POINTER(2);
- PG_RETURN_POINTER(gbt_var_penalty(result, o, n, &tinfo));
+ PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
+ &tinfo));
}
diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c
index a1efde6146..2664a26870 100644
--- a/contrib/btree_gist/btree_cash.c
+++ b/contrib/btree_gist/btree_cash.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_cash.c,v 1.11 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_cash.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -18,6 +18,7 @@ PG_FUNCTION_INFO_V1(gbt_cash_compress);
PG_FUNCTION_INFO_V1(gbt_cash_union);
PG_FUNCTION_INFO_V1(gbt_cash_picksplit);
PG_FUNCTION_INFO_V1(gbt_cash_consistent);
+PG_FUNCTION_INFO_V1(gbt_cash_distance);
PG_FUNCTION_INFO_V1(gbt_cash_penalty);
PG_FUNCTION_INFO_V1(gbt_cash_same);
@@ -25,6 +26,7 @@ Datum gbt_cash_compress(PG_FUNCTION_ARGS);
Datum gbt_cash_union(PG_FUNCTION_ARGS);
Datum gbt_cash_picksplit(PG_FUNCTION_ARGS);
Datum gbt_cash_consistent(PG_FUNCTION_ARGS);
+Datum gbt_cash_distance(PG_FUNCTION_ARGS);
Datum gbt_cash_penalty(PG_FUNCTION_ARGS);
Datum gbt_cash_same(PG_FUNCTION_ARGS);
@@ -71,6 +73,12 @@ gbt_cashkey_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
+static float8
+gbt_cash_dist(const void *a, const void *b)
+{
+ return GET_FLOAT_DISTANCE(Cash, a, b);
+}
+
static const gbtree_ninfo tinfo =
{
@@ -81,10 +89,33 @@ static const gbtree_ninfo tinfo =
gbt_casheq,
gbt_cashle,
gbt_cashlt,
- gbt_cashkey_cmp
+ gbt_cashkey_cmp,
+ gbt_cash_dist
};
+PG_FUNCTION_INFO_V1(cash_dist);
+Datum cash_dist(PG_FUNCTION_ARGS);
+Datum
+cash_dist(PG_FUNCTION_ARGS)
+{
+ Cash a = PG_GETARG_CASH(0);
+ Cash b = PG_GETARG_CASH(1);
+ Cash r;
+ Cash ra;
+
+ r = a - b;
+ ra = Abs(r);
+
+ /* Overflow check. */
+ if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("money out of range")));
+
+ PG_RETURN_CASH(ra);
+}
+
/**************************************************
* Cash ops
**************************************************/
@@ -125,6 +156,25 @@ gbt_cash_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_cash_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ Cash query = PG_GETARG_CASH(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ cashKEY *kkk = (cashKEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_cash_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_date.c b/contrib/btree_gist/btree_date.c
index d8dce91535..8a675e2f1d 100644
--- a/contrib/btree_gist/btree_date.c
+++ b/contrib/btree_gist/btree_date.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_date.c,v 1.9 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_date.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -18,6 +18,7 @@ PG_FUNCTION_INFO_V1(gbt_date_compress);
PG_FUNCTION_INFO_V1(gbt_date_union);
PG_FUNCTION_INFO_V1(gbt_date_picksplit);
PG_FUNCTION_INFO_V1(gbt_date_consistent);
+PG_FUNCTION_INFO_V1(gbt_date_distance);
PG_FUNCTION_INFO_V1(gbt_date_penalty);
PG_FUNCTION_INFO_V1(gbt_date_same);
@@ -25,6 +26,7 @@ Datum gbt_date_compress(PG_FUNCTION_ARGS);
Datum gbt_date_union(PG_FUNCTION_ARGS);
Datum gbt_date_picksplit(PG_FUNCTION_ARGS);
Datum gbt_date_consistent(PG_FUNCTION_ARGS);
+Datum gbt_date_distance(PG_FUNCTION_ARGS);
Datum gbt_date_penalty(PG_FUNCTION_ARGS);
Datum gbt_date_same(PG_FUNCTION_ARGS);
@@ -84,6 +86,17 @@ gbt_datekey_cmp(const void *a, const void *b)
return res;
}
+static float8
+gdb_date_dist(const void *a, const void *b)
+{
+ /* we assume the difference can't overflow */
+ Datum diff = DirectFunctionCall2(date_mi,
+ DateADTGetDatum(*((const DateADT *) a)),
+ DateADTGetDatum(*((const DateADT *) b)));
+
+ return (float8) Abs(DatumGetInt32(diff));
+}
+
static const gbtree_ninfo tinfo =
{
@@ -94,10 +107,25 @@ static const gbtree_ninfo tinfo =
gbt_dateeq,
gbt_datele,
gbt_datelt,
- gbt_datekey_cmp
+ gbt_datekey_cmp,
+ gdb_date_dist
};
+PG_FUNCTION_INFO_V1(date_dist);
+Datum date_dist(PG_FUNCTION_ARGS);
+Datum
+date_dist(PG_FUNCTION_ARGS)
+{
+ /* we assume the difference can't overflow */
+ Datum diff = DirectFunctionCall2(date_mi,
+ PG_GETARG_DATUM(0),
+ PG_GETARG_DATUM(1));
+
+ PG_RETURN_INT32(Abs(DatumGetInt32(diff)));
+}
+
+
/**************************************************
* date ops
**************************************************/
@@ -140,6 +168,25 @@ gbt_date_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_date_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ DateADT query = PG_GETARG_DATEADT(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_date_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c
index 7ece9ea220..266256b23c 100644
--- a/contrib/btree_gist/btree_float4.c
+++ b/contrib/btree_gist/btree_float4.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_float4.c,v 1.10 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_float4.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_float4_compress);
PG_FUNCTION_INFO_V1(gbt_float4_union);
PG_FUNCTION_INFO_V1(gbt_float4_picksplit);
PG_FUNCTION_INFO_V1(gbt_float4_consistent);
+PG_FUNCTION_INFO_V1(gbt_float4_distance);
PG_FUNCTION_INFO_V1(gbt_float4_penalty);
PG_FUNCTION_INFO_V1(gbt_float4_same);
@@ -24,6 +25,7 @@ Datum gbt_float4_compress(PG_FUNCTION_ARGS);
Datum gbt_float4_union(PG_FUNCTION_ARGS);
Datum gbt_float4_picksplit(PG_FUNCTION_ARGS);
Datum gbt_float4_consistent(PG_FUNCTION_ARGS);
+Datum gbt_float4_distance(PG_FUNCTION_ARGS);
Datum gbt_float4_penalty(PG_FUNCTION_ARGS);
Datum gbt_float4_same(PG_FUNCTION_ARGS);
@@ -70,6 +72,12 @@ gbt_float4key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
+static float8
+gbt_float4_dist(const void *a, const void *b)
+{
+ return GET_FLOAT_DISTANCE(float4, a, b);
+}
+
static const gbtree_ninfo tinfo =
{
@@ -80,10 +88,27 @@ static const gbtree_ninfo tinfo =
gbt_float4eq,
gbt_float4le,
gbt_float4lt,
- gbt_float4key_cmp
+ gbt_float4key_cmp,
+ gbt_float4_dist
};
+PG_FUNCTION_INFO_V1(float4_dist);
+Datum float4_dist(PG_FUNCTION_ARGS);
+Datum
+float4_dist(PG_FUNCTION_ARGS)
+{
+ float4 a = PG_GETARG_FLOAT4(0);
+ float4 b = PG_GETARG_FLOAT4(1);
+ float4 r;
+
+ r = a - b;
+ CHECKFLOATVAL(r, isinf(a) || isinf(b), true);
+
+ PG_RETURN_FLOAT4(Abs(r));
+}
+
+
/**************************************************
* float4 ops
**************************************************/
@@ -124,6 +149,25 @@ gbt_float4_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_float4_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ float4 query = PG_GETARG_FLOAT4(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ float4KEY *kkk = (float4KEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_float4_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c
index ab4912883d..efbee0f3e4 100644
--- a/contrib/btree_gist/btree_float8.c
+++ b/contrib/btree_gist/btree_float8.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_float8.c,v 1.10 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_float8.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_float8_compress);
PG_FUNCTION_INFO_V1(gbt_float8_union);
PG_FUNCTION_INFO_V1(gbt_float8_picksplit);
PG_FUNCTION_INFO_V1(gbt_float8_consistent);
+PG_FUNCTION_INFO_V1(gbt_float8_distance);
PG_FUNCTION_INFO_V1(gbt_float8_penalty);
PG_FUNCTION_INFO_V1(gbt_float8_same);
@@ -24,6 +25,7 @@ Datum gbt_float8_compress(PG_FUNCTION_ARGS);
Datum gbt_float8_union(PG_FUNCTION_ARGS);
Datum gbt_float8_picksplit(PG_FUNCTION_ARGS);
Datum gbt_float8_consistent(PG_FUNCTION_ARGS);
+Datum gbt_float8_distance(PG_FUNCTION_ARGS);
Datum gbt_float8_penalty(PG_FUNCTION_ARGS);
Datum gbt_float8_same(PG_FUNCTION_ARGS);
@@ -71,6 +73,19 @@ gbt_float8key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
+static float8
+gbt_float8_dist(const void *a, const void *b)
+{
+ float8 arg1 = *(const float8 *) a;
+ float8 arg2 = *(const float8 *) b;
+ float8 r;
+
+ r = arg1 - arg2;
+ CHECKFLOATVAL(r, isinf(arg1) || isinf(arg2), true);
+
+ return Abs(r);
+}
+
static const gbtree_ninfo tinfo =
{
@@ -81,10 +96,26 @@ static const gbtree_ninfo tinfo =
gbt_float8eq,
gbt_float8le,
gbt_float8lt,
- gbt_float8key_cmp
+ gbt_float8key_cmp,
+ gbt_float8_dist
};
+PG_FUNCTION_INFO_V1(float8_dist);
+Datum float8_dist(PG_FUNCTION_ARGS);
+Datum
+float8_dist(PG_FUNCTION_ARGS)
+{
+ float8 a = PG_GETARG_FLOAT8(0);
+ float8 b = PG_GETARG_FLOAT8(1);
+ float8 r;
+
+ r = a - b;
+ CHECKFLOATVAL(r, isinf(a) || isinf(b), true);
+
+ PG_RETURN_FLOAT8(Abs(r));
+}
+
/**************************************************
* float8 ops
**************************************************/
@@ -125,6 +156,25 @@ gbt_float8_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_float8_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ float8 query = PG_GETARG_FLOAT8(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ float8KEY *kkk = (float8KEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_float8_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_gist.sql.in b/contrib/btree_gist/btree_gist--1.0.sql
index e78c83cdc2..dd428995c1 100644
--- a/contrib/btree_gist/btree_gist.sql.in
+++ b/contrib/btree_gist/btree_gist--1.0.sql
@@ -1,14 +1,11 @@
-/* $PostgreSQL: pgsql/contrib/btree_gist/btree_gist.sql.in,v 1.21 2009/06/11 18:30:03 tgl Exp $ */
+/* contrib/btree_gist/btree_gist--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION gbtreekey4_in(cstring)
+CREATE FUNCTION gbtreekey4_in(cstring)
RETURNS gbtreekey4
AS 'MODULE_PATHNAME', 'gbtreekey_in'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbtreekey4_out(gbtreekey4)
+CREATE FUNCTION gbtreekey4_out(gbtreekey4)
RETURNS cstring
AS 'MODULE_PATHNAME', 'gbtreekey_out'
LANGUAGE C IMMUTABLE STRICT;
@@ -19,12 +16,12 @@ CREATE TYPE gbtreekey4 (
OUTPUT = gbtreekey4_out
);
-CREATE OR REPLACE FUNCTION gbtreekey8_in(cstring)
+CREATE FUNCTION gbtreekey8_in(cstring)
RETURNS gbtreekey8
AS 'MODULE_PATHNAME', 'gbtreekey_in'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbtreekey8_out(gbtreekey8)
+CREATE FUNCTION gbtreekey8_out(gbtreekey8)
RETURNS cstring
AS 'MODULE_PATHNAME', 'gbtreekey_out'
LANGUAGE C IMMUTABLE STRICT;
@@ -35,12 +32,12 @@ CREATE TYPE gbtreekey8 (
OUTPUT = gbtreekey8_out
);
-CREATE OR REPLACE FUNCTION gbtreekey16_in(cstring)
+CREATE FUNCTION gbtreekey16_in(cstring)
RETURNS gbtreekey16
AS 'MODULE_PATHNAME', 'gbtreekey_in'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbtreekey16_out(gbtreekey16)
+CREATE FUNCTION gbtreekey16_out(gbtreekey16)
RETURNS cstring
AS 'MODULE_PATHNAME', 'gbtreekey_out'
LANGUAGE C IMMUTABLE STRICT;
@@ -51,12 +48,12 @@ CREATE TYPE gbtreekey16 (
OUTPUT = gbtreekey16_out
);
-CREATE OR REPLACE FUNCTION gbtreekey32_in(cstring)
+CREATE FUNCTION gbtreekey32_in(cstring)
RETURNS gbtreekey32
AS 'MODULE_PATHNAME', 'gbtreekey_in'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbtreekey32_out(gbtreekey32)
+CREATE FUNCTION gbtreekey32_out(gbtreekey32)
RETURNS cstring
AS 'MODULE_PATHNAME', 'gbtreekey_out'
LANGUAGE C IMMUTABLE STRICT;
@@ -67,12 +64,12 @@ CREATE TYPE gbtreekey32 (
OUTPUT = gbtreekey32_out
);
-CREATE OR REPLACE FUNCTION gbtreekey_var_in(cstring)
+CREATE FUNCTION gbtreekey_var_in(cstring)
RETURNS gbtreekey_var
AS 'MODULE_PATHNAME', 'gbtreekey_in'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbtreekey_var_out(gbtreekey_var)
+CREATE FUNCTION gbtreekey_var_out(gbtreekey_var)
RETURNS cstring
AS 'MODULE_PATHNAME', 'gbtreekey_out'
LANGUAGE C IMMUTABLE STRICT;
@@ -84,6 +81,151 @@ CREATE TYPE gbtreekey_var (
STORAGE = EXTENDED
);
+--distance operators
+
+CREATE FUNCTION cash_dist(money, money)
+RETURNS money
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = money,
+ RIGHTARG = money,
+ PROCEDURE = cash_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION date_dist(date, date)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = date,
+ RIGHTARG = date,
+ PROCEDURE = date_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float4_dist(float4, float4)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = float4,
+ RIGHTARG = float4,
+ PROCEDURE = float4_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float8_dist(float8, float8)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = float8,
+ RIGHTARG = float8,
+ PROCEDURE = float8_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int2_dist(int2, int2)
+RETURNS int2
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = int2,
+ RIGHTARG = int2,
+ PROCEDURE = int2_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int4_dist(int4, int4)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = int4,
+ RIGHTARG = int4,
+ PROCEDURE = int4_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int8_dist(int8, int8)
+RETURNS int8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = int8,
+ RIGHTARG = int8,
+ PROCEDURE = int8_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION interval_dist(interval, interval)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = interval,
+ RIGHTARG = interval,
+ PROCEDURE = interval_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION oid_dist(oid, oid)
+RETURNS oid
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = oid,
+ RIGHTARG = oid,
+ PROCEDURE = oid_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION time_dist(time, time)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = time,
+ RIGHTARG = time,
+ PROCEDURE = time_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION ts_dist(timestamp, timestamp)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = timestamp,
+ RIGHTARG = timestamp,
+ PROCEDURE = ts_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION tstz_dist(timestamptz, timestamptz)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = timestamptz,
+ RIGHTARG = timestamptz,
+ PROCEDURE = tstz_dist,
+ COMMUTATOR = '<->'
+);
--
@@ -94,49 +236,54 @@ CREATE TYPE gbtreekey_var (
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_oid_consistent(internal,oid,int2,oid,internal)
+CREATE FUNCTION gbt_oid_consistent(internal,oid,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_oid_compress(internal)
+CREATE FUNCTION gbt_oid_distance(internal,oid,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_oid_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_decompress(internal)
+CREATE FUNCTION gbt_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_var_decompress(internal)
+CREATE FUNCTION gbt_var_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_oid_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_oid_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_oid_picksplit(internal, internal)
+CREATE FUNCTION gbt_oid_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_oid_union(bytea, internal)
+CREATE FUNCTION gbt_oid_union(bytea, internal)
RETURNS gbtreekey8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_oid_same(internal, internal, internal)
+CREATE FUNCTION gbt_oid_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_oid_ops
-DEFAULT FOR TYPE oid USING gist
+DEFAULT FOR TYPE oid USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -152,6 +299,15 @@ AS
FUNCTION 7 gbt_oid_same (internal, internal, internal),
STORAGE gbtreekey8;
+-- Add operators that are new in 9.1. We do it like this, leaving them
+-- "loose" in the operator family rather than bound into the opclass, because
+-- that's the only state that can be reproduced during an upgrade from 9.0.
+
+ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD
+ OPERATOR 6 <> (oid, oid) ,
+ OPERATOR 15 <-> (oid, oid) FOR ORDER BY pg_catalog.oid_ops ,
+ FUNCTION 8 (oid, oid) gbt_oid_distance (internal, oid, int2, oid) ;
+
--
--
@@ -161,39 +317,44 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_int2_consistent(internal,int2,int2,oid,internal)
+CREATE FUNCTION gbt_int2_consistent(internal,int2,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int2_compress(internal)
+CREATE FUNCTION gbt_int2_distance(internal,int2,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int2_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int2_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_int2_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int2_picksplit(internal, internal)
+CREATE FUNCTION gbt_int2_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int2_union(bytea, internal)
+CREATE FUNCTION gbt_int2_union(bytea, internal)
RETURNS gbtreekey4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int2_same(internal, internal, internal)
+CREATE FUNCTION gbt_int2_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_int2_ops
-DEFAULT FOR TYPE int2 USING gist
+DEFAULT FOR TYPE int2 USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -209,6 +370,12 @@ AS
FUNCTION 7 gbt_int2_same (internal, internal, internal),
STORAGE gbtreekey4;
+ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD
+ OPERATOR 6 <> (int2, int2) ,
+ OPERATOR 15 <-> (int2, int2) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (int2, int2) gbt_int2_distance (internal, int2, int2, oid) ;
+
+
--
--
--
@@ -217,39 +384,44 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_int4_consistent(internal,int4,int2,oid,internal)
+CREATE FUNCTION gbt_int4_consistent(internal,int4,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int4_compress(internal)
+CREATE FUNCTION gbt_int4_distance(internal,int4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int4_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int4_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_int4_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int4_picksplit(internal, internal)
+CREATE FUNCTION gbt_int4_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int4_union(bytea, internal)
+CREATE FUNCTION gbt_int4_union(bytea, internal)
RETURNS gbtreekey8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int4_same(internal, internal, internal)
+CREATE FUNCTION gbt_int4_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_int4_ops
-DEFAULT FOR TYPE int4 USING gist
+DEFAULT FOR TYPE int4 USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -265,6 +437,12 @@ AS
FUNCTION 7 gbt_int4_same (internal, internal, internal),
STORAGE gbtreekey8;
+ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD
+ OPERATOR 6 <> (int4, int4) ,
+ OPERATOR 15 <-> (int4, int4) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (int4, int4) gbt_int4_distance (internal, int4, int2, oid) ;
+
+
--
--
--
@@ -273,39 +451,44 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_int8_consistent(internal,int8,int2,oid,internal)
+CREATE FUNCTION gbt_int8_consistent(internal,int8,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int8_compress(internal)
+CREATE FUNCTION gbt_int8_distance(internal,int8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int8_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int8_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_int8_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int8_picksplit(internal, internal)
+CREATE FUNCTION gbt_int8_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int8_union(bytea, internal)
+CREATE FUNCTION gbt_int8_union(bytea, internal)
RETURNS gbtreekey16
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_int8_same(internal, internal, internal)
+CREATE FUNCTION gbt_int8_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_int8_ops
-DEFAULT FOR TYPE int8 USING gist
+DEFAULT FOR TYPE int8 USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -321,6 +504,11 @@ AS
FUNCTION 7 gbt_int8_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD
+ OPERATOR 6 <> (int8, int8) ,
+ OPERATOR 15 <-> (int8, int8) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (int8, int8) gbt_int8_distance (internal, int8, int2, oid) ;
+
--
--
@@ -330,39 +518,44 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_float4_consistent(internal,float4,int2,oid,internal)
+CREATE FUNCTION gbt_float4_consistent(internal,float4,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float4_compress(internal)
+CREATE FUNCTION gbt_float4_distance(internal,float4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_float4_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float4_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_float4_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float4_picksplit(internal, internal)
+CREATE FUNCTION gbt_float4_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float4_union(bytea, internal)
+CREATE FUNCTION gbt_float4_union(bytea, internal)
RETURNS gbtreekey8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float4_same(internal, internal, internal)
+CREATE FUNCTION gbt_float4_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_float4_ops
-DEFAULT FOR TYPE float4 USING gist
+DEFAULT FOR TYPE float4 USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -378,7 +571,10 @@ AS
FUNCTION 7 gbt_float4_same (internal, internal, internal),
STORAGE gbtreekey8;
-
+ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD
+ OPERATOR 6 <> (float4, float4) ,
+ OPERATOR 15 <-> (float4, float4) FOR ORDER BY pg_catalog.float_ops ,
+ FUNCTION 8 (float4, float4) gbt_float4_distance (internal, float4, int2, oid) ;
--
@@ -389,39 +585,44 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_float8_consistent(internal,float8,int2,oid,internal)
+CREATE FUNCTION gbt_float8_consistent(internal,float8,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float8_compress(internal)
+CREATE FUNCTION gbt_float8_distance(internal,float8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_float8_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float8_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_float8_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float8_picksplit(internal, internal)
+CREATE FUNCTION gbt_float8_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float8_union(bytea, internal)
+CREATE FUNCTION gbt_float8_union(bytea, internal)
RETURNS gbtreekey16
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_float8_same(internal, internal, internal)
+CREATE FUNCTION gbt_float8_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_float8_ops
-DEFAULT FOR TYPE float8 USING gist
+DEFAULT FOR TYPE float8 USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -437,58 +638,73 @@ AS
FUNCTION 7 gbt_float8_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD
+ OPERATOR 6 <> (float8, float8) ,
+ OPERATOR 15 <-> (float8, float8) FOR ORDER BY pg_catalog.float_ops ,
+ FUNCTION 8 (float8, float8) gbt_float8_distance (internal, float8, int2, oid) ;
+
--
--
--
-- timestamp ops
---
+--
--
--
-CREATE OR REPLACE FUNCTION gbt_ts_consistent(internal,timestamp,int2,oid,internal)
+CREATE FUNCTION gbt_ts_consistent(internal,timestamp,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_tstz_consistent(internal,timestamptz,int2,oid,internal)
+CREATE FUNCTION gbt_ts_distance(internal,timestamp,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_tstz_consistent(internal,timestamptz,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_ts_compress(internal)
+
+CREATE FUNCTION gbt_tstz_distance(internal,timestamptz,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_ts_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_tstz_compress(internal)
+CREATE FUNCTION gbt_tstz_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_ts_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_ts_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_ts_picksplit(internal, internal)
+
+CREATE FUNCTION gbt_ts_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_ts_union(bytea, internal)
+
+CREATE FUNCTION gbt_ts_union(bytea, internal)
RETURNS gbtreekey16
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_ts_same(internal, internal, internal)
+CREATE FUNCTION gbt_ts_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_timestamp_ops
-DEFAULT FOR TYPE timestamp USING gist
+DEFAULT FOR TYPE timestamp USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -504,10 +720,15 @@ AS
FUNCTION 7 gbt_ts_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD
+ OPERATOR 6 <> (timestamp, timestamp) ,
+ OPERATOR 15 <-> (timestamp, timestamp) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (timestamp, timestamp) gbt_ts_distance (internal, timestamp, int2, oid) ;
+
-- Create the operator class
CREATE OPERATOR CLASS gist_timestamptz_ops
-DEFAULT FOR TYPE timestamptz USING gist
+DEFAULT FOR TYPE timestamptz USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -523,58 +744,68 @@ AS
FUNCTION 7 gbt_ts_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD
+ OPERATOR 6 <> (timestamptz, timestamptz) ,
+ OPERATOR 15 <-> (timestamptz, timestamptz) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (timestamptz, timestamptz) gbt_tstz_distance (internal, timestamptz, int2, oid) ;
+
--
--
--
-- time ops
---
+--
--
--
-CREATE OR REPLACE FUNCTION gbt_time_consistent(internal,time,int2,oid,internal)
+CREATE FUNCTION gbt_time_consistent(internal,time,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_timetz_consistent(internal,timetz,int2,oid,internal)
+CREATE FUNCTION gbt_time_distance(internal,time,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_timetz_consistent(internal,timetz,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_time_compress(internal)
+CREATE FUNCTION gbt_time_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_timetz_compress(internal)
+CREATE FUNCTION gbt_timetz_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_time_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_time_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_time_picksplit(internal, internal)
+
+CREATE FUNCTION gbt_time_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_time_union(bytea, internal)
+
+CREATE FUNCTION gbt_time_union(bytea, internal)
RETURNS gbtreekey16
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_time_same(internal, internal, internal)
+CREATE FUNCTION gbt_time_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_time_ops
-DEFAULT FOR TYPE time USING gist
+DEFAULT FOR TYPE time USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -590,8 +821,14 @@ AS
FUNCTION 7 gbt_time_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
+ OPERATOR 6 <> (time, time) ,
+ OPERATOR 15 <-> (time, time) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (time, time) gbt_time_distance (internal, time, int2, oid) ;
+
+
CREATE OPERATOR CLASS gist_timetz_ops
-DEFAULT FOR TYPE timetz USING gist
+DEFAULT FOR TYPE timetz USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -607,48 +844,56 @@ AS
FUNCTION 7 gbt_time_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD
+ OPERATOR 6 <> (timetz, timetz) ;
+
--
--
--
-- date ops
---
+--
--
--
-CREATE OR REPLACE FUNCTION gbt_date_consistent(internal,date,int2,oid,internal)
+CREATE FUNCTION gbt_date_consistent(internal,date,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_date_compress(internal)
+CREATE FUNCTION gbt_date_distance(internal,date,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_date_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_date_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_date_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_date_picksplit(internal, internal)
+
+CREATE FUNCTION gbt_date_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_date_union(bytea, internal)
+
+CREATE FUNCTION gbt_date_union(bytea, internal)
RETURNS gbtreekey8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_date_same(internal, internal, internal)
+CREATE FUNCTION gbt_date_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_date_ops
-DEFAULT FOR TYPE date USING gist
+DEFAULT FOR TYPE date USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -664,53 +909,63 @@ AS
FUNCTION 7 gbt_date_same (internal, internal, internal),
STORAGE gbtreekey8;
+ALTER OPERATOR FAMILY gist_date_ops USING gist ADD
+ OPERATOR 6 <> (date, date) ,
+ OPERATOR 15 <-> (date, date) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (date, date) gbt_date_distance (internal, date, int2, oid) ;
+
--
--
--
-- interval ops
---
+--
--
--
-CREATE OR REPLACE FUNCTION gbt_intv_consistent(internal,interval,int2,oid,internal)
+CREATE FUNCTION gbt_intv_consistent(internal,interval,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_intv_compress(internal)
+CREATE FUNCTION gbt_intv_distance(internal,interval,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_intv_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_intv_decompress(internal)
+CREATE FUNCTION gbt_intv_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_intv_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_intv_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_intv_picksplit(internal, internal)
+
+CREATE FUNCTION gbt_intv_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gbt_intv_union(bytea, internal)
+
+CREATE FUNCTION gbt_intv_union(bytea, internal)
RETURNS gbtreekey32
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_intv_same(internal, internal, internal)
+CREATE FUNCTION gbt_intv_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_interval_ops
-DEFAULT FOR TYPE interval USING gist
+DEFAULT FOR TYPE interval USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -726,6 +981,12 @@ AS
FUNCTION 7 gbt_intv_same (internal, internal, internal),
STORAGE gbtreekey32;
+ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD
+ OPERATOR 6 <> (interval, interval) ,
+ OPERATOR 15 <-> (interval, interval) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (interval, interval) gbt_intv_distance (internal, interval, int2, oid) ;
+
+
--
--
--
@@ -734,39 +995,44 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_cash_consistent(internal,money,int2,oid,internal)
+CREATE FUNCTION gbt_cash_consistent(internal,money,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_cash_compress(internal)
+CREATE FUNCTION gbt_cash_distance(internal,money,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_cash_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_cash_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_cash_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_cash_picksplit(internal, internal)
+CREATE FUNCTION gbt_cash_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_cash_union(bytea, internal)
+CREATE FUNCTION gbt_cash_union(bytea, internal)
RETURNS gbtreekey8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_cash_same(internal, internal, internal)
+CREATE FUNCTION gbt_cash_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_cash_ops
-DEFAULT FOR TYPE money USING gist
+DEFAULT FOR TYPE money USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -782,6 +1048,12 @@ AS
FUNCTION 7 gbt_cash_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD
+ OPERATOR 6 <> (money, money) ,
+ OPERATOR 15 <-> (money, money) FOR ORDER BY pg_catalog.money_ops ,
+ FUNCTION 8 (money, money) gbt_cash_distance (internal, money, int2, oid) ;
+
+
--
--
--
@@ -790,39 +1062,39 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_macad_consistent(internal,macaddr,int2,oid,internal)
+CREATE FUNCTION gbt_macad_consistent(internal,macaddr,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_macad_compress(internal)
+CREATE FUNCTION gbt_macad_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_macad_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_macad_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_macad_picksplit(internal, internal)
+CREATE FUNCTION gbt_macad_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_macad_union(bytea, internal)
+CREATE FUNCTION gbt_macad_union(bytea, internal)
RETURNS gbtreekey16
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_macad_same(internal, internal, internal)
+CREATE FUNCTION gbt_macad_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_macaddr_ops
-DEFAULT FOR TYPE macaddr USING gist
+DEFAULT FOR TYPE macaddr USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -838,6 +1110,8 @@ AS
FUNCTION 7 gbt_macad_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD
+ OPERATOR 6 <> (macaddr, macaddr) ;
--
@@ -848,49 +1122,49 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_text_consistent(internal,text,int2,oid,internal)
+CREATE FUNCTION gbt_text_consistent(internal,text,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bpchar_consistent(internal,bpchar,int2,oid,internal)
+CREATE FUNCTION gbt_bpchar_consistent(internal,bpchar,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_text_compress(internal)
+CREATE FUNCTION gbt_text_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bpchar_compress(internal)
+CREATE FUNCTION gbt_bpchar_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_text_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_text_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_text_picksplit(internal, internal)
+CREATE FUNCTION gbt_text_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_text_union(bytea, internal)
+CREATE FUNCTION gbt_text_union(bytea, internal)
RETURNS gbtreekey_var
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_text_same(internal, internal, internal)
+CREATE FUNCTION gbt_text_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_text_ops
-DEFAULT FOR TYPE text USING gist
+DEFAULT FOR TYPE text USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -904,12 +1178,15 @@ AS
FUNCTION 5 gbt_text_penalty (internal, internal, internal),
FUNCTION 6 gbt_text_picksplit (internal, internal),
FUNCTION 7 gbt_text_same (internal, internal, internal),
- STORAGE gbtreekey_var;
+ STORAGE gbtreekey_var;
+
+ALTER OPERATOR FAMILY gist_text_ops USING gist ADD
+ OPERATOR 6 <> (text, text) ;
---- Create the operator class
CREATE OPERATOR CLASS gist_bpchar_ops
-DEFAULT FOR TYPE bpchar USING gist
+DEFAULT FOR TYPE bpchar USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -923,8 +1200,10 @@ AS
FUNCTION 5 gbt_text_penalty (internal, internal, internal),
FUNCTION 6 gbt_text_picksplit (internal, internal),
FUNCTION 7 gbt_text_same (internal, internal, internal),
- STORAGE gbtreekey_var;
+ STORAGE gbtreekey_var;
+ALTER OPERATOR FAMILY gist_bpchar_ops USING gist ADD
+ OPERATOR 6 <> (bpchar, bpchar) ;
--
@@ -934,39 +1213,39 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_bytea_consistent(internal,bytea,int2,oid,internal)
+CREATE FUNCTION gbt_bytea_consistent(internal,bytea,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bytea_compress(internal)
+CREATE FUNCTION gbt_bytea_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bytea_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_bytea_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bytea_picksplit(internal, internal)
+CREATE FUNCTION gbt_bytea_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bytea_union(bytea, internal)
+CREATE FUNCTION gbt_bytea_union(bytea, internal)
RETURNS gbtreekey_var
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bytea_same(internal, internal, internal)
+CREATE FUNCTION gbt_bytea_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_bytea_ops
-DEFAULT FOR TYPE bytea USING gist
+DEFAULT FOR TYPE bytea USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -980,7 +1259,10 @@ AS
FUNCTION 5 gbt_bytea_penalty (internal, internal, internal),
FUNCTION 6 gbt_bytea_picksplit (internal, internal),
FUNCTION 7 gbt_bytea_same (internal, internal, internal),
- STORAGE gbtreekey_var;
+ STORAGE gbtreekey_var;
+
+ALTER OPERATOR FAMILY gist_bytea_ops USING gist ADD
+ OPERATOR 6 <> (bytea, bytea) ;
--
@@ -991,39 +1273,39 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_numeric_consistent(internal,numeric,int2,oid,internal)
+CREATE FUNCTION gbt_numeric_consistent(internal,numeric,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_numeric_compress(internal)
+CREATE FUNCTION gbt_numeric_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_numeric_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_numeric_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_numeric_picksplit(internal, internal)
+CREATE FUNCTION gbt_numeric_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_numeric_union(bytea, internal)
+CREATE FUNCTION gbt_numeric_union(bytea, internal)
RETURNS gbtreekey_var
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_numeric_same(internal, internal, internal)
+CREATE FUNCTION gbt_numeric_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_numeric_ops
-DEFAULT FOR TYPE numeric USING gist
+DEFAULT FOR TYPE numeric USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -1037,7 +1319,11 @@ AS
FUNCTION 5 gbt_numeric_penalty (internal, internal, internal),
FUNCTION 6 gbt_numeric_picksplit (internal, internal),
FUNCTION 7 gbt_numeric_same (internal, internal, internal),
- STORAGE gbtreekey_var;
+ STORAGE gbtreekey_var;
+
+ALTER OPERATOR FAMILY gist_numeric_ops USING gist ADD
+ OPERATOR 6 <> (numeric, numeric) ;
+
--
--
@@ -1046,39 +1332,39 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_bit_consistent(internal,bit,int2,oid,internal)
+CREATE FUNCTION gbt_bit_consistent(internal,bit,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bit_compress(internal)
+CREATE FUNCTION gbt_bit_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bit_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_bit_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bit_picksplit(internal, internal)
+CREATE FUNCTION gbt_bit_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bit_union(bytea, internal)
+CREATE FUNCTION gbt_bit_union(bytea, internal)
RETURNS gbtreekey_var
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_bit_same(internal, internal, internal)
+CREATE FUNCTION gbt_bit_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_bit_ops
-DEFAULT FOR TYPE bit USING gist
+DEFAULT FOR TYPE bit USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -1092,12 +1378,15 @@ AS
FUNCTION 5 gbt_bit_penalty (internal, internal, internal),
FUNCTION 6 gbt_bit_picksplit (internal, internal),
FUNCTION 7 gbt_bit_same (internal, internal, internal),
- STORAGE gbtreekey_var;
+ STORAGE gbtreekey_var;
+
+ALTER OPERATOR FAMILY gist_bit_ops USING gist ADD
+ OPERATOR 6 <> (bit, bit) ;
-- Create the operator class
CREATE OPERATOR CLASS gist_vbit_ops
-DEFAULT FOR TYPE varbit USING gist
+DEFAULT FOR TYPE varbit USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -1111,8 +1400,10 @@ AS
FUNCTION 5 gbt_bit_penalty (internal, internal, internal),
FUNCTION 6 gbt_bit_picksplit (internal, internal),
FUNCTION 7 gbt_bit_same (internal, internal, internal),
- STORAGE gbtreekey_var;
+ STORAGE gbtreekey_var;
+ALTER OPERATOR FAMILY gist_vbit_ops USING gist ADD
+ OPERATOR 6 <> (varbit, varbit) ;
--
@@ -1123,39 +1414,39 @@ AS
--
--
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gbt_inet_consistent(internal,inet,int2,oid,internal)
+CREATE FUNCTION gbt_inet_consistent(internal,inet,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_inet_compress(internal)
+CREATE FUNCTION gbt_inet_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_inet_penalty(internal,internal,internal)
+CREATE FUNCTION gbt_inet_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_inet_picksplit(internal, internal)
+CREATE FUNCTION gbt_inet_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_inet_union(bytea, internal)
+CREATE FUNCTION gbt_inet_union(bytea, internal)
RETURNS gbtreekey16
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gbt_inet_same(internal, internal, internal)
+CREATE FUNCTION gbt_inet_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Create the operator class
CREATE OPERATOR CLASS gist_inet_ops
-DEFAULT FOR TYPE inet USING gist
+DEFAULT FOR TYPE inet USING gist
AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
@@ -1171,9 +1462,13 @@ AS
FUNCTION 7 gbt_inet_same (internal, internal, internal),
STORAGE gbtreekey16;
+ALTER OPERATOR FAMILY gist_inet_ops USING gist ADD
+ OPERATOR 6 <> (inet, inet) ;
+
+
-- Create the operator class
CREATE OPERATOR CLASS gist_cidr_ops
-DEFAULT FOR TYPE cidr USING gist
+DEFAULT FOR TYPE cidr USING gist
AS
OPERATOR 1 < (inet, inet) ,
OPERATOR 2 <= (inet, inet) ,
@@ -1188,3 +1483,6 @@ AS
FUNCTION 6 gbt_inet_picksplit (internal, internal),
FUNCTION 7 gbt_inet_same (internal, internal, internal),
STORAGE gbtreekey16;
+
+ALTER OPERATOR FAMILY gist_cidr_ops USING gist ADD
+ OPERATOR 6 <> (inet, inet) ;
diff --git a/contrib/btree_gist/btree_gist--unpackaged--1.0.sql b/contrib/btree_gist/btree_gist--unpackaged--1.0.sql
new file mode 100644
index 0000000000..00252bf7c3
--- /dev/null
+++ b/contrib/btree_gist/btree_gist--unpackaged--1.0.sql
@@ -0,0 +1,476 @@
+/* contrib/btree_gist/btree_gist--unpackaged--1.0.sql */
+
+ALTER EXTENSION btree_gist ADD type gbtreekey4;
+ALTER EXTENSION btree_gist ADD function gbtreekey4_in(cstring);
+ALTER EXTENSION btree_gist ADD function gbtreekey4_out(gbtreekey4);
+ALTER EXTENSION btree_gist ADD type gbtreekey8;
+ALTER EXTENSION btree_gist ADD function gbtreekey8_in(cstring);
+ALTER EXTENSION btree_gist ADD function gbtreekey8_out(gbtreekey8);
+ALTER EXTENSION btree_gist ADD type gbtreekey16;
+ALTER EXTENSION btree_gist ADD function gbtreekey16_in(cstring);
+ALTER EXTENSION btree_gist ADD function gbtreekey16_out(gbtreekey16);
+ALTER EXTENSION btree_gist ADD type gbtreekey32;
+ALTER EXTENSION btree_gist ADD function gbtreekey32_in(cstring);
+ALTER EXTENSION btree_gist ADD function gbtreekey32_out(gbtreekey32);
+ALTER EXTENSION btree_gist ADD type gbtreekey_var;
+ALTER EXTENSION btree_gist ADD function gbtreekey_var_in(cstring);
+ALTER EXTENSION btree_gist ADD function gbtreekey_var_out(gbtreekey_var);
+ALTER EXTENSION btree_gist ADD function gbt_oid_consistent(internal,oid,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_oid_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_decompress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_var_decompress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_oid_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_oid_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_oid_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_oid_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_oid_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_oid_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_int2_consistent(internal,smallint,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int2_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_int2_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int2_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int2_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int2_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_int2_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_int2_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_int4_consistent(internal,integer,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int4_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_int4_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int4_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int4_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int4_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_int4_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_int4_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_int8_consistent(internal,bigint,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int8_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_int8_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int8_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int8_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_int8_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_int8_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_int8_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_float4_consistent(internal,real,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float4_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_float4_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float4_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float4_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float4_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_float4_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_float4_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_float8_consistent(internal,double precision,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float8_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_float8_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float8_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float8_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_float8_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_float8_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_float8_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_ts_consistent(internal,timestamp without time zone,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_tstz_consistent(internal,timestamp with time zone,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_ts_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_tstz_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_ts_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_ts_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_ts_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_ts_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_timestamp_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_timestamp_ops using gist;
+ALTER EXTENSION btree_gist ADD operator family gist_timestamptz_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_timestamptz_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_time_consistent(internal,time without time zone,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_timetz_consistent(internal,time with time zone,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_time_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_timetz_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_time_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_time_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_time_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_time_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_time_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_time_ops using gist;
+ALTER EXTENSION btree_gist ADD operator family gist_timetz_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_timetz_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_date_consistent(internal,date,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_date_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_date_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_date_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_date_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_date_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_date_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_date_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_intv_consistent(internal,interval,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_intv_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_intv_decompress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_intv_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_intv_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_intv_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_intv_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_interval_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_interval_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_cash_consistent(internal,money,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_cash_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_cash_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_cash_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_cash_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_cash_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_cash_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_cash_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_macad_consistent(internal,macaddr,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_macad_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_macad_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_macad_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_macad_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_macad_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_macaddr_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_macaddr_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_text_consistent(internal,text,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bpchar_consistent(internal,character,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_text_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_bpchar_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_text_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_text_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_text_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_text_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_text_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_text_ops using gist;
+ALTER EXTENSION btree_gist ADD operator family gist_bpchar_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_bpchar_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_bytea_consistent(internal,bytea,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bytea_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_bytea_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bytea_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bytea_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bytea_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_bytea_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_bytea_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_numeric_consistent(internal,numeric,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_numeric_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_numeric_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_numeric_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_numeric_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_numeric_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_numeric_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_numeric_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_bit_consistent(internal,bit,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bit_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_bit_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bit_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bit_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_bit_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_bit_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_bit_ops using gist;
+ALTER EXTENSION btree_gist ADD operator family gist_vbit_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_vbit_ops using gist;
+ALTER EXTENSION btree_gist ADD function gbt_inet_consistent(internal,inet,smallint,oid,internal);
+ALTER EXTENSION btree_gist ADD function gbt_inet_compress(internal);
+ALTER EXTENSION btree_gist ADD function gbt_inet_penalty(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_inet_picksplit(internal,internal);
+ALTER EXTENSION btree_gist ADD function gbt_inet_union(bytea,internal);
+ALTER EXTENSION btree_gist ADD function gbt_inet_same(internal,internal,internal);
+ALTER EXTENSION btree_gist ADD operator family gist_inet_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_inet_ops using gist;
+ALTER EXTENSION btree_gist ADD operator family gist_cidr_ops using gist;
+ALTER EXTENSION btree_gist ADD operator class gist_cidr_ops using gist;
+
+
+-- Add functions and operators that are new in 9.1
+
+--distance operators
+
+CREATE FUNCTION cash_dist(money, money)
+RETURNS money
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = money,
+ RIGHTARG = money,
+ PROCEDURE = cash_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION date_dist(date, date)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = date,
+ RIGHTARG = date,
+ PROCEDURE = date_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float4_dist(float4, float4)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = float4,
+ RIGHTARG = float4,
+ PROCEDURE = float4_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION float8_dist(float8, float8)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = float8,
+ RIGHTARG = float8,
+ PROCEDURE = float8_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int2_dist(int2, int2)
+RETURNS int2
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = int2,
+ RIGHTARG = int2,
+ PROCEDURE = int2_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int4_dist(int4, int4)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = int4,
+ RIGHTARG = int4,
+ PROCEDURE = int4_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION int8_dist(int8, int8)
+RETURNS int8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = int8,
+ RIGHTARG = int8,
+ PROCEDURE = int8_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION interval_dist(interval, interval)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = interval,
+ RIGHTARG = interval,
+ PROCEDURE = interval_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION oid_dist(oid, oid)
+RETURNS oid
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = oid,
+ RIGHTARG = oid,
+ PROCEDURE = oid_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION time_dist(time, time)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = time,
+ RIGHTARG = time,
+ PROCEDURE = time_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION ts_dist(timestamp, timestamp)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = timestamp,
+ RIGHTARG = timestamp,
+ PROCEDURE = ts_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION tstz_dist(timestamptz, timestamptz)
+RETURNS interval
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE OPERATOR <-> (
+ LEFTARG = timestamptz,
+ RIGHTARG = timestamptz,
+ PROCEDURE = tstz_dist,
+ COMMUTATOR = '<->'
+);
+
+-- Support functions for distance operators
+
+CREATE FUNCTION gbt_oid_distance(internal,oid,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int2_distance(internal,int2,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int4_distance(internal,int4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_int8_distance(internal,int8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_float4_distance(internal,float4,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_float8_distance(internal,float8,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_ts_distance(internal,timestamp,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_tstz_distance(internal,timestamptz,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_time_distance(internal,time,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_date_distance(internal,date,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_intv_distance(internal,interval,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_cash_distance(internal,money,int2,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+
+-- Add new-in-9.1 stuff to the operator classes.
+
+ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD
+ OPERATOR 6 <> (oid, oid) ,
+ OPERATOR 15 <-> (oid, oid) FOR ORDER BY pg_catalog.oid_ops ,
+ FUNCTION 8 (oid, oid) gbt_oid_distance (internal, oid, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD
+ OPERATOR 6 <> (int2, int2) ,
+ OPERATOR 15 <-> (int2, int2) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (int2, int2) gbt_int2_distance (internal, int2, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD
+ OPERATOR 6 <> (int4, int4) ,
+ OPERATOR 15 <-> (int4, int4) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (int4, int4) gbt_int4_distance (internal, int4, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD
+ OPERATOR 6 <> (int8, int8) ,
+ OPERATOR 15 <-> (int8, int8) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (int8, int8) gbt_int8_distance (internal, int8, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD
+ OPERATOR 6 <> (float4, float4) ,
+ OPERATOR 15 <-> (float4, float4) FOR ORDER BY pg_catalog.float_ops ,
+ FUNCTION 8 (float4, float4) gbt_float4_distance (internal, float4, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD
+ OPERATOR 6 <> (float8, float8) ,
+ OPERATOR 15 <-> (float8, float8) FOR ORDER BY pg_catalog.float_ops ,
+ FUNCTION 8 (float8, float8) gbt_float8_distance (internal, float8, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD
+ OPERATOR 6 <> (timestamp, timestamp) ,
+ OPERATOR 15 <-> (timestamp, timestamp) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (timestamp, timestamp) gbt_ts_distance (internal, timestamp, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD
+ OPERATOR 6 <> (timestamptz, timestamptz) ,
+ OPERATOR 15 <-> (timestamptz, timestamptz) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (timestamptz, timestamptz) gbt_tstz_distance (internal, timestamptz, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
+ OPERATOR 6 <> (time, time) ,
+ OPERATOR 15 <-> (time, time) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (time, time) gbt_time_distance (internal, time, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD
+ OPERATOR 6 <> (timetz, timetz) ;
+
+ALTER OPERATOR FAMILY gist_date_ops USING gist ADD
+ OPERATOR 6 <> (date, date) ,
+ OPERATOR 15 <-> (date, date) FOR ORDER BY pg_catalog.integer_ops ,
+ FUNCTION 8 (date, date) gbt_date_distance (internal, date, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD
+ OPERATOR 6 <> (interval, interval) ,
+ OPERATOR 15 <-> (interval, interval) FOR ORDER BY pg_catalog.interval_ops ,
+ FUNCTION 8 (interval, interval) gbt_intv_distance (internal, interval, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD
+ OPERATOR 6 <> (money, money) ,
+ OPERATOR 15 <-> (money, money) FOR ORDER BY pg_catalog.money_ops ,
+ FUNCTION 8 (money, money) gbt_cash_distance (internal, money, int2, oid) ;
+
+ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD
+ OPERATOR 6 <> (macaddr, macaddr) ;
+
+ALTER OPERATOR FAMILY gist_text_ops USING gist ADD
+ OPERATOR 6 <> (text, text) ;
+
+ALTER OPERATOR FAMILY gist_bpchar_ops USING gist ADD
+ OPERATOR 6 <> (bpchar, bpchar) ;
+
+ALTER OPERATOR FAMILY gist_bytea_ops USING gist ADD
+ OPERATOR 6 <> (bytea, bytea) ;
+
+ALTER OPERATOR FAMILY gist_numeric_ops USING gist ADD
+ OPERATOR 6 <> (numeric, numeric) ;
+
+ALTER OPERATOR FAMILY gist_bit_ops USING gist ADD
+ OPERATOR 6 <> (bit, bit) ;
+
+ALTER OPERATOR FAMILY gist_vbit_ops USING gist ADD
+ OPERATOR 6 <> (varbit, varbit) ;
+
+ALTER OPERATOR FAMILY gist_inet_ops USING gist ADD
+ OPERATOR 6 <> (inet, inet) ;
+
+ALTER OPERATOR FAMILY gist_cidr_ops USING gist ADD
+ OPERATOR 6 <> (inet, inet) ;
diff --git a/contrib/btree_gist/btree_gist.c b/contrib/btree_gist/btree_gist.c
index f109de4a64..7e1c7e054c 100644
--- a/contrib/btree_gist/btree_gist.c
+++ b/contrib/btree_gist/btree_gist.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_gist.c,v 1.13 2009/06/11 14:48:50 momjian Exp $
+ * contrib/btree_gist/btree_gist.c
*/
#include "btree_gist.h"
diff --git a/contrib/btree_gist/btree_gist.control b/contrib/btree_gist/btree_gist.control
new file mode 100644
index 0000000000..10e2f949c1
--- /dev/null
+++ b/contrib/btree_gist/btree_gist.control
@@ -0,0 +1,5 @@
+# btree_gist extension
+comment = 'support for indexing common datatypes in GiST'
+default_version = '1.0'
+module_pathname = '$libdir/btree_gist'
+relocatable = true
diff --git a/contrib/btree_gist/btree_gist.h b/contrib/btree_gist/btree_gist.h
index 425ce8cff4..058a3f99e9 100644
--- a/contrib/btree_gist/btree_gist.h
+++ b/contrib/btree_gist/btree_gist.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_gist.h,v 1.9 2009/06/11 14:48:50 momjian Exp $
+ * contrib/btree_gist/btree_gist.h
*/
#ifndef __BTREE_GIST_H__
#define __BTREE_GIST_H__
@@ -9,6 +9,8 @@
#include "access/itup.h"
#include "access/nbtree.h"
+#define BtreeGistNotEqualStrategyNumber 6
+
/* indexed types */
enum gbtree_type
diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c
index a8d18c578b..690a01cbc7 100644
--- a/contrib/btree_gist/btree_inet.c
+++ b/contrib/btree_gist/btree_inet.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_inet.c,v 1.12 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_inet.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -84,7 +84,8 @@ static const gbtree_ninfo tinfo =
gbt_ineteq,
gbt_inetle,
gbt_inetlt,
- gbt_inetkey_cmp
+ gbt_inetkey_cmp,
+ NULL
};
diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c
index 2be4c40aa8..7841145b53 100644
--- a/contrib/btree_gist/btree_int2.c
+++ b/contrib/btree_gist/btree_int2.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_int2.c,v 1.10 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_int2.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int2_compress);
PG_FUNCTION_INFO_V1(gbt_int2_union);
PG_FUNCTION_INFO_V1(gbt_int2_picksplit);
PG_FUNCTION_INFO_V1(gbt_int2_consistent);
+PG_FUNCTION_INFO_V1(gbt_int2_distance);
PG_FUNCTION_INFO_V1(gbt_int2_penalty);
PG_FUNCTION_INFO_V1(gbt_int2_same);
@@ -24,6 +25,7 @@ Datum gbt_int2_compress(PG_FUNCTION_ARGS);
Datum gbt_int2_union(PG_FUNCTION_ARGS);
Datum gbt_int2_picksplit(PG_FUNCTION_ARGS);
Datum gbt_int2_consistent(PG_FUNCTION_ARGS);
+Datum gbt_int2_distance(PG_FUNCTION_ARGS);
Datum gbt_int2_penalty(PG_FUNCTION_ARGS);
Datum gbt_int2_same(PG_FUNCTION_ARGS);
@@ -70,6 +72,12 @@ gbt_int2key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
+static float8
+gbt_int2_dist(const void *a, const void *b)
+{
+ return GET_FLOAT_DISTANCE(int2, a, b);
+}
+
static const gbtree_ninfo tinfo =
{
@@ -80,12 +88,32 @@ static const gbtree_ninfo tinfo =
gbt_int2eq,
gbt_int2le,
gbt_int2lt,
- gbt_int2key_cmp
+ gbt_int2key_cmp,
+ gbt_int2_dist
};
+PG_FUNCTION_INFO_V1(int2_dist);
+Datum int2_dist(PG_FUNCTION_ARGS);
+Datum
+int2_dist(PG_FUNCTION_ARGS)
+{
+ int2 a = PG_GETARG_INT16(0);
+ int2 b = PG_GETARG_INT16(1);
+ int2 r;
+ int2 ra;
+
+ r = a - b;
+ ra = Abs(r);
+ /* Overflow check. */
+ if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("smallint out of range")));
+ PG_RETURN_INT16(ra);
+}
/**************************************************
@@ -128,6 +156,25 @@ gbt_int2_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_int2_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ int16 query = PG_GETARG_INT16(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ int16KEY *kkk = (int16KEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_int2_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c
index aa0d4ac33f..0e4b4f85b0 100644
--- a/contrib/btree_gist/btree_int4.c
+++ b/contrib/btree_gist/btree_int4.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_int4.c,v 1.10 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_int4.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int4_compress);
PG_FUNCTION_INFO_V1(gbt_int4_union);
PG_FUNCTION_INFO_V1(gbt_int4_picksplit);
PG_FUNCTION_INFO_V1(gbt_int4_consistent);
+PG_FUNCTION_INFO_V1(gbt_int4_distance);
PG_FUNCTION_INFO_V1(gbt_int4_penalty);
PG_FUNCTION_INFO_V1(gbt_int4_same);
@@ -24,6 +25,7 @@ Datum gbt_int4_compress(PG_FUNCTION_ARGS);
Datum gbt_int4_union(PG_FUNCTION_ARGS);
Datum gbt_int4_picksplit(PG_FUNCTION_ARGS);
Datum gbt_int4_consistent(PG_FUNCTION_ARGS);
+Datum gbt_int4_distance(PG_FUNCTION_ARGS);
Datum gbt_int4_penalty(PG_FUNCTION_ARGS);
Datum gbt_int4_same(PG_FUNCTION_ARGS);
@@ -71,6 +73,12 @@ gbt_int4key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
+static float8
+gbt_int4_dist(const void *a, const void *b)
+{
+ return GET_FLOAT_DISTANCE(int4, a, b);
+}
+
static const gbtree_ninfo tinfo =
{
@@ -81,10 +89,34 @@ static const gbtree_ninfo tinfo =
gbt_int4eq,
gbt_int4le,
gbt_int4lt,
- gbt_int4key_cmp
+ gbt_int4key_cmp,
+ gbt_int4_dist
};
+PG_FUNCTION_INFO_V1(int4_dist);
+Datum int4_dist(PG_FUNCTION_ARGS);
+Datum
+int4_dist(PG_FUNCTION_ARGS)
+{
+ int4 a = PG_GETARG_INT32(0);
+ int4 b = PG_GETARG_INT32(1);
+ int4 r;
+ int4 ra;
+
+ r = a - b;
+ ra = Abs(r);
+
+ /* Overflow check. */
+ if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+
+ PG_RETURN_INT32(ra);
+}
+
+
/**************************************************
* int32 ops
**************************************************/
@@ -125,6 +157,25 @@ gbt_int4_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_int4_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ int32 query = PG_GETARG_INT32(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ int32KEY *kkk = (int32KEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_int4_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c
index 4cf36a07fa..d54113d393 100644
--- a/contrib/btree_gist/btree_int8.c
+++ b/contrib/btree_gist/btree_int8.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_int8.c,v 1.10 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_int8.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int8_compress);
PG_FUNCTION_INFO_V1(gbt_int8_union);
PG_FUNCTION_INFO_V1(gbt_int8_picksplit);
PG_FUNCTION_INFO_V1(gbt_int8_consistent);
+PG_FUNCTION_INFO_V1(gbt_int8_distance);
PG_FUNCTION_INFO_V1(gbt_int8_penalty);
PG_FUNCTION_INFO_V1(gbt_int8_same);
@@ -24,6 +25,7 @@ Datum gbt_int8_compress(PG_FUNCTION_ARGS);
Datum gbt_int8_union(PG_FUNCTION_ARGS);
Datum gbt_int8_picksplit(PG_FUNCTION_ARGS);
Datum gbt_int8_consistent(PG_FUNCTION_ARGS);
+Datum gbt_int8_distance(PG_FUNCTION_ARGS);
Datum gbt_int8_penalty(PG_FUNCTION_ARGS);
Datum gbt_int8_same(PG_FUNCTION_ARGS);
@@ -71,6 +73,12 @@ gbt_int8key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
+static float8
+gbt_int8_dist(const void *a, const void *b)
+{
+ return GET_FLOAT_DISTANCE(int64, a, b);
+}
+
static const gbtree_ninfo tinfo =
{
@@ -81,10 +89,34 @@ static const gbtree_ninfo tinfo =
gbt_int8eq,
gbt_int8le,
gbt_int8lt,
- gbt_int8key_cmp
+ gbt_int8key_cmp,
+ gbt_int8_dist
};
+PG_FUNCTION_INFO_V1(int8_dist);
+Datum int8_dist(PG_FUNCTION_ARGS);
+Datum
+int8_dist(PG_FUNCTION_ARGS)
+{
+ int64 a = PG_GETARG_INT64(0);
+ int64 b = PG_GETARG_INT64(1);
+ int64 r;
+ int64 ra;
+
+ r = a - b;
+ ra = Abs(r);
+
+ /* Overflow check. */
+ if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+
+ PG_RETURN_INT64(ra);
+}
+
+
/**************************************************
* int64 ops
**************************************************/
@@ -125,6 +157,25 @@ gbt_int8_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_int8_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ int64 query = PG_GETARG_INT64(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ int64KEY *kkk = (int64KEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_int8_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c
index 32b9ddbad7..137a5fcd7f 100644
--- a/contrib/btree_gist/btree_interval.c
+++ b/contrib/btree_gist/btree_interval.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_interval.c,v 1.14 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_interval.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -20,6 +20,7 @@ PG_FUNCTION_INFO_V1(gbt_intv_decompress);
PG_FUNCTION_INFO_V1(gbt_intv_union);
PG_FUNCTION_INFO_V1(gbt_intv_picksplit);
PG_FUNCTION_INFO_V1(gbt_intv_consistent);
+PG_FUNCTION_INFO_V1(gbt_intv_distance);
PG_FUNCTION_INFO_V1(gbt_intv_penalty);
PG_FUNCTION_INFO_V1(gbt_intv_same);
@@ -28,6 +29,7 @@ Datum gbt_intv_decompress(PG_FUNCTION_ARGS);
Datum gbt_intv_union(PG_FUNCTION_ARGS);
Datum gbt_intv_picksplit(PG_FUNCTION_ARGS);
Datum gbt_intv_consistent(PG_FUNCTION_ARGS);
+Datum gbt_intv_distance(PG_FUNCTION_ARGS);
Datum gbt_intv_penalty(PG_FUNCTION_ARGS);
Datum gbt_intv_same(PG_FUNCTION_ARGS);
@@ -83,6 +85,12 @@ intr2num(const Interval *i)
return INTERVAL_TO_SEC(i);
}
+static float8
+gbt_intv_dist(const void *a, const void *b)
+{
+ return (float8) Abs(intr2num((Interval *) a) - intr2num((Interval *) b));
+}
+
/*
* INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
* in pg_type. This might be less than sizeof(Interval) if the compiler
@@ -99,10 +107,38 @@ static const gbtree_ninfo tinfo =
gbt_intveq,
gbt_intvle,
gbt_intvlt,
- gbt_intvkey_cmp
+ gbt_intvkey_cmp,
+ gbt_intv_dist
};
+Interval *
+abs_interval(Interval *a)
+{
+ static Interval zero = {0, 0, 0};
+
+ if (DatumGetBool(DirectFunctionCall2(interval_lt,
+ IntervalPGetDatum(a),
+ IntervalPGetDatum(&zero))))
+ a = DatumGetIntervalP(DirectFunctionCall1(interval_um,
+ IntervalPGetDatum(a)));
+
+ return a;
+}
+
+PG_FUNCTION_INFO_V1(interval_dist);
+Datum interval_dist(PG_FUNCTION_ARGS);
+Datum
+interval_dist(PG_FUNCTION_ARGS)
+{
+ Datum diff = DirectFunctionCall2(interval_mi,
+ PG_GETARG_DATUM(0),
+ PG_GETARG_DATUM(1));
+
+ PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
+}
+
+
/**************************************************
* interval ops
**************************************************/
@@ -191,6 +227,25 @@ gbt_intv_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_intv_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ Interval *query = PG_GETARG_INTERVAL_P(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ intvKEY *kkk = (intvKEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_intv_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c
index 60092b4e9e..aa150e26a2 100644
--- a/contrib/btree_gist/btree_macaddr.c
+++ b/contrib/btree_gist/btree_macaddr.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_macaddr.c,v 1.10 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_macaddr.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -84,7 +84,8 @@ static const gbtree_ninfo tinfo =
gbt_macadeq,
gbt_macadle,
gbt_macadlt,
- gbt_macadkey_cmp
+ gbt_macadkey_cmp,
+ NULL
};
diff --git a/contrib/btree_gist/btree_numeric.c b/contrib/btree_gist/btree_numeric.c
index 810bb279da..e962c6dd32 100644
--- a/contrib/btree_gist/btree_numeric.c
+++ b/contrib/btree_gist/btree_numeric.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_numeric.c,v 1.13 2009/06/11 14:48:50 momjian Exp $
+ * contrib/btree_gist/btree_numeric.c
*/
#include "btree_gist.h"
@@ -32,41 +32,51 @@ Datum gbt_numeric_same(PG_FUNCTION_ARGS);
/* define for comparison */
static bool
-gbt_numeric_gt(const void *a, const void *b)
+gbt_numeric_gt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(numeric_gt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(numeric_gt,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_numeric_ge(const void *a, const void *b)
+gbt_numeric_ge(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(numeric_ge, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(numeric_ge,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_numeric_eq(const void *a, const void *b)
+gbt_numeric_eq(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(numeric_eq, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(numeric_eq,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_numeric_le(const void *a, const void *b)
+gbt_numeric_le(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(numeric_le, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(numeric_le,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_numeric_lt(const void *a, const void *b)
+gbt_numeric_lt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(numeric_lt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2(numeric_lt,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
-
static int32
-gbt_numeric_cmp(const bytea *a, const bytea *b)
+gbt_numeric_cmp(const void *a, const void *b, Oid collation)
{
- return
- (DatumGetInt32(DirectFunctionCall2(numeric_cmp, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
@@ -116,7 +126,8 @@ gbt_numeric_consistent(PG_FUNCTION_ARGS)
/* All cases served by this function are exact */
*recheck = false;
- retval = gbt_var_consistent(&r, query, &strategy, GIST_LEAF(entry), &tinfo);
+ retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
+ GIST_LEAF(entry), &tinfo);
PG_RETURN_BOOL(retval);
}
@@ -128,7 +139,8 @@ gbt_numeric_union(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int32 *size = (int *) PG_GETARG_POINTER(1);
- PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
+ PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
+ &tinfo));
}
@@ -139,7 +151,8 @@ gbt_numeric_same(PG_FUNCTION_ARGS)
Datum d2 = PG_GETARG_DATUM(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
- PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
+ *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+ PG_RETURN_POINTER(result);
}
@@ -163,7 +176,7 @@ gbt_numeric_penalty(PG_FUNCTION_ARGS)
rk = gbt_var_key_readable(org);
uni = PointerGetDatum(gbt_var_key_copy(&rk, TRUE));
- gbt_var_bin_union(&uni, newe, &tinfo);
+ gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo);
ok = gbt_var_key_readable(org);
uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
@@ -185,9 +198,9 @@ gbt_numeric_penalty(PG_FUNCTION_ARGS)
NumericGetDatum(os)
));
- if (NUMERIC_IS_NAN(us))
+ if (numeric_is_nan(us))
{
- if (NUMERIC_IS_NAN(os))
+ if (numeric_is_nan(os))
*result = 0.0;
else
*result = 1.0;
@@ -224,6 +237,7 @@ gbt_numeric_picksplit(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
- gbt_var_picksplit(entryvec, v, &tinfo);
+ gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
+ &tinfo);
PG_RETURN_POINTER(v);
}
diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c
index 96e4be54d4..3b0929b42b 100644
--- a/contrib/btree_gist/btree_oid.c
+++ b/contrib/btree_gist/btree_oid.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_oid.c,v 1.10 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_oid.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_oid_compress);
PG_FUNCTION_INFO_V1(gbt_oid_union);
PG_FUNCTION_INFO_V1(gbt_oid_picksplit);
PG_FUNCTION_INFO_V1(gbt_oid_consistent);
+PG_FUNCTION_INFO_V1(gbt_oid_distance);
PG_FUNCTION_INFO_V1(gbt_oid_penalty);
PG_FUNCTION_INFO_V1(gbt_oid_same);
@@ -24,6 +25,7 @@ Datum gbt_oid_compress(PG_FUNCTION_ARGS);
Datum gbt_oid_union(PG_FUNCTION_ARGS);
Datum gbt_oid_picksplit(PG_FUNCTION_ARGS);
Datum gbt_oid_consistent(PG_FUNCTION_ARGS);
+Datum gbt_oid_distance(PG_FUNCTION_ARGS);
Datum gbt_oid_penalty(PG_FUNCTION_ARGS);
Datum gbt_oid_same(PG_FUNCTION_ARGS);
@@ -71,6 +73,18 @@ gbt_oidkey_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
+static float8
+gbt_oid_dist(const void *a, const void *b)
+{
+ Oid aa = *(const Oid *) a;
+ Oid bb = *(const Oid *) b;
+
+ if (aa < bb)
+ return (float8) (bb - aa);
+ else
+ return (float8) (aa - bb);
+}
+
static const gbtree_ninfo tinfo =
{
@@ -81,10 +95,28 @@ static const gbtree_ninfo tinfo =
gbt_oideq,
gbt_oidle,
gbt_oidlt,
- gbt_oidkey_cmp
+ gbt_oidkey_cmp,
+ gbt_oid_dist
};
+PG_FUNCTION_INFO_V1(oid_dist);
+Datum oid_dist(PG_FUNCTION_ARGS);
+Datum
+oid_dist(PG_FUNCTION_ARGS)
+{
+ Oid a = PG_GETARG_OID(0);
+ Oid b = PG_GETARG_OID(1);
+ Oid res;
+
+ if (a < b)
+ res = b - a;
+ else
+ res = a - b;
+ PG_RETURN_OID(res);
+}
+
+
/**************************************************
* Oid ops
**************************************************/
@@ -125,6 +157,25 @@ gbt_oid_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_oid_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ Oid query = PG_GETARG_OID(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ oidKEY *kkk = (oidKEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+
+Datum
gbt_oid_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_text.c b/contrib/btree_gist/btree_text.c
index 8b01eb7aac..3d4f8c13c8 100644
--- a/contrib/btree_gist/btree_text.c
+++ b/contrib/btree_gist/btree_text.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_text.c,v 1.12 2009/06/11 14:48:50 momjian Exp $
+ * contrib/btree_gist/btree_text.c
*/
#include "btree_gist.h"
#include "btree_utils_var.h"
@@ -30,39 +30,57 @@ Datum gbt_text_same(PG_FUNCTION_ARGS);
/* define for comparison */
static bool
-gbt_textgt(const void *a, const void *b)
+gbt_textgt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(text_gt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_gt,
+ collation,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_textge(const void *a, const void *b)
+gbt_textge(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(text_ge, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_ge,
+ collation,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_texteq(const void *a, const void *b)
+gbt_texteq(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(texteq, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(texteq,
+ collation,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_textle(const void *a, const void *b)
+gbt_textle(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(text_le, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_le,
+ collation,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
-gbt_textlt(const void *a, const void *b)
+gbt_textlt(const void *a, const void *b, Oid collation)
{
- return (DatumGetBool(DirectFunctionCall2(text_lt, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_lt,
+ collation,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static int32
-gbt_textcmp(const bytea *a, const bytea *b)
+gbt_textcmp(const void *a, const void *b, Oid collation)
{
- return DatumGetInt32(DirectFunctionCall2(bttextcmp, PointerGetDatum(a), PointerGetDatum(b)));
+ return DatumGetInt32(DirectFunctionCall2Coll(bttextcmp,
+ collation,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static gbtree_vinfo tinfo =
@@ -150,7 +168,8 @@ gbt_text_consistent(PG_FUNCTION_ARGS)
tinfo.eml = pg_database_encoding_max_length();
}
- retval = gbt_var_consistent(&r, query, &strategy, GIST_LEAF(entry), &tinfo);
+ retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
+ GIST_LEAF(entry), &tinfo);
PG_RETURN_BOOL(retval);
}
@@ -178,7 +197,8 @@ gbt_bpchar_consistent(PG_FUNCTION_ARGS)
tinfo.eml = pg_database_encoding_max_length();
}
- retval = gbt_var_consistent(&r, trim, &strategy, GIST_LEAF(entry), &tinfo);
+ retval = gbt_var_consistent(&r, trim, strategy, PG_GET_COLLATION(),
+ GIST_LEAF(entry), &tinfo);
PG_RETURN_BOOL(retval);
}
@@ -189,7 +209,8 @@ gbt_text_union(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int32 *size = (int *) PG_GETARG_POINTER(1);
- PG_RETURN_POINTER(gbt_var_union(entryvec, size, &tinfo));
+ PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
+ &tinfo));
}
@@ -199,7 +220,8 @@ gbt_text_picksplit(PG_FUNCTION_ARGS)
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
- gbt_var_picksplit(entryvec, v, &tinfo);
+ gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
+ &tinfo);
PG_RETURN_POINTER(v);
}
@@ -210,7 +232,8 @@ gbt_text_same(PG_FUNCTION_ARGS)
Datum d2 = PG_GETARG_DATUM(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
- PG_RETURN_POINTER(gbt_var_same(result, d1, d2, &tinfo));
+ *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+ PG_RETURN_POINTER(result);
}
@@ -221,5 +244,6 @@ gbt_text_penalty(PG_FUNCTION_ARGS)
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
float *result = (float *) PG_GETARG_POINTER(2);
- PG_RETURN_POINTER(gbt_var_penalty(result, o, n, &tinfo));
+ PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
+ &tinfo));
}
diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c
index 8566a8efb7..e9cfe33f45 100644
--- a/contrib/btree_gist/btree_time.c
+++ b/contrib/btree_gist/btree_time.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_time.c,v 1.18 2010/02/26 02:00:31 momjian Exp $
+ * contrib/btree_gist/btree_time.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -20,6 +20,7 @@ PG_FUNCTION_INFO_V1(gbt_timetz_compress);
PG_FUNCTION_INFO_V1(gbt_time_union);
PG_FUNCTION_INFO_V1(gbt_time_picksplit);
PG_FUNCTION_INFO_V1(gbt_time_consistent);
+PG_FUNCTION_INFO_V1(gbt_time_distance);
PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
PG_FUNCTION_INFO_V1(gbt_time_penalty);
PG_FUNCTION_INFO_V1(gbt_time_same);
@@ -29,6 +30,7 @@ Datum gbt_timetz_compress(PG_FUNCTION_ARGS);
Datum gbt_time_union(PG_FUNCTION_ARGS);
Datum gbt_time_picksplit(PG_FUNCTION_ARGS);
Datum gbt_time_consistent(PG_FUNCTION_ARGS);
+Datum gbt_time_distance(PG_FUNCTION_ARGS);
Datum gbt_timetz_consistent(PG_FUNCTION_ARGS);
Datum gbt_time_penalty(PG_FUNCTION_ARGS);
Datum gbt_time_same(PG_FUNCTION_ARGS);
@@ -112,6 +114,19 @@ gbt_timekey_cmp(const void *a, const void *b)
return res;
}
+static float8
+gbt_time_dist(const void *a, const void *b)
+{
+ const TimeADT *aa = (const TimeADT *) a;
+ const TimeADT *bb = (const TimeADT *) b;
+ Interval *i;
+
+ i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
+ TimeADTGetDatumFast(*aa),
+ TimeADTGetDatumFast(*bb)));
+ return (float8) Abs(INTERVAL_TO_SEC(i));
+}
+
static const gbtree_ninfo tinfo =
{
@@ -122,10 +137,24 @@ static const gbtree_ninfo tinfo =
gbt_timeeq,
gbt_timele,
gbt_timelt,
- gbt_timekey_cmp
+ gbt_timekey_cmp,
+ gbt_time_dist
};
+PG_FUNCTION_INFO_V1(time_dist);
+Datum time_dist(PG_FUNCTION_ARGS);
+Datum
+time_dist(PG_FUNCTION_ARGS)
+{
+ Datum diff = DirectFunctionCall2(time_mi_time,
+ PG_GETARG_DATUM(0),
+ PG_GETARG_DATUM(1));
+
+ PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
+}
+
+
/**************************************************
* time ops
**************************************************/
@@ -197,6 +226,24 @@ gbt_time_consistent(PG_FUNCTION_ARGS)
}
Datum
+gbt_time_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ TimeADT query = PG_GETARG_TIMEADT(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ timeKEY *kkk = (timeKEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+Datum
gbt_timetz_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c
index 543f2129b0..9d3a5919a0 100644
--- a/contrib/btree_gist/btree_ts.c
+++ b/contrib/btree_gist/btree_ts.c
@@ -1,8 +1,9 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_ts.c,v 1.19 2010/02/26 02:00:32 momjian Exp $
+ * contrib/btree_gist/btree_ts.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
+#include "utils/builtins.h"
#include "utils/datetime.h"
typedef struct
@@ -19,7 +20,9 @@ PG_FUNCTION_INFO_V1(gbt_tstz_compress);
PG_FUNCTION_INFO_V1(gbt_ts_union);
PG_FUNCTION_INFO_V1(gbt_ts_picksplit);
PG_FUNCTION_INFO_V1(gbt_ts_consistent);
+PG_FUNCTION_INFO_V1(gbt_ts_distance);
PG_FUNCTION_INFO_V1(gbt_tstz_consistent);
+PG_FUNCTION_INFO_V1(gbt_tstz_distance);
PG_FUNCTION_INFO_V1(gbt_ts_penalty);
PG_FUNCTION_INFO_V1(gbt_ts_same);
@@ -28,7 +31,9 @@ Datum gbt_tstz_compress(PG_FUNCTION_ARGS);
Datum gbt_ts_union(PG_FUNCTION_ARGS);
Datum gbt_ts_picksplit(PG_FUNCTION_ARGS);
Datum gbt_ts_consistent(PG_FUNCTION_ARGS);
+Datum gbt_ts_distance(PG_FUNCTION_ARGS);
Datum gbt_tstz_consistent(PG_FUNCTION_ARGS);
+Datum gbt_tstz_distance(PG_FUNCTION_ARGS);
Datum gbt_ts_penalty(PG_FUNCTION_ARGS);
Datum gbt_ts_same(PG_FUNCTION_ARGS);
@@ -110,6 +115,22 @@ gbt_tskey_cmp(const void *a, const void *b)
return res;
}
+static float8
+gbt_ts_dist(const void *a, const void *b)
+{
+ const Timestamp *aa = (const Timestamp *) a;
+ const Timestamp *bb = (const Timestamp *) b;
+ Interval *i;
+
+ if (TIMESTAMP_NOT_FINITE(*aa) || TIMESTAMP_NOT_FINITE(*bb))
+ return get_float8_infinity();
+
+ i = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+ TimestampGetDatumFast(*aa),
+ TimestampGetDatumFast(*bb)));
+ return (float8) Abs(INTERVAL_TO_SEC(i));
+}
+
static const gbtree_ninfo tinfo =
{
@@ -120,10 +141,70 @@ static const gbtree_ninfo tinfo =
gbt_tseq,
gbt_tsle,
gbt_tslt,
- gbt_tskey_cmp
+ gbt_tskey_cmp,
+ gbt_ts_dist
};
+PG_FUNCTION_INFO_V1(ts_dist);
+Datum ts_dist(PG_FUNCTION_ARGS);
+Datum
+ts_dist(PG_FUNCTION_ARGS)
+{
+ Timestamp a = PG_GETARG_TIMESTAMP(0);
+ Timestamp b = PG_GETARG_TIMESTAMP(1);
+ Interval *r;
+
+ if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+ {
+ Interval *p = palloc(sizeof(Interval));
+
+ p->day = INT_MAX;
+ p->month = INT_MAX;
+#ifdef HAVE_INT64_TIMESTAMP
+ p->time = INT64CONST(0x7FFFFFFFFFFFFFFF);
+#else
+ p->time = DBL_MAX;
+#endif
+ PG_RETURN_INTERVAL_P(p);
+ }
+ else
+ r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+ PG_GETARG_DATUM(0),
+ PG_GETARG_DATUM(1)));
+ PG_RETURN_INTERVAL_P(abs_interval(r));
+}
+
+PG_FUNCTION_INFO_V1(tstz_dist);
+Datum tstz_dist(PG_FUNCTION_ARGS);
+Datum
+tstz_dist(PG_FUNCTION_ARGS)
+{
+ TimestampTz a = PG_GETARG_TIMESTAMPTZ(0);
+ TimestampTz b = PG_GETARG_TIMESTAMPTZ(1);
+ Interval *r;
+
+ if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+ {
+ Interval *p = palloc(sizeof(Interval));
+
+ p->day = INT_MAX;
+ p->month = INT_MAX;
+#ifdef HAVE_INT64_TIMESTAMP
+ p->time = INT64CONST(0x7FFFFFFFFFFFFFFF);
+#else
+ p->time = DBL_MAX;
+#endif
+ PG_RETURN_INTERVAL_P(p);
+ }
+
+ r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+ PG_GETARG_DATUM(0),
+ PG_GETARG_DATUM(1)));
+ PG_RETURN_INTERVAL_P(abs_interval(r));
+}
+
+
/**************************************************
* timestamp ops
**************************************************/
@@ -214,6 +295,24 @@ gbt_ts_consistent(PG_FUNCTION_ARGS)
}
Datum
+gbt_ts_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ Timestamp query = PG_GETARG_TIMESTAMP(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+
+ key.lower = (GBT_NUMKEY *) &kkk->lower;
+ key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+ );
+}
+
+Datum
gbt_tstz_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
@@ -238,6 +337,26 @@ gbt_tstz_consistent(PG_FUNCTION_ARGS)
);
}
+Datum
+gbt_tstz_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ char *kkk = (char *) DatumGetPointer(entry->key);
+ GBT_NUMKEY_R key;
+ Timestamp qqq;
+
+ key.lower = (GBT_NUMKEY *) &kkk[0];
+ key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
+ qqq = tstz_to_ts_gmt(query);
+
+ PG_RETURN_FLOAT8(
+ gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), &tinfo)
+ );
+}
+
Datum
gbt_ts_union(PG_FUNCTION_ARGS)
diff --git a/contrib/btree_gist/btree_utils_num.c b/contrib/btree_gist/btree_utils_num.c
index ff206dcda8..a3da5802df 100644
--- a/contrib/btree_gist/btree_utils_num.c
+++ b/contrib/btree_gist/btree_utils_num.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_num.c,v 1.12 2009/06/11 14:48:50 momjian Exp $
+ * contrib/btree_gist/btree_utils_num.c
*/
#include "btree_gist.h"
#include "btree_utils_num.h"
@@ -184,20 +184,19 @@ gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
/*
-** The GiST consistent method
-*/
-
+ * The GiST consistent method
+ *
+ * Note: we currently assume that no datatypes that use this routine are
+ * collation-aware; so we don't bother passing collation through.
+ */
bool
-gbt_num_consistent(
- const GBT_NUMKEY_R *key,
+gbt_num_consistent(const GBT_NUMKEY_R *key,
const void *query,
const StrategyNumber *strategy,
bool is_leaf,
- const gbtree_ninfo *tinfo
-)
+ const gbtree_ninfo *tinfo)
{
-
- bool retval = FALSE;
+ bool retval;
switch (*strategy)
{
@@ -214,7 +213,7 @@ gbt_num_consistent(
if (is_leaf)
retval = (*tinfo->f_eq) (query, key->lower);
else
- retval = (*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper);
+ retval = ((*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper)) ? true : false;
break;
case BTGreaterStrategyNumber:
if (is_leaf)
@@ -225,14 +224,44 @@ gbt_num_consistent(
case BTGreaterEqualStrategyNumber:
retval = (*tinfo->f_le) (query, key->upper);
break;
+ case BtreeGistNotEqualStrategyNumber:
+ retval = (!((*tinfo->f_eq) (query, key->lower) &&
+ (*tinfo->f_eq) (query, key->upper))) ? true : false;
+ break;
default:
- retval = FALSE;
+ retval = false;
}
return (retval);
}
+/*
+** The GiST distance method (for KNN-Gist)
+*/
+
+float8
+gbt_num_distance(const GBT_NUMKEY_R *key,
+ const void *query,
+ bool is_leaf,
+ const gbtree_ninfo *tinfo)
+{
+ float8 retval;
+
+ if (tinfo->f_dist == NULL)
+ elog(ERROR, "KNN search is not supported for btree_gist type %d",
+ (int) tinfo->t);
+ if (tinfo->f_le(query, key->lower))
+ retval = tinfo->f_dist(query, key->lower);
+ else if (tinfo->f_ge(query, key->upper))
+ retval = tinfo->f_dist(query, key->upper);
+ else
+ retval = 0.0;
+
+ return retval;
+}
+
+
GIST_SPLITVEC *
gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
const gbtree_ninfo *tinfo)
diff --git a/contrib/btree_gist/btree_utils_num.h b/contrib/btree_gist/btree_utils_num.h
index dcd17bc430..8935ed6630 100644
--- a/contrib/btree_gist/btree_utils_num.h
+++ b/contrib/btree_gist/btree_utils_num.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_num.h,v 1.14 2009/06/11 14:48:50 momjian Exp $
+ * contrib/btree_gist/btree_utils_num.h
*/
#ifndef __BTREE_UTILS_NUM_H__
#define __BTREE_UTILS_NUM_H__
@@ -40,24 +40,25 @@ typedef struct
/* Methods */
- bool (*f_gt) (const void *, const void *); /* greater then */
- bool (*f_ge) (const void *, const void *); /* greater equal */
+ bool (*f_gt) (const void *, const void *); /* greater than */
+ bool (*f_ge) (const void *, const void *); /* greater or equal */
bool (*f_eq) (const void *, const void *); /* equal */
- bool (*f_le) (const void *, const void *); /* less equal */
- bool (*f_lt) (const void *, const void *); /* less then */
+ bool (*f_le) (const void *, const void *); /* less or equal */
+ bool (*f_lt) (const void *, const void *); /* less than */
int (*f_cmp) (const void *, const void *); /* key compare function */
+ float8 (*f_dist) (const void *, const void *); /* key distance function */
} gbtree_ninfo;
/*
* Numeric btree functions
-*/
+ */
/*
* Note: The factor 0.49 in following macro avoids floating point overflows
-*/
+ */
#define penalty_num(result,olower,oupper,nlower,nupper) do { \
double tmp = 0.0F; \
(*(result)) = 0.0F; \
@@ -91,11 +92,37 @@ typedef struct
(ivp)->month * (30.0 * SECS_PER_DAY))
#endif
+#define GET_FLOAT_DISTANCE(t, arg1, arg2) Abs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
+
+#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
+
+/*
+ * check to see if a float4/8 val has underflowed or overflowed
+ * borrowed from src/backend/utils/adt/float.c
+ */
+#define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid) \
+do { \
+ if (isinf(val) && !(inf_is_valid)) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
+ errmsg("value out of range: overflow"))); \
+ \
+ if ((val) == 0.0 && !(zero_is_valid)) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
+ errmsg("value out of range: underflow"))); \
+} while(0)
+
+
+extern Interval *abs_interval(Interval *a);
extern bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query,
const StrategyNumber *strategy, bool is_leaf,
const gbtree_ninfo *tinfo);
+extern float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query,
+ bool is_leaf, const gbtree_ninfo *tinfo);
+
extern GIST_SPLITVEC *gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
const gbtree_ninfo *tinfo);
diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c
index 916706d8a4..e73799bb21 100644
--- a/contrib/btree_gist/btree_utils_var.c
+++ b/contrib/btree_gist/btree_utils_var.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_var.c,v 1.23 2010/02/26 02:00:32 momjian Exp $
+ * contrib/btree_gist/btree_utils_var.c
*/
#include "btree_gist.h"
@@ -12,6 +12,20 @@
#include "utils/builtins.h"
#include "utils/rel.h"
+/* used for key sorting */
+typedef struct
+{
+ int i;
+ GBT_VARKEY *t;
+} Vsrt;
+
+typedef struct
+{
+ const gbtree_vinfo *tinfo;
+ Oid collation;
+} gbt_vsrt_arg;
+
+
PG_FUNCTION_INFO_V1(gbt_var_decompress);
Datum gbt_var_decompress(PG_FUNCTION_ARGS);
@@ -139,13 +153,11 @@ gbt_var_node_cp_len(const GBT_VARKEY *node, const gbtree_vinfo *tinfo)
/*
* returns true, if query matches prefix ( common prefix )
-*/
+ */
static bool
gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinfo)
{
-
bool out = FALSE;
- int32 k = 0;
int32 qlen = VARSIZE(query) - VARHDRSZ;
int32 nlen = VARSIZE(pf) - VARHDRSZ;
@@ -154,27 +166,7 @@ gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinf
char *q = VARDATA(query);
char *n = VARDATA(pf);
- if (tinfo->eml > 1)
- {
- out = (varstr_cmp(q, nlen, n, nlen) == 0);
- }
- else
- {
- out = TRUE;
- for (k = 0; k < nlen; k++)
- {
- if (*n != *q)
- {
- out = FALSE;
- break;
- }
- if (k < (nlen - 1))
- {
- q++;
- n++;
- }
- }
- }
+ out = (memcmp(q, n, nlen) == 0);
}
return out;
@@ -183,17 +175,14 @@ gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinf
/*
* returns true, if query matches node using common prefix
-*/
-
+ */
static bool
gbt_var_node_pf_match(const GBT_VARKEY_R *node, const bytea *query, const gbtree_vinfo *tinfo)
{
-
return (tinfo->trnc && (
gbt_bytea_pf_match(node->lower, query, tinfo) ||
gbt_bytea_pf_match(node->upper, query, tinfo)
));
-
}
@@ -231,9 +220,9 @@ gbt_var_node_truncate(const GBT_VARKEY *node, int32 cpf_length, const gbtree_vin
void
-gbt_var_bin_union(Datum *u, GBT_VARKEY *e, const gbtree_vinfo *tinfo)
+gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
+ const gbtree_vinfo *tinfo)
{
-
GBT_VARKEY *nk = NULL;
GBT_VARKEY *tmp = NULL;
GBT_VARKEY_R nr;
@@ -251,14 +240,14 @@ gbt_var_bin_union(Datum *u, GBT_VARKEY *e, const gbtree_vinfo *tinfo)
GBT_VARKEY_R ro = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(*u));
- if ((*tinfo->f_cmp) ((bytea *) ro.lower, (bytea *) eo.lower) > 0)
+ if ((*tinfo->f_cmp) (ro.lower, eo.lower, collation) > 0)
{
nr.lower = eo.lower;
nr.upper = ro.upper;
nk = gbt_var_key_copy(&nr, TRUE);
}
- if ((*tinfo->f_cmp) ((bytea *) ro.upper, (bytea *) eo.upper) < 0)
+ if ((*tinfo->f_cmp) (ro.upper, eo.upper, collation) < 0)
{
nr.upper = eo.upper;
nr.lower = ro.lower;
@@ -307,7 +296,8 @@ gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo)
GBT_VARKEY *
-gbt_var_union(const GistEntryVector *entryvec, int32 *size, const gbtree_vinfo *tinfo)
+gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation,
+ const gbtree_vinfo *tinfo)
{
int i = 0,
@@ -325,7 +315,7 @@ gbt_var_union(const GistEntryVector *entryvec, int32 *size, const gbtree_vinfo *
for (i = 1; i < numranges; i++)
{
cur = (GBT_VARKEY *) DatumGetPointer(entryvec->vector[i].key);
- gbt_var_bin_union(&out, cur, tinfo);
+ gbt_var_bin_union(&out, cur, collation, tinfo);
}
@@ -346,9 +336,10 @@ gbt_var_union(const GistEntryVector *entryvec, int32 *size, const gbtree_vinfo *
bool
-gbt_var_same(bool *result, const Datum d1, const Datum d2, const gbtree_vinfo *tinfo)
+gbt_var_same(Datum d1, Datum d2, Oid collation,
+ const gbtree_vinfo *tinfo)
{
-
+ bool result;
GBT_VARKEY *t1 = (GBT_VARKEY *) DatumGetPointer(d1);
GBT_VARKEY *t2 = (GBT_VARKEY *) DatumGetPointer(d2);
GBT_VARKEY_R r1,
@@ -358,22 +349,19 @@ gbt_var_same(bool *result, const Datum d1, const Datum d2, const gbtree_vinfo *t
r2 = gbt_var_key_readable(t2);
if (t1 && t2)
- {
- *result = (((*tinfo->f_cmp) ((bytea *) r1.lower, (bytea *) r2.lower) == 0
- && (*tinfo->f_cmp) ((bytea *) r1.upper, (bytea *) r2.upper) == 0) ? TRUE : FALSE);
- }
+ result = ((*tinfo->f_cmp) (r1.lower, r2.lower, collation) == 0 &&
+ (*tinfo->f_cmp) (r1.upper, r2.upper, collation) == 0);
else
- *result = (t1 == NULL && t2 == NULL) ? TRUE : FALSE;
+ result = (t1 == NULL && t2 == NULL);
- PG_RETURN_POINTER(result);
+ return result;
}
-
float *
-gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree_vinfo *tinfo)
+gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
+ Oid collation, const gbtree_vinfo *tinfo)
{
-
GBT_VARKEY *orge = (GBT_VARKEY *) DatumGetPointer(o->key);
GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
GBT_VARKEY_R ok,
@@ -393,21 +381,19 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree
if ((VARSIZE(ok.lower) - VARHDRSZ) == 0 && (VARSIZE(ok.upper) - VARHDRSZ) == 0)
*res = 0.0;
- else if (!(
- (
- ((*tinfo->f_cmp) (nk.lower, ok.lower) >= 0 || gbt_bytea_pf_match(ok.lower, nk.lower, tinfo)) &&
- ((*tinfo->f_cmp) (nk.upper, ok.upper) <= 0 || gbt_bytea_pf_match(ok.upper, nk.upper, tinfo))
- )
- ))
+ else if (!(((*tinfo->f_cmp) (nk.lower, ok.lower, collation) >= 0 ||
+ gbt_bytea_pf_match(ok.lower, nk.lower, tinfo)) &&
+ ((*tinfo->f_cmp) (nk.upper, ok.upper, collation) <= 0 ||
+ gbt_bytea_pf_match(ok.upper, nk.upper, tinfo))))
{
Datum d = PointerGetDatum(0);
double dres = 0.0;
int32 ol,
ul;
- gbt_var_bin_union(&d, orge, tinfo);
+ gbt_var_bin_union(&d, orge, collation, tinfo);
ol = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
- gbt_var_bin_union(&d, newe, tinfo);
+ gbt_var_bin_union(&d, newe, collation, tinfo);
ul = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
if (ul < ol)
@@ -443,18 +429,19 @@ gbt_vsrt_cmp(const void *a, const void *b, void *arg)
{
GBT_VARKEY_R ar = gbt_var_key_readable(((const Vsrt *) a)->t);
GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->t);
- const gbtree_vinfo *tinfo = (const gbtree_vinfo *) arg;
+ const gbt_vsrt_arg *varg = (const gbt_vsrt_arg *) arg;
int res;
- res = (*tinfo->f_cmp) (ar.lower, br.lower);
+ res = (*varg->tinfo->f_cmp) (ar.lower, br.lower, varg->collation);
if (res == 0)
- return (*tinfo->f_cmp) (ar.upper, br.upper);
+ return (*varg->tinfo->f_cmp) (ar.upper, br.upper, varg->collation);
return res;
}
GIST_SPLITVEC *
-gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtree_vinfo *tinfo)
+gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
+ Oid collation, const gbtree_vinfo *tinfo)
{
OffsetNumber i,
maxoff = entryvec->n - 1;
@@ -463,6 +450,7 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
nbytes;
char *cur;
GBT_VARKEY **sv = NULL;
+ gbt_vsrt_arg varg;
arr = (Vsrt *) palloc((maxoff + 1) * sizeof(Vsrt));
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
@@ -496,11 +484,13 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
}
/* sort */
+ varg.tinfo = tinfo;
+ varg.collation = collation;
qsort_arg((void *) &arr[FirstOffsetNumber],
maxoff - FirstOffsetNumber + 1,
sizeof(Vsrt),
gbt_vsrt_cmp,
- (void *) tinfo);
+ (void *) &varg);
/* We do simply create two parts */
@@ -508,13 +498,13 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
{
if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
{
- gbt_var_bin_union(&v->spl_ldatum, arr[i].t, tinfo);
+ gbt_var_bin_union(&v->spl_ldatum, arr[i].t, collation, tinfo);
v->spl_left[v->spl_nleft] = arr[i].i;
v->spl_nleft++;
}
else
{
- gbt_var_bin_union(&v->spl_rdatum, arr[i].t, tinfo);
+ gbt_var_bin_union(&v->spl_rdatum, arr[i].t, collation, tinfo);
v->spl_right[v->spl_nright] = arr[i].i;
v->spl_nright++;
}
@@ -545,60 +535,61 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
* The GiST consistent method
*/
bool
-gbt_var_consistent(
- GBT_VARKEY_R *key,
+gbt_var_consistent(GBT_VARKEY_R *key,
const void *query,
- const StrategyNumber *strategy,
+ StrategyNumber strategy,
+ Oid collation,
bool is_leaf,
- const gbtree_vinfo *tinfo
-)
+ const gbtree_vinfo *tinfo)
{
bool retval = FALSE;
- switch (*strategy)
+ switch (strategy)
{
case BTLessEqualStrategyNumber:
if (is_leaf)
- retval = (*tinfo->f_ge) (query, (void *) key->lower);
+ retval = (*tinfo->f_ge) (query, key->lower, collation);
else
- retval = (*tinfo->f_cmp) ((bytea *) query, key->lower) >= 0
+ retval = (*tinfo->f_cmp) (query, key->lower, collation) >= 0
|| gbt_var_node_pf_match(key, query, tinfo);
break;
case BTLessStrategyNumber:
if (is_leaf)
- retval = (*tinfo->f_gt) (query, (void *) key->lower);
+ retval = (*tinfo->f_gt) (query, key->lower, collation);
else
- retval = (*tinfo->f_cmp) ((bytea *) query, key->lower) >= 0
+ retval = (*tinfo->f_cmp) (query, key->lower, collation) >= 0
|| gbt_var_node_pf_match(key, query, tinfo);
break;
case BTEqualStrategyNumber:
if (is_leaf)
- retval = (*tinfo->f_eq) (query, (void *) key->lower);
+ retval = (*tinfo->f_eq) (query, key->lower, collation);
else
- retval = (
- (
- (*tinfo->f_cmp) (key->lower, (bytea *) query) <= 0 &&
- (*tinfo->f_cmp) ((bytea *) query, (void *) key->upper) <= 0
- ) || gbt_var_node_pf_match(key, query, tinfo)
- );
+ retval =
+ ((*tinfo->f_cmp) (key->lower, query, collation) <= 0 &&
+ (*tinfo->f_cmp) (query, key->upper, collation) <= 0) ||
+ gbt_var_node_pf_match(key, query, tinfo);
break;
case BTGreaterStrategyNumber:
if (is_leaf)
- retval = (*tinfo->f_lt) (query, (void *) key->upper);
+ retval = (*tinfo->f_lt) (query, key->upper, collation);
else
- retval = (*tinfo->f_cmp) ((bytea *) query, key->upper) <= 0
+ retval = (*tinfo->f_cmp) (query, key->upper, collation) <= 0
|| gbt_var_node_pf_match(key, query, tinfo);
break;
case BTGreaterEqualStrategyNumber:
if (is_leaf)
- retval = (*tinfo->f_le) (query, (void *) key->upper);
+ retval = (*tinfo->f_le) (query, key->upper, collation);
else
- retval = (*tinfo->f_cmp) ((bytea *) query, key->upper) <= 0
+ retval = (*tinfo->f_cmp) (query, key->upper, collation) <= 0
|| gbt_var_node_pf_match(key, query, tinfo);
break;
+ case BtreeGistNotEqualStrategyNumber:
+ retval = !((*tinfo->f_eq) (query, key->lower, collation) &&
+ (*tinfo->f_eq) (query, key->upper, collation));
+ break;
default:
retval = FALSE;
}
- return (retval);
+ return retval;
}
diff --git a/contrib/btree_gist/btree_utils_var.h b/contrib/btree_gist/btree_utils_var.h
index 49f5d59ee2..57d10e80f1 100644
--- a/contrib/btree_gist/btree_utils_var.h
+++ b/contrib/btree_gist/btree_utils_var.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_utils_var.h,v 1.9 2009/06/11 14:48:50 momjian Exp $
+ * contrib/btree_gist/btree_utils_var.h
*/
#ifndef __BTREE_UTILS_VAR_H__
#define __BTREE_UTILS_VAR_H__
@@ -18,18 +18,9 @@ typedef struct
*upper;
} GBT_VARKEY_R;
-/* used for key sorting */
-typedef struct
-{
- int i;
- GBT_VARKEY *t;
-} Vsrt;
-
/*
- type description
-*/
-
-
+ * type description
+ */
typedef struct
{
@@ -42,12 +33,12 @@ typedef struct
/* Methods */
- bool (*f_gt) (const void *, const void *); /* greater then */
- bool (*f_ge) (const void *, const void *); /* greater equal */
- bool (*f_eq) (const void *, const void *); /* equal */
- bool (*f_le) (const void *, const void *); /* less equal */
- bool (*f_lt) (const void *, const void *); /* less then */
- int32 (*f_cmp) (const bytea *, const bytea *); /* node compare */
+ bool (*f_gt) (const void *, const void *, Oid); /* greater than */
+ bool (*f_ge) (const void *, const void *, Oid); /* greater equal */
+ bool (*f_eq) (const void *, const void *, Oid); /* equal */
+ bool (*f_le) (const void *, const void *, Oid); /* less equal */
+ bool (*f_lt) (const void *, const void *, Oid); /* less than */
+ int32 (*f_cmp) (const void *, const void *, Oid); /* compare */
GBT_VARKEY *(*f_l2n) (GBT_VARKEY *); /* convert leaf to node */
} gbtree_vinfo;
@@ -60,21 +51,22 @@ extern GBT_VARKEY *gbt_var_key_copy(const GBT_VARKEY_R *u, bool force_node);
extern GISTENTRY *gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo);
extern GBT_VARKEY *gbt_var_union(const GistEntryVector *entryvec, int32 *size,
- const gbtree_vinfo *tinfo);
+ Oid collation, const gbtree_vinfo *tinfo);
-extern bool gbt_var_same(bool *result, const Datum d1, const Datum d2,
+extern bool gbt_var_same(Datum d1, Datum d2, Oid collation,
const gbtree_vinfo *tinfo);
extern float *gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
- const gbtree_vinfo *tinfo);
+ Oid collation, const gbtree_vinfo *tinfo);
extern bool gbt_var_consistent(GBT_VARKEY_R *key, const void *query,
- const StrategyNumber *strategy, bool is_leaf,
+ StrategyNumber strategy, Oid collation, bool is_leaf,
const gbtree_vinfo *tinfo);
extern GIST_SPLITVEC *gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
- const gbtree_vinfo *tinfo);
-extern void gbt_var_bin_union(Datum *u, GBT_VARKEY *e,
+ Oid collation, const gbtree_vinfo *tinfo);
+
+extern void gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
const gbtree_vinfo *tinfo);
#endif
diff --git a/contrib/btree_gist/data/interval.data b/contrib/btree_gist/data/interval.data
index a4afaedefd..af418c2cbb 100644
--- a/contrib/btree_gist/data/interval.data
+++ b/contrib/btree_gist/data/interval.data
@@ -609,4 +609,4 @@
7243 days 19:10:42
-2143 days -07:51:00
-9553 days -11:47:20
--14153 days -13:26:25 \ No newline at end of file
+-14153 days -13:26:25
diff --git a/contrib/btree_gist/data/macaddr.data b/contrib/btree_gist/data/macaddr.data
index a18c0b2047..12ef5300a1 100644
--- a/contrib/btree_gist/data/macaddr.data
+++ b/contrib/btree_gist/data/macaddr.data
@@ -641,4 +641,4 @@ dd:79:87:70:0b:e7
27:bb:a9:3a:7b:f0
73:3c:06:b1:51:ad
47:0e:59:c0:5d:38
-13:13:e1:1c:aa:25 \ No newline at end of file
+13:13:e1:1c:aa:25
diff --git a/contrib/btree_gist/data/numeric.data b/contrib/btree_gist/data/numeric.data
index 9be64adc0a..58d76fa0ac 100644
--- a/contrib/btree_gist/data/numeric.data
+++ b/contrib/btree_gist/data/numeric.data
@@ -8,4 +8,4 @@
0
0
NaN
-NaN \ No newline at end of file
+NaN
diff --git a/contrib/btree_gist/data/text.data b/contrib/btree_gist/data/text.data
index 512035241f..4494936ad9 100644
--- a/contrib/btree_gist/data/text.data
+++ b/contrib/btree_gist/data/text.data
@@ -1 +1 @@
-2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 \ No newline at end of file
+2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809 2eb2c961c1cbf6 cf8d7b68cb9a2f36 7bbedb4ae7 06ec46c55611a466eb7e3edcc009ca6 e 5ed9cd0ea5a4e55d601027c56a 64cacf3a42afc 90e63000c34506993345355640 79bce 173bb7 c5 574ea7c921cb0f25 089d56d16dff24f336e4740 6870470f1f9afcb4f7c56c9f b97e117fc965 7013029 e48f6dd481 7d00e1e227beef84a9 904d4c34241f cb5c0f14 3a8a70 f51a73164e92052fbb53b4cc2f1fed 3c3fecaa0270175 2521ef03594 fa05756812648f450fb 13c2f b39a0729d6182e9 15b5ea204fe73 d8991afd72d21acd188df1 a29fff57ab897338 de549b3ed5a024534c007125c 2fcf3e5c3e3 7427b6daec5c3f 473 8 a5d9 840410976ac2eeab58e1ca8bf46c2b7 1db9cc85a336f1291ea19922 db808f3548cda91 2e379ce80af12bd7ed56d0338c a ea67a7c847f6620fc894f0ba10044 0e 52e97d975af7201d8 d95e6f08184d8ff 19762476fa 42f278f3534f3f2be0abaed71 f0aba11835e4e1d94 e8534cf677046eafb8f5f761865 ffbee273c7bb 2bb77f6e780 c77e81851c491 e a9f45d765b01a030d5d317 ff7345a22bc360 c87363ba121297b063e83 13ea32e9618d 40304f6c2a7e92c1c66ff4208e a781b4a21419abfdf5eb467e4d48908 8a65656e514b2b3ef8f86310aaf85 4 90b7b2862e3dbc8f0eef3dfc6075bfa eb94a1c a58abb5def4fa43840e6e2716 260e6eaebb 42415d712bf83944dcd1204e 305254fc3b849150b5 5bbd7f8471dcd3621 2ae0548115a250 0c1988e9 76f98bef45639b7 0d5a28f01dc b71 c046576faa4d49eff8 c1e8d01c 10c86c457ea050455a742da4f8 ea7676af85c71c7eeca635 6a07137227404d a4 7186172 8150f31c9a15401c f1bb9057a9938bfa 22b482be08f424ec4 21daea994293589 15bff393f6b17fef24786dd6f9 d5a2d 4b3b5dd9370543e b4a93b2ac4341945d06 d384447812e0 4e3c97e9b8f7 f7d4d644b2a1d373 5102c b9531f725674b28 1aa16e7e34285797c1439 51aa762ea14b40fb8876c887eea6 45a62d3d5d3e946250904697486591 b3f1a8 243524767bf846d 8 95 45a922872 dd2497eb1e3da8d513d2 7821db9e14d4f 24c4f085de60d7c0c6ea3fc6bc e4c9f8c68596d7d afd6c8cb0f2516b87f24bbd8 61d2e457c70949 d2d362cdc657 3605f9d27fd6d72 32de91d66fe5bf537530 859e1a08b65 9b5a55f 4116cda9fddeb843964002 e81f3b2c0ca566ad3dbbc6e234 0d3b1d54 10c440be5c0bca95 7dad841f a61f041967972e805ccfee55c deee9cc16e92ab197 7627554073c1f56b9e 21bebcbfd2e2282f84 7b121a83eeb91db8bda81ba88c634b46394 59885ebc737617addaaf0cb809
diff --git a/contrib/btree_gist/data/timetz.data b/contrib/btree_gist/data/timetz.data
index d342fa30f3..a179a1ece5 100644
--- a/contrib/btree_gist/data/timetz.data
+++ b/contrib/btree_gist/data/timetz.data
@@ -596,4 +596,4 @@
09:20:46 GMT+9
19:38:36 GMT+0
14:15:53 GMT+7
-01:05:51 GMT+6 \ No newline at end of file
+01:05:51 GMT+6
diff --git a/contrib/btree_gist/data/varbit.data b/contrib/btree_gist/data/varbit.data
index 5db3d82957..b25a264dc4 100644
--- a/contrib/btree_gist/data/varbit.data
+++ b/contrib/btree_gist/data/varbit.data
@@ -618,4 +618,4 @@
00101010101001101111000
011000111001010000111101
0110100000111000001111000101010000110110100101101100
-1011100101010110011010010011110100101100100001100111100010100001000111 \ No newline at end of file
+1011100101010110011010010011110100101100100001100111100010100001000111
diff --git a/contrib/btree_gist/expected/cash.out b/contrib/btree_gist/expected/cash.out
index 2beb8cd92d..a4100d844e 100644
--- a/contrib/btree_gist/expected/cash.out
+++ b/contrib/btree_gist/expected/cash.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM moneytmp WHERE a > '22649.64';
253
(1 row)
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+ a | ?column?
+------------+----------
+ $21,472.79 | $0.00
+ $21,469.25 | $3.54
+ $21,915.01 | $442.22
+(3 rows)
+
CREATE INDEX moneyidx ON moneytmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM moneytmp WHERE a < '22649.64'::money;
@@ -64,3 +72,20 @@ SELECT count(*) FROM moneytmp WHERE a > '22649.64'::money;
253
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+ QUERY PLAN
+-----------------------------------------------
+ Limit
+ -> Index Scan using moneyidx on moneytmp
+ Order By: (a <-> '$21,472.79'::money)
+(3 rows)
+
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+ a | ?column?
+------------+----------
+ $21,472.79 | $0.00
+ $21,469.25 | $3.54
+ $21,915.01 | $442.22
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/date.out b/contrib/btree_gist/expected/date.out
index f2082cf391..4a360bea6d 100644
--- a/contrib/btree_gist/expected/date.out
+++ b/contrib/btree_gist/expected/date.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM datetmp WHERE a > '2001-02-13';
313
(1 row)
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+ a | ?column?
+------------+----------
+ 02-13-2001 | 0
+ 02-11-2001 | 2
+ 03-24-2001 | 39
+(3 rows)
+
CREATE INDEX dateidx ON datetmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM datetmp WHERE a < '2001-02-13'::date;
@@ -64,3 +72,20 @@ SELECT count(*) FROM datetmp WHERE a > '2001-02-13'::date;
313
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+ QUERY PLAN
+----------------------------------------------
+ Limit
+ -> Index Scan using dateidx on datetmp
+ Order By: (a <-> '02-13-2001'::date)
+(3 rows)
+
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+ a | ?column?
+------------+----------
+ 02-13-2001 | 0
+ 02-11-2001 | 2
+ 03-24-2001 | 39
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/float4.out b/contrib/btree_gist/expected/float4.out
index c7f65c8d7f..1695f7805a 100644
--- a/contrib/btree_gist/expected/float4.out
+++ b/contrib/btree_gist/expected/float4.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM float4tmp WHERE a > -179.0;
302
(1 row)
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+ a | ?column?
+----------+----------
+ -179 | 0
+ -189.024 | 10.0239
+ -158.177 | 20.8226
+(3 rows)
+
CREATE INDEX float4idx ON float4tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM float4tmp WHERE a < -179.0::float4;
@@ -64,3 +72,20 @@ SELECT count(*) FROM float4tmp WHERE a > -179.0::float4;
302
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+ QUERY PLAN
+-----------------------------------------------
+ Limit
+ -> Index Scan using float4idx on float4tmp
+ Order By: (a <-> (-179)::real)
+(3 rows)
+
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+ a | ?column?
+----------+----------
+ -179 | 0
+ -189.024 | 10.0239
+ -158.177 | 20.8226
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/float8.out b/contrib/btree_gist/expected/float8.out
index 4598ac87a2..7d2228b797 100644
--- a/contrib/btree_gist/expected/float8.out
+++ b/contrib/btree_gist/expected/float8.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM float8tmp WHERE a > -1890.0;
306
(1 row)
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+ a | ?column?
+--------------+------------
+ -1890 | 0
+ -2003.634512 | 113.634512
+ -1769.73634 | 120.26366
+(3 rows)
+
CREATE INDEX float8idx ON float8tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM float8tmp WHERE a < -1890.0::float8;
@@ -64,3 +72,20 @@ SELECT count(*) FROM float8tmp WHERE a > -1890.0::float8;
306
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+ QUERY PLAN
+-----------------------------------------------------
+ Limit
+ -> Index Scan using float8idx on float8tmp
+ Order By: (a <-> (-1890)::double precision)
+(3 rows)
+
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+ a | ?column?
+--------------+------------
+ -1890 | 0
+ -2003.634512 | 113.634512
+ -1769.73634 | 120.26366
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/init.out b/contrib/btree_gist/expected/init.out
index c808249545..afe0534682 100644
--- a/contrib/btree_gist/expected/init.out
+++ b/contrib/btree_gist/expected/init.out
@@ -1,7 +1 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of btree_gist.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION btree_gist;
diff --git a/contrib/btree_gist/expected/int2.out b/contrib/btree_gist/expected/int2.out
index a82819c26a..b1cc3b14b2 100644
--- a/contrib/btree_gist/expected/int2.out
+++ b/contrib/btree_gist/expected/int2.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM int2tmp WHERE a > 237;
248
(1 row)
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+ a | ?column?
+-----+----------
+ 237 | 0
+ 232 | 5
+ 228 | 9
+(3 rows)
+
CREATE INDEX int2idx ON int2tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM int2tmp WHERE a < 237::int2;
@@ -64,3 +72,20 @@ SELECT count(*) FROM int2tmp WHERE a > 237::int2;
248
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+ QUERY PLAN
+-------------------------------------------
+ Limit
+ -> Index Scan using int2idx on int2tmp
+ Order By: (a <-> 237::smallint)
+(3 rows)
+
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+ a | ?column?
+-----+----------
+ 237 | 0
+ 232 | 5
+ 228 | 9
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/int4.out b/contrib/btree_gist/expected/int4.out
index d4ac0e1513..41bed1f6e3 100644
--- a/contrib/btree_gist/expected/int4.out
+++ b/contrib/btree_gist/expected/int4.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM int4tmp WHERE a > 237;
248
(1 row)
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+ a | ?column?
+-----+----------
+ 237 | 0
+ 232 | 5
+ 228 | 9
+(3 rows)
+
CREATE INDEX int4idx ON int4tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM int4tmp WHERE a < 237::int4;
@@ -64,3 +72,20 @@ SELECT count(*) FROM int4tmp WHERE a > 237::int4;
248
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+ QUERY PLAN
+-------------------------------------------
+ Limit
+ -> Index Scan using int4idx on int4tmp
+ Order By: (a <-> 237)
+(3 rows)
+
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+ a | ?column?
+-----+----------
+ 237 | 0
+ 232 | 5
+ 228 | 9
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/int8.out b/contrib/btree_gist/expected/int8.out
index 1da484525b..ff0af4a5fb 100644
--- a/contrib/btree_gist/expected/int8.out
+++ b/contrib/btree_gist/expected/int8.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM int8tmp WHERE a > 464571291354841;
270
(1 row)
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+ a | ?column?
+-----------------+----------------
+ 464571291354841 | 0
+ 457257666629329 | 7313624725512
+ 478227196042750 | 13655904687909
+(3 rows)
+
CREATE INDEX int8idx ON int8tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM int8tmp WHERE a < 464571291354841::int8;
@@ -64,3 +72,20 @@ SELECT count(*) FROM int8tmp WHERE a > 464571291354841::int8;
270
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+ QUERY PLAN
+---------------------------------------------------
+ Limit
+ -> Index Scan using int8idx on int8tmp
+ Order By: (a <-> 464571291354841::bigint)
+(3 rows)
+
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+ a | ?column?
+-----------------+----------------
+ 464571291354841 | 0
+ 457257666629329 | 7313624725512
+ 478227196042750 | 13655904687909
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/interval.out b/contrib/btree_gist/expected/interval.out
index 4c78e21346..6955251a04 100644
--- a/contrib/btree_gist/expected/interval.out
+++ b/contrib/btree_gist/expected/interval.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23';
270
(1 row)
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+ a | ?column?
+-------------------------------------+--------------------------------------
+ @ 199 days 21 hours 21 mins 23 secs | @ 0
+ @ 183 days 6 hours 52 mins 48 secs | @ 16 days 14 hours 28 mins 35 secs
+ @ 220 days 19 hours 5 mins 42 secs | @ 21 days -2 hours -15 mins -41 secs
+(3 rows)
+
CREATE INDEX intervalidx ON intervaltmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM intervaltmp WHERE a < '199 days 21:21:23'::interval;
@@ -64,3 +72,20 @@ SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23'::interval;
270
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+ QUERY PLAN
+---------------------------------------------------------------------------
+ Limit
+ -> Index Scan using intervalidx on intervaltmp
+ Order By: (a <-> '@ 199 days 21 hours 21 mins 23 secs'::interval)
+(3 rows)
+
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+ a | ?column?
+-------------------------------------+--------------------------------------
+ @ 199 days 21 hours 21 mins 23 secs | @ 0
+ @ 183 days 6 hours 52 mins 48 secs | @ 16 days 14 hours 28 mins 35 secs
+ @ 220 days 19 hours 5 mins 42 secs | @ 21 days -2 hours -15 mins -41 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/not_equal.out b/contrib/btree_gist/expected/not_equal.out
new file mode 100644
index 0000000000..d9b91e2d56
--- /dev/null
+++ b/contrib/btree_gist/expected/not_equal.out
@@ -0,0 +1,40 @@
+SET enable_seqscan to false;
+-- test search for "not equals"
+CREATE TABLE test_ne (
+ a TIMESTAMP,
+ b NUMERIC
+);
+CREATE INDEX test_ne_idx ON test_ne USING gist (a, b);
+INSERT INTO test_ne SELECT '2009-01-01', 10.7 FROM generate_series(1,1000);
+INSERT INTO test_ne VALUES('2007-02-03', -91.3);
+INSERT INTO test_ne VALUES('2011-09-01', 43.7);
+INSERT INTO test_ne SELECT '2009-01-01', 10.7 FROM generate_series(1,1000);
+EXPLAIN (COSTS OFF) SELECT * FROM test_ne WHERE a <> '2009-01-01' AND b <> 10.7;
+ QUERY PLAN
+------------------------------------------------------------------------------------------------------
+ Bitmap Heap Scan on test_ne
+ Recheck Cond: ((a <> 'Thu Jan 01 00:00:00 2009'::timestamp without time zone) AND (b <> 10.7))
+ -> Bitmap Index Scan on test_ne_idx
+ Index Cond: ((a <> 'Thu Jan 01 00:00:00 2009'::timestamp without time zone) AND (b <> 10.7))
+(4 rows)
+
+SELECT * FROM test_ne WHERE a <> '2009-01-01' AND b <> 10.7;
+ a | b
+--------------------------+-------
+ Sat Feb 03 00:00:00 2007 | -91.3
+ Thu Sep 01 00:00:00 2011 | 43.7
+(2 rows)
+
+-- test search for "not equals" using an exclusion constraint
+CREATE TABLE zoo (
+ cage INTEGER,
+ animal TEXT,
+ EXCLUDE USING gist (cage WITH =, animal WITH <>)
+);
+NOTICE: CREATE TABLE / EXCLUDE will create implicit index "zoo_cage_animal_excl" for table "zoo"
+INSERT INTO zoo VALUES(123, 'zebra');
+INSERT INTO zoo VALUES(123, 'zebra');
+INSERT INTO zoo VALUES(123, 'lion');
+ERROR: conflicting key value violates exclusion constraint "zoo_cage_animal_excl"
+DETAIL: Key (cage, animal)=(123, lion) conflicts with existing key (cage, animal)=(123, zebra).
+INSERT INTO zoo VALUES(124, 'lion');
diff --git a/contrib/btree_gist/expected/time.out b/contrib/btree_gist/expected/time.out
index 015a67f6a1..1b9da4e192 100644
--- a/contrib/btree_gist/expected/time.out
+++ b/contrib/btree_gist/expected/time.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM timetmp WHERE a > '10:57:11';
292
(1 row)
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+ a | ?column?
+----------+-----------------
+ 10:57:11 | @ 0
+ 10:57:10 | @ 1 sec
+ 10:55:32 | @ 1 min 39 secs
+(3 rows)
+
CREATE INDEX timeidx ON timetmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM timetmp WHERE a < '10:57:11'::time;
@@ -64,3 +72,20 @@ SELECT count(*) FROM timetmp WHERE a > '10:57:11'::time;
292
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+ QUERY PLAN
+--------------------------------------------------------------
+ Limit
+ -> Index Scan using timeidx on timetmp
+ Order By: (a <-> '10:57:11'::time without time zone)
+(3 rows)
+
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+ a | ?column?
+----------+-----------------
+ 10:57:11 | @ 0
+ 10:57:10 | @ 1 sec
+ 10:55:32 | @ 1 min 39 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/timestamp.out b/contrib/btree_gist/expected/timestamp.out
index dc53895ca2..cc3624f084 100644
--- a/contrib/btree_gist/expected/timestamp.out
+++ b/contrib/btree_gist/expected/timestamp.out
@@ -32,6 +32,14 @@ SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08';
289
(1 row)
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+ a | ?column?
+--------------------------+------------------------------------
+ Tue Oct 26 08:55:08 2004 | @ 0
+ Sun Oct 31 06:35:03 2004 | @ 4 days 21 hours 39 mins 55 secs
+ Mon Nov 29 20:12:43 2004 | @ 34 days 11 hours 17 mins 35 secs
+(3 rows)
+
CREATE INDEX timestampidx ON timestamptmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM timestamptmp WHERE a < '2004-10-26 08:55:08'::timestamp;
@@ -64,3 +72,20 @@ SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08'::timestamp;
289
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+ QUERY PLAN
+-----------------------------------------------------------------------------------
+ Limit
+ -> Index Scan using timestampidx on timestamptmp
+ Order By: (a <-> 'Tue Oct 26 08:55:08 2004'::timestamp without time zone)
+(3 rows)
+
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+ a | ?column?
+--------------------------+------------------------------------
+ Tue Oct 26 08:55:08 2004 | @ 0
+ Sun Oct 31 06:35:03 2004 | @ 4 days 21 hours 39 mins 55 secs
+ Mon Nov 29 20:12:43 2004 | @ 34 days 11 hours 17 mins 35 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/expected/timestamptz.out b/contrib/btree_gist/expected/timestamptz.out
index 391705f0db..88d2404c44 100644
--- a/contrib/btree_gist/expected/timestamptz.out
+++ b/contrib/btree_gist/expected/timestamptz.out
@@ -92,6 +92,14 @@ SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4';
157
(1 row)
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+ a | ?column?
+------------------------------+-----------------------------------
+ Tue Dec 18 05:59:54 2018 PST | @ 1 hour
+ Thu Jan 10 03:01:34 2019 PST | @ 22 days 22 hours 1 min 40 secs
+ Thu Jan 24 12:28:12 2019 PST | @ 37 days 7 hours 28 mins 18 secs
+(3 rows)
+
CREATE INDEX timestamptzidx ON timestamptztmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+3'::timestamptz;
@@ -184,3 +192,20 @@ SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4'::time
157
(1 row)
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Limit
+ -> Index Scan using timestamptzidx on timestamptztmp
+ Order By: (a <-> 'Tue Dec 18 04:59:54 2018 PST'::timestamp with time zone)
+(3 rows)
+
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+ a | ?column?
+------------------------------+-----------------------------------
+ Tue Dec 18 05:59:54 2018 PST | @ 1 hour
+ Thu Jan 10 03:01:34 2019 PST | @ 22 days 22 hours 1 min 40 secs
+ Thu Jan 24 12:28:12 2019 PST | @ 37 days 7 hours 28 mins 18 secs
+(3 rows)
+
diff --git a/contrib/btree_gist/sql/cash.sql b/contrib/btree_gist/sql/cash.sql
index 5313e8f696..0e037984e1 100644
--- a/contrib/btree_gist/sql/cash.sql
+++ b/contrib/btree_gist/sql/cash.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM moneytmp WHERE a >= '22649.64';
SELECT count(*) FROM moneytmp WHERE a > '22649.64';
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+
CREATE INDEX moneyidx ON moneytmp USING gist ( a );
SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM moneytmp WHERE a = '22649.64'::money;
SELECT count(*) FROM moneytmp WHERE a >= '22649.64'::money;
SELECT count(*) FROM moneytmp WHERE a > '22649.64'::money;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
+SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
diff --git a/contrib/btree_gist/sql/cidr.sql b/contrib/btree_gist/sql/cidr.sql
index de06c24c92..9bd77185b9 100644
--- a/contrib/btree_gist/sql/cidr.sql
+++ b/contrib/btree_gist/sql/cidr.sql
@@ -28,4 +28,3 @@ SELECT count(*) FROM cidrtmp WHERE a = '121.111.63.82'::cidr;
SELECT count(*) FROM cidrtmp WHERE a >= '121.111.63.82'::cidr;
SELECT count(*) FROM cidrtmp WHERE a > '121.111.63.82'::cidr;
-
diff --git a/contrib/btree_gist/sql/date.sql b/contrib/btree_gist/sql/date.sql
index 3fa855c905..f969ef0a08 100644
--- a/contrib/btree_gist/sql/date.sql
+++ b/contrib/btree_gist/sql/date.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM datetmp WHERE a >= '2001-02-13';
SELECT count(*) FROM datetmp WHERE a > '2001-02-13';
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+
CREATE INDEX dateidx ON datetmp USING gist ( a );
SET enable_seqscan=off;
@@ -30,3 +32,6 @@ SELECT count(*) FROM datetmp WHERE a >= '2001-02-13'::date;
SELECT count(*) FROM datetmp WHERE a > '2001-02-13'::date;
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
+SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
diff --git a/contrib/btree_gist/sql/float4.sql b/contrib/btree_gist/sql/float4.sql
index fb4b726d22..3da1ce953c 100644
--- a/contrib/btree_gist/sql/float4.sql
+++ b/contrib/btree_gist/sql/float4.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM float4tmp WHERE a >= -179.0;
SELECT count(*) FROM float4tmp WHERE a > -179.0;
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+
CREATE INDEX float4idx ON float4tmp USING gist ( a );
SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM float4tmp WHERE a = -179.0::float4;
SELECT count(*) FROM float4tmp WHERE a >= -179.0::float4;
SELECT count(*) FROM float4tmp WHERE a > -179.0::float4;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
+SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
diff --git a/contrib/btree_gist/sql/float8.sql b/contrib/btree_gist/sql/float8.sql
index f8bd12efa1..e1e819b37f 100644
--- a/contrib/btree_gist/sql/float8.sql
+++ b/contrib/btree_gist/sql/float8.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM float8tmp WHERE a >= -1890.0;
SELECT count(*) FROM float8tmp WHERE a > -1890.0;
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+
CREATE INDEX float8idx ON float8tmp USING gist ( a );
SET enable_seqscan=off;
@@ -29,3 +31,7 @@ SELECT count(*) FROM float8tmp WHERE a = -1890.0::float8;
SELECT count(*) FROM float8tmp WHERE a >= -1890.0::float8;
SELECT count(*) FROM float8tmp WHERE a > -1890.0::float8;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
+SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
diff --git a/contrib/btree_gist/sql/inet.sql b/contrib/btree_gist/sql/inet.sql
index 39594945fe..328846c0a3 100644
--- a/contrib/btree_gist/sql/inet.sql
+++ b/contrib/btree_gist/sql/inet.sql
@@ -29,4 +29,3 @@ SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
SELECT count(*) FROM inettmp WHERE a >= '89.225.196.191'::inet;
SELECT count(*) FROM inettmp WHERE a > '89.225.196.191'::inet;
-
diff --git a/contrib/btree_gist/sql/init.sql b/contrib/btree_gist/sql/init.sql
index 7fafde12d8..afe0534682 100644
--- a/contrib/btree_gist/sql/init.sql
+++ b/contrib/btree_gist/sql/init.sql
@@ -1,9 +1 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of btree_gist.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i btree_gist.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION btree_gist;
diff --git a/contrib/btree_gist/sql/int2.sql b/contrib/btree_gist/sql/int2.sql
index c8303bde12..988518795f 100644
--- a/contrib/btree_gist/sql/int2.sql
+++ b/contrib/btree_gist/sql/int2.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM int2tmp WHERE a >= 237;
SELECT count(*) FROM int2tmp WHERE a > 237;
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+
CREATE INDEX int2idx ON int2tmp USING gist ( a );
SET enable_seqscan=off;
@@ -30,3 +32,6 @@ SELECT count(*) FROM int2tmp WHERE a >= 237::int2;
SELECT count(*) FROM int2tmp WHERE a > 237::int2;
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
+SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
diff --git a/contrib/btree_gist/sql/int4.sql b/contrib/btree_gist/sql/int4.sql
index 2f80c5afd1..659ab5ee24 100644
--- a/contrib/btree_gist/sql/int4.sql
+++ b/contrib/btree_gist/sql/int4.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM int4tmp WHERE a >= 237;
SELECT count(*) FROM int4tmp WHERE a > 237;
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+
CREATE INDEX int4idx ON int4tmp USING gist ( a );
SET enable_seqscan=off;
@@ -30,3 +32,6 @@ SELECT count(*) FROM int4tmp WHERE a >= 237::int4;
SELECT count(*) FROM int4tmp WHERE a > 237::int4;
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
+SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
diff --git a/contrib/btree_gist/sql/int8.sql b/contrib/btree_gist/sql/int8.sql
index 97ad6056ed..51e55e9c14 100644
--- a/contrib/btree_gist/sql/int8.sql
+++ b/contrib/btree_gist/sql/int8.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM int8tmp WHERE a >= 464571291354841;
SELECT count(*) FROM int8tmp WHERE a > 464571291354841;
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+
CREATE INDEX int8idx ON int8tmp USING gist ( a );
SET enable_seqscan=off;
@@ -30,3 +32,6 @@ SELECT count(*) FROM int8tmp WHERE a >= 464571291354841::int8;
SELECT count(*) FROM int8tmp WHERE a > 464571291354841::int8;
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
+SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
diff --git a/contrib/btree_gist/sql/interval.sql b/contrib/btree_gist/sql/interval.sql
index 2139435065..0f8b031520 100644
--- a/contrib/btree_gist/sql/interval.sql
+++ b/contrib/btree_gist/sql/interval.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM intervaltmp WHERE a >= '199 days 21:21:23';
SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23';
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+
CREATE INDEX intervalidx ON intervaltmp USING gist ( a );
SET enable_seqscan=off;
@@ -30,3 +32,6 @@ SELECT count(*) FROM intervaltmp WHERE a >= '199 days 21:21:23'::interval;
SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23'::interval;
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
+SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
diff --git a/contrib/btree_gist/sql/macaddr.sql b/contrib/btree_gist/sql/macaddr.sql
index 18e0f3c68b..d9c54b2930 100644
--- a/contrib/btree_gist/sql/macaddr.sql
+++ b/contrib/btree_gist/sql/macaddr.sql
@@ -29,4 +29,3 @@ SELECT count(*) FROM macaddrtmp WHERE a = '22:00:5c:e5:9b:0d'::macaddr;
SELECT count(*) FROM macaddrtmp WHERE a >= '22:00:5c:e5:9b:0d'::macaddr;
SELECT count(*) FROM macaddrtmp WHERE a > '22:00:5c:e5:9b:0d'::macaddr;
-
diff --git a/contrib/btree_gist/sql/not_equal.sql b/contrib/btree_gist/sql/not_equal.sql
new file mode 100644
index 0000000000..b1940ef4fe
--- /dev/null
+++ b/contrib/btree_gist/sql/not_equal.sql
@@ -0,0 +1,32 @@
+
+SET enable_seqscan to false;
+
+-- test search for "not equals"
+
+CREATE TABLE test_ne (
+ a TIMESTAMP,
+ b NUMERIC
+);
+CREATE INDEX test_ne_idx ON test_ne USING gist (a, b);
+
+INSERT INTO test_ne SELECT '2009-01-01', 10.7 FROM generate_series(1,1000);
+INSERT INTO test_ne VALUES('2007-02-03', -91.3);
+INSERT INTO test_ne VALUES('2011-09-01', 43.7);
+INSERT INTO test_ne SELECT '2009-01-01', 10.7 FROM generate_series(1,1000);
+
+EXPLAIN (COSTS OFF) SELECT * FROM test_ne WHERE a <> '2009-01-01' AND b <> 10.7;
+
+SELECT * FROM test_ne WHERE a <> '2009-01-01' AND b <> 10.7;
+
+-- test search for "not equals" using an exclusion constraint
+
+CREATE TABLE zoo (
+ cage INTEGER,
+ animal TEXT,
+ EXCLUDE USING gist (cage WITH =, animal WITH <>)
+);
+
+INSERT INTO zoo VALUES(123, 'zebra');
+INSERT INTO zoo VALUES(123, 'zebra');
+INSERT INTO zoo VALUES(123, 'lion');
+INSERT INTO zoo VALUES(124, 'lion');
diff --git a/contrib/btree_gist/sql/time.sql b/contrib/btree_gist/sql/time.sql
index 304e28add8..6104e7f61c 100644
--- a/contrib/btree_gist/sql/time.sql
+++ b/contrib/btree_gist/sql/time.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM timetmp WHERE a >= '10:57:11';
SELECT count(*) FROM timetmp WHERE a > '10:57:11';
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+
CREATE INDEX timeidx ON timetmp USING gist ( a );
SET enable_seqscan=off;
@@ -30,3 +32,6 @@ SELECT count(*) FROM timetmp WHERE a >= '10:57:11'::time;
SELECT count(*) FROM timetmp WHERE a > '10:57:11'::time;
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
+SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
diff --git a/contrib/btree_gist/sql/timestamp.sql b/contrib/btree_gist/sql/timestamp.sql
index 5b04e3e2d2..95effebfc4 100644
--- a/contrib/btree_gist/sql/timestamp.sql
+++ b/contrib/btree_gist/sql/timestamp.sql
@@ -16,6 +16,8 @@ SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08';
SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08';
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+
CREATE INDEX timestampidx ON timestamptmp USING gist ( a );
SET enable_seqscan=off;
@@ -30,3 +32,6 @@ SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08'::timestamp;
SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08'::timestamp;
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
+SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
diff --git a/contrib/btree_gist/sql/timestamptz.sql b/contrib/btree_gist/sql/timestamptz.sql
index 371233bc53..f70caa4a64 100644
--- a/contrib/btree_gist/sql/timestamptz.sql
+++ b/contrib/btree_gist/sql/timestamptz.sql
@@ -37,7 +37,7 @@ SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4';
SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4';
-
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
CREATE INDEX timestamptzidx ON timestamptztmp USING gist ( a );
@@ -74,3 +74,7 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+4'::time
SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4'::timestamptz;
SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4'::timestamptz;
+
+EXPLAIN (COSTS OFF)
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
+SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
diff --git a/contrib/btree_gist/uninstall_btree_gist.sql b/contrib/btree_gist/uninstall_btree_gist.sql
deleted file mode 100644
index 9e71819e1a..0000000000
--- a/contrib/btree_gist/uninstall_btree_gist.sql
+++ /dev/null
@@ -1,280 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/btree_gist/uninstall_btree_gist.sql,v 1.5 2008/04/14 17:05:32 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR CLASS gist_cidr_ops USING gist;
-
-DROP OPERATOR CLASS gist_inet_ops USING gist;
-
-DROP FUNCTION gbt_inet_same(internal, internal, internal);
-
-DROP FUNCTION gbt_inet_union(bytea, internal);
-
-DROP FUNCTION gbt_inet_picksplit(internal, internal);
-
-DROP FUNCTION gbt_inet_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_inet_compress(internal);
-
-DROP FUNCTION gbt_inet_consistent(internal,inet,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_vbit_ops USING gist;
-
-DROP OPERATOR CLASS gist_bit_ops USING gist;
-
-DROP FUNCTION gbt_bit_same(internal, internal, internal);
-
-DROP FUNCTION gbt_bit_union(bytea, internal);
-
-DROP FUNCTION gbt_bit_picksplit(internal, internal);
-
-DROP FUNCTION gbt_bit_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_bit_compress(internal);
-
-DROP FUNCTION gbt_bit_consistent(internal,bit,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_numeric_ops USING gist;
-
-DROP FUNCTION gbt_numeric_same(internal, internal, internal);
-
-DROP FUNCTION gbt_numeric_union(bytea, internal);
-
-DROP FUNCTION gbt_numeric_picksplit(internal, internal);
-
-DROP FUNCTION gbt_numeric_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_numeric_compress(internal);
-
-DROP FUNCTION gbt_numeric_consistent(internal,numeric,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_bytea_ops USING gist;
-
-DROP FUNCTION gbt_bytea_same(internal, internal, internal);
-
-DROP FUNCTION gbt_bytea_union(bytea, internal);
-
-DROP FUNCTION gbt_bytea_picksplit(internal, internal);
-
-DROP FUNCTION gbt_bytea_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_bytea_compress(internal);
-
-DROP FUNCTION gbt_bytea_consistent(internal,bytea,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_bpchar_ops USING gist;
-
-DROP OPERATOR CLASS gist_text_ops USING gist;
-
-DROP FUNCTION gbt_text_same(internal, internal, internal);
-
-DROP FUNCTION gbt_text_union(bytea, internal);
-
-DROP FUNCTION gbt_text_picksplit(internal, internal);
-
-DROP FUNCTION gbt_text_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_bpchar_compress(internal);
-
-DROP FUNCTION gbt_text_compress(internal);
-
-DROP FUNCTION gbt_bpchar_consistent(internal,bpchar,int2,oid,internal);
-
-DROP FUNCTION gbt_text_consistent(internal,text,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_macaddr_ops USING gist;
-
-DROP FUNCTION gbt_macad_same(internal, internal, internal);
-
-DROP FUNCTION gbt_macad_union(bytea, internal);
-
-DROP FUNCTION gbt_macad_picksplit(internal, internal);
-
-DROP FUNCTION gbt_macad_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_macad_compress(internal);
-
-DROP FUNCTION gbt_macad_consistent(internal,macaddr,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_cash_ops USING gist;
-
-DROP FUNCTION gbt_cash_same(internal, internal, internal);
-
-DROP FUNCTION gbt_cash_union(bytea, internal);
-
-DROP FUNCTION gbt_cash_picksplit(internal, internal);
-
-DROP FUNCTION gbt_cash_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_cash_compress(internal);
-
-DROP FUNCTION gbt_cash_consistent(internal,money,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_interval_ops USING gist;
-
-DROP FUNCTION gbt_intv_same(internal, internal, internal);
-
-DROP FUNCTION gbt_intv_union(bytea, internal);
-
-DROP FUNCTION gbt_intv_picksplit(internal, internal);
-
-DROP FUNCTION gbt_intv_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_intv_decompress(internal);
-
-DROP FUNCTION gbt_intv_compress(internal);
-
-DROP FUNCTION gbt_intv_consistent(internal,interval,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_date_ops USING gist;
-
-DROP FUNCTION gbt_date_same(internal, internal, internal);
-
-DROP FUNCTION gbt_date_union(bytea, internal);
-
-DROP FUNCTION gbt_date_picksplit(internal, internal);
-
-DROP FUNCTION gbt_date_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_date_compress(internal);
-
-DROP FUNCTION gbt_date_consistent(internal,date,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_timetz_ops USING gist;
-
-DROP OPERATOR CLASS gist_time_ops USING gist;
-
-DROP FUNCTION gbt_time_same(internal, internal, internal);
-
-DROP FUNCTION gbt_time_union(bytea, internal);
-
-DROP FUNCTION gbt_time_picksplit(internal, internal);
-
-DROP FUNCTION gbt_time_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_timetz_compress(internal);
-
-DROP FUNCTION gbt_time_compress(internal);
-
-DROP FUNCTION gbt_timetz_consistent(internal,timetz,int2,oid,internal);
-
-DROP FUNCTION gbt_time_consistent(internal,time,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_timestamptz_ops USING gist;
-
-DROP OPERATOR CLASS gist_timestamp_ops USING gist;
-
-DROP FUNCTION gbt_ts_same(internal, internal, internal);
-
-DROP FUNCTION gbt_ts_union(bytea, internal);
-
-DROP FUNCTION gbt_ts_picksplit(internal, internal);
-
-DROP FUNCTION gbt_ts_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_tstz_compress(internal);
-
-DROP FUNCTION gbt_ts_compress(internal);
-
-DROP FUNCTION gbt_tstz_consistent(internal,timestamptz,int2,oid,internal);
-
-DROP FUNCTION gbt_ts_consistent(internal,timestamp,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_float8_ops USING gist;
-
-DROP FUNCTION gbt_float8_same(internal, internal, internal);
-
-DROP FUNCTION gbt_float8_union(bytea, internal);
-
-DROP FUNCTION gbt_float8_picksplit(internal, internal);
-
-DROP FUNCTION gbt_float8_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_float8_compress(internal);
-
-DROP FUNCTION gbt_float8_consistent(internal,float8,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_float4_ops USING gist;
-
-DROP FUNCTION gbt_float4_same(internal, internal, internal);
-
-DROP FUNCTION gbt_float4_union(bytea, internal);
-
-DROP FUNCTION gbt_float4_picksplit(internal, internal);
-
-DROP FUNCTION gbt_float4_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_float4_compress(internal);
-
-DROP FUNCTION gbt_float4_consistent(internal,float4,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_int8_ops USING gist;
-
-DROP FUNCTION gbt_int8_same(internal, internal, internal);
-
-DROP FUNCTION gbt_int8_union(bytea, internal);
-
-DROP FUNCTION gbt_int8_picksplit(internal, internal);
-
-DROP FUNCTION gbt_int8_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_int8_compress(internal);
-
-DROP FUNCTION gbt_int8_consistent(internal,int8,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_int4_ops USING gist;
-
-DROP FUNCTION gbt_int4_same(internal, internal, internal);
-
-DROP FUNCTION gbt_int4_union(bytea, internal);
-
-DROP FUNCTION gbt_int4_picksplit(internal, internal);
-
-DROP FUNCTION gbt_int4_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_int4_compress(internal);
-
-DROP FUNCTION gbt_int4_consistent(internal,int4,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_int2_ops USING gist;
-
-DROP FUNCTION gbt_int2_same(internal, internal, internal);
-
-DROP FUNCTION gbt_int2_union(bytea, internal);
-
-DROP FUNCTION gbt_int2_picksplit(internal, internal);
-
-DROP FUNCTION gbt_int2_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_int2_compress(internal);
-
-DROP FUNCTION gbt_int2_consistent(internal,int2,int2,oid,internal);
-
-DROP OPERATOR CLASS gist_oid_ops USING gist;
-
-DROP FUNCTION gbt_oid_same(internal, internal, internal);
-
-DROP FUNCTION gbt_oid_union(bytea, internal);
-
-DROP FUNCTION gbt_oid_picksplit(internal, internal);
-
-DROP FUNCTION gbt_oid_penalty(internal,internal,internal);
-
-DROP FUNCTION gbt_var_decompress(internal);
-
-DROP FUNCTION gbt_decompress(internal);
-
-DROP FUNCTION gbt_oid_compress(internal);
-
-DROP FUNCTION gbt_oid_consistent(internal,oid,int2,oid,internal);
-
-DROP TYPE gbtreekey_var CASCADE;
-
-DROP TYPE gbtreekey32 CASCADE;
-
-DROP TYPE gbtreekey16 CASCADE;
-
-DROP TYPE gbtreekey8 CASCADE;
-
-DROP TYPE gbtreekey4 CASCADE;
diff --git a/contrib/chkpass/Makefile b/contrib/chkpass/Makefile
index f106b6dcfe..b775aef17d 100644
--- a/contrib/chkpass/Makefile
+++ b/contrib/chkpass/Makefile
@@ -1,10 +1,12 @@
-# $PostgreSQL: pgsql/contrib/chkpass/Makefile,v 1.10 2007/11/10 23:59:50 momjian Exp $
+# contrib/chkpass/Makefile
MODULE_big = chkpass
OBJS = chkpass.o
+
+EXTENSION = chkpass
+DATA = chkpass--1.0.sql chkpass--unpackaged--1.0.sql
+
SHLIB_LINK = $(filter -lcrypt, $(LIBS))
-DATA_built = chkpass.sql
-DATA = uninstall_chkpass.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/chkpass/chkpass.sql.in b/contrib/chkpass/chkpass--1.0.sql
index 93dbade064..755fee3bc3 100644
--- a/contrib/chkpass/chkpass.sql.in
+++ b/contrib/chkpass/chkpass--1.0.sql
@@ -1,30 +1,26 @@
-/* $PostgreSQL: pgsql/contrib/chkpass/chkpass.sql.in,v 1.9 2007/11/13 04:24:27 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/chkpass/chkpass--1.0.sql */
--
-- Input and output functions and the type itself:
--
-CREATE OR REPLACE FUNCTION chkpass_in(cstring)
+CREATE FUNCTION chkpass_in(cstring)
RETURNS chkpass
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION chkpass_out(chkpass)
+CREATE FUNCTION chkpass_out(chkpass)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
CREATE TYPE chkpass (
internallength = 16,
- externallength = 13,
input = chkpass_in,
output = chkpass_out
);
-CREATE OR REPLACE FUNCTION raw(chkpass)
+CREATE FUNCTION raw(chkpass)
RETURNS text
AS 'MODULE_PATHNAME', 'chkpass_rout'
LANGUAGE C STRICT;
@@ -33,12 +29,12 @@ CREATE OR REPLACE FUNCTION raw(chkpass)
-- The various boolean tests:
--
-CREATE OR REPLACE FUNCTION eq(chkpass, text)
+CREATE FUNCTION eq(chkpass, text)
RETURNS bool
AS 'MODULE_PATHNAME', 'chkpass_eq'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION ne(chkpass, text)
+CREATE FUNCTION ne(chkpass, text)
RETURNS bool
AS 'MODULE_PATHNAME', 'chkpass_ne'
LANGUAGE C STRICT;
diff --git a/contrib/chkpass/chkpass--unpackaged--1.0.sql b/contrib/chkpass/chkpass--unpackaged--1.0.sql
new file mode 100644
index 0000000000..bf91950f3c
--- /dev/null
+++ b/contrib/chkpass/chkpass--unpackaged--1.0.sql
@@ -0,0 +1,10 @@
+/* contrib/chkpass/chkpass--unpackaged--1.0.sql */
+
+ALTER EXTENSION chkpass ADD type chkpass;
+ALTER EXTENSION chkpass ADD function chkpass_in(cstring);
+ALTER EXTENSION chkpass ADD function chkpass_out(chkpass);
+ALTER EXTENSION chkpass ADD function raw(chkpass);
+ALTER EXTENSION chkpass ADD function eq(chkpass,text);
+ALTER EXTENSION chkpass ADD function ne(chkpass,text);
+ALTER EXTENSION chkpass ADD operator <>(chkpass,text);
+ALTER EXTENSION chkpass ADD operator =(chkpass,text);
diff --git a/contrib/chkpass/chkpass.c b/contrib/chkpass/chkpass.c
index 56a998ec83..0c9fec0e67 100644
--- a/contrib/chkpass/chkpass.c
+++ b/contrib/chkpass/chkpass.c
@@ -4,7 +4,7 @@
* darcy@druid.net
* http://www.druid.net/darcy/
*
- * $PostgreSQL: pgsql/contrib/chkpass/chkpass.c,v 1.21 2009/06/11 14:48:50 momjian Exp $
+ * contrib/chkpass/chkpass.c
* best viewed with tabs set to 4
*/
diff --git a/contrib/chkpass/chkpass.control b/contrib/chkpass/chkpass.control
new file mode 100644
index 0000000000..bd4b3d3d0d
--- /dev/null
+++ b/contrib/chkpass/chkpass.control
@@ -0,0 +1,5 @@
+# chkpass extension
+comment = 'data type for auto-encrypted passwords'
+default_version = '1.0'
+module_pathname = '$libdir/chkpass'
+relocatable = true
diff --git a/contrib/chkpass/uninstall_chkpass.sql b/contrib/chkpass/uninstall_chkpass.sql
deleted file mode 100644
index 386fc95c5f..0000000000
--- a/contrib/chkpass/uninstall_chkpass.sql
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/chkpass/uninstall_chkpass.sql,v 1.5 2007/11/13 04:24:27 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR <>(chkpass, text);
-
-DROP OPERATOR =(chkpass, text);
-
-DROP FUNCTION ne(chkpass, text);
-
-DROP FUNCTION eq(chkpass, text);
-
-DROP FUNCTION raw(chkpass);
-
-DROP TYPE chkpass CASCADE;
diff --git a/contrib/citext/.gitignore b/contrib/citext/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/citext/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/citext/Makefile b/contrib/citext/Makefile
index d38e2762dd..65942528dd 100644
--- a/contrib/citext/Makefile
+++ b/contrib/citext/Makefile
@@ -1,8 +1,10 @@
-# $PostgreSQL: pgsql/contrib/citext/Makefile,v 1.1 2008/07/29 18:31:20 tgl Exp $
+# contrib/citext/Makefile
MODULES = citext
-DATA_built = citext.sql
-DATA = uninstall_citext.sql
+
+EXTENSION = citext
+DATA = citext--1.0.sql citext--unpackaged--1.0.sql
+
REGRESS = citext
ifdef USE_PGXS
diff --git a/contrib/citext/citext.sql.in b/contrib/citext/citext--1.0.sql
index bd781e6168..2760f7e08d 100644
--- a/contrib/citext/citext.sql.in
+++ b/contrib/citext/citext--1.0.sql
@@ -1,7 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/citext/citext.sql.in,v 1.3 2008/09/05 18:25:16 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/citext/citext--1.0.sql */
--
-- PostgreSQL code for CITEXT.
@@ -19,22 +16,22 @@ CREATE TYPE citext;
--
-- Input and output functions.
--
-CREATE OR REPLACE FUNCTION citextin(cstring)
+CREATE FUNCTION citextin(cstring)
RETURNS citext
AS 'textin'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citextout(citext)
+CREATE FUNCTION citextout(citext)
RETURNS cstring
AS 'textout'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citextrecv(internal)
+CREATE FUNCTION citextrecv(internal)
RETURNS citext
AS 'textrecv'
LANGUAGE internal STABLE STRICT;
-CREATE OR REPLACE FUNCTION citextsend(citext)
+CREATE FUNCTION citextsend(citext)
RETURNS bytea
AS 'textsend'
LANGUAGE internal STABLE STRICT;
@@ -52,7 +49,8 @@ CREATE TYPE citext (
STORAGE = extended,
-- make it a non-preferred member of string type category
CATEGORY = 'S',
- PREFERRED = false
+ PREFERRED = false,
+ COLLATABLE = true
);
--
@@ -60,17 +58,17 @@ CREATE TYPE citext (
-- automatically kick in.
--
-CREATE OR REPLACE FUNCTION citext(bpchar)
+CREATE FUNCTION citext(bpchar)
RETURNS citext
AS 'rtrim1'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext(boolean)
+CREATE FUNCTION citext(boolean)
RETURNS citext
AS 'booltext'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext(inet)
+CREATE FUNCTION citext(inet)
RETURNS citext
AS 'network_show'
LANGUAGE internal IMMUTABLE STRICT;
@@ -92,32 +90,32 @@ CREATE CAST (inet AS citext) WITH FUNCTION citext(inet) AS ASSIGNMENT;
-- Operator Functions.
--
-CREATE OR REPLACE FUNCTION citext_eq( citext, citext )
+CREATE FUNCTION citext_eq( citext, citext )
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext_ne( citext, citext )
+CREATE FUNCTION citext_ne( citext, citext )
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext_lt( citext, citext )
+CREATE FUNCTION citext_lt( citext, citext )
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext_le( citext, citext )
+CREATE FUNCTION citext_le( citext, citext )
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext_gt( citext, citext )
+CREATE FUNCTION citext_gt( citext, citext )
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext_ge( citext, citext )
+CREATE FUNCTION citext_ge( citext, citext )
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -192,12 +190,12 @@ CREATE OPERATOR > (
-- Support functions for indexing.
--
-CREATE OR REPLACE FUNCTION citext_cmp(citext, citext)
+CREATE FUNCTION citext_cmp(citext, citext)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION citext_hash(citext)
+CREATE FUNCTION citext_hash(citext)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -228,12 +226,12 @@ DEFAULT FOR TYPE citext USING hash AS
-- Aggregates.
--
-CREATE OR REPLACE FUNCTION citext_smaller(citext, citext)
+CREATE FUNCTION citext_smaller(citext, citext)
RETURNS citext
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION citext_larger(citext, citext)
+CREATE FUNCTION citext_larger(citext, citext)
RETURNS citext
AS 'MODULE_PATHNAME'
LANGUAGE 'C' IMMUTABLE STRICT;
@@ -254,19 +252,19 @@ CREATE AGGREGATE max(citext) (
-- CITEXT pattern matching.
--
-CREATE OR REPLACE FUNCTION texticlike(citext, citext)
+CREATE FUNCTION texticlike(citext, citext)
RETURNS bool AS 'texticlike'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION texticnlike(citext, citext)
+CREATE FUNCTION texticnlike(citext, citext)
RETURNS bool AS 'texticnlike'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION texticregexeq(citext, citext)
+CREATE FUNCTION texticregexeq(citext, citext)
RETURNS bool AS 'texticregexeq'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION texticregexne(citext, citext)
+CREATE FUNCTION texticregexne(citext, citext)
RETURNS bool AS 'texticregexne'
LANGUAGE internal IMMUTABLE STRICT;
@@ -343,22 +341,22 @@ CREATE OPERATOR !~~* (
);
--
--- Matching citext to text.
+-- Matching citext to text.
--
-CREATE OR REPLACE FUNCTION texticlike(citext, text)
+CREATE FUNCTION texticlike(citext, text)
RETURNS bool AS 'texticlike'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION texticnlike(citext, text)
+CREATE FUNCTION texticnlike(citext, text)
RETURNS bool AS 'texticnlike'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION texticregexeq(citext, text)
+CREATE FUNCTION texticregexeq(citext, text)
RETURNS bool AS 'texticregexeq'
LANGUAGE internal IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION texticregexne(citext, text)
+CREATE FUNCTION texticregexne(citext, text)
RETURNS bool AS 'texticregexne'
LANGUAGE internal IMMUTABLE STRICT;
@@ -439,50 +437,50 @@ CREATE OPERATOR !~~* (
-- XXX TODO Ideally these would be implemented in C.
--
-CREATE OR REPLACE FUNCTION regexp_matches( citext, citext ) RETURNS TEXT[] AS $$
+CREATE FUNCTION regexp_matches( citext, citext ) RETURNS TEXT[] AS $$
SELECT pg_catalog.regexp_matches( $1::pg_catalog.text, $2::pg_catalog.text, 'i' );
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION regexp_matches( citext, citext, text ) RETURNS TEXT[] AS $$
+CREATE FUNCTION regexp_matches( citext, citext, text ) RETURNS 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;
-CREATE OR REPLACE FUNCTION regexp_replace( citext, citext, text ) returns TEXT AS $$
+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');
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION regexp_replace( citext, citext, text, text ) returns TEXT AS $$
+CREATE FUNCTION regexp_replace( citext, citext, text, text ) returns TEXT AS $$
SELECT pg_catalog.regexp_replace( $1::pg_catalog.text, $2::pg_catalog.text, $3, CASE WHEN pg_catalog.strpos($4, 'c') = 0 THEN $4 || 'i' ELSE $4 END);
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION regexp_split_to_array( citext, citext ) RETURNS TEXT[] AS $$
+CREATE FUNCTION regexp_split_to_array( citext, citext ) RETURNS TEXT[] AS $$
SELECT pg_catalog.regexp_split_to_array( $1::pg_catalog.text, $2::pg_catalog.text, 'i' );
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION regexp_split_to_array( citext, citext, text ) RETURNS TEXT[] AS $$
+CREATE FUNCTION regexp_split_to_array( citext, citext, text ) RETURNS TEXT[] AS $$
SELECT pg_catalog.regexp_split_to_array( $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;
-CREATE OR REPLACE FUNCTION regexp_split_to_table( citext, citext ) RETURNS SETOF TEXT AS $$
+CREATE FUNCTION regexp_split_to_table( citext, citext ) RETURNS SETOF TEXT AS $$
SELECT pg_catalog.regexp_split_to_table( $1::pg_catalog.text, $2::pg_catalog.text, 'i' );
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION regexp_split_to_table( citext, citext, text ) RETURNS SETOF TEXT AS $$
+CREATE FUNCTION regexp_split_to_table( citext, citext, text ) RETURNS SETOF TEXT AS $$
SELECT pg_catalog.regexp_split_to_table( $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;
-CREATE OR REPLACE FUNCTION strpos( citext, citext ) RETURNS INT AS $$
+CREATE FUNCTION strpos( citext, citext ) RETURNS INT AS $$
SELECT pg_catalog.strpos( pg_catalog.lower( $1::pg_catalog.text ), pg_catalog.lower( $2::pg_catalog.text ) );
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION replace( citext, citext, citext ) RETURNS TEXT AS $$
+CREATE FUNCTION replace( citext, citext, citext ) RETURNS TEXT AS $$
SELECT pg_catalog.regexp_replace( $1::pg_catalog.text, pg_catalog.regexp_replace($2::pg_catalog.text, '([^a-zA-Z_0-9])', E'\\\\\\1', 'g'), $3::pg_catalog.text, 'gi' );
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION split_part( citext, citext, int ) RETURNS TEXT AS $$
+CREATE FUNCTION split_part( citext, citext, int ) RETURNS TEXT AS $$
SELECT (pg_catalog.regexp_split_to_array( $1::pg_catalog.text, pg_catalog.regexp_replace($2::pg_catalog.text, '([^a-zA-Z_0-9])', E'\\\\\\1', 'g'), 'i'))[$3];
$$ LANGUAGE SQL IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION translate( citext, citext, text ) RETURNS TEXT AS $$
+CREATE FUNCTION translate( citext, citext, text ) RETURNS TEXT AS $$
SELECT pg_catalog.translate( pg_catalog.translate( $1::pg_catalog.text, pg_catalog.lower($2::pg_catalog.text), $3), pg_catalog.upper($2::pg_catalog.text), $3);
$$ LANGUAGE SQL IMMUTABLE STRICT;
diff --git a/contrib/citext/citext--unpackaged--1.0.sql b/contrib/citext/citext--unpackaged--1.0.sql
new file mode 100644
index 0000000000..a59df36797
--- /dev/null
+++ b/contrib/citext/citext--unpackaged--1.0.sql
@@ -0,0 +1,88 @@
+/* contrib/citext/citext--unpackaged--1.0.sql */
+
+ALTER EXTENSION citext ADD type citext;
+ALTER EXTENSION citext ADD function citextin(cstring);
+ALTER EXTENSION citext ADD function citextout(citext);
+ALTER EXTENSION citext ADD function citextrecv(internal);
+ALTER EXTENSION citext ADD function citextsend(citext);
+ALTER EXTENSION citext ADD function citext(character);
+ALTER EXTENSION citext ADD function citext(boolean);
+ALTER EXTENSION citext ADD function citext(inet);
+ALTER EXTENSION citext ADD cast (citext as text);
+ALTER EXTENSION citext ADD cast (citext as character varying);
+ALTER EXTENSION citext ADD cast (citext as character);
+ALTER EXTENSION citext ADD cast (text as citext);
+ALTER EXTENSION citext ADD cast (character varying as citext);
+ALTER EXTENSION citext ADD cast (character as citext);
+ALTER EXTENSION citext ADD cast (boolean as citext);
+ALTER EXTENSION citext ADD cast (inet as citext);
+ALTER EXTENSION citext ADD function citext_eq(citext,citext);
+ALTER EXTENSION citext ADD function citext_ne(citext,citext);
+ALTER EXTENSION citext ADD function citext_lt(citext,citext);
+ALTER EXTENSION citext ADD function citext_le(citext,citext);
+ALTER EXTENSION citext ADD function citext_gt(citext,citext);
+ALTER EXTENSION citext ADD function citext_ge(citext,citext);
+ALTER EXTENSION citext ADD operator <>(citext,citext);
+ALTER EXTENSION citext ADD operator =(citext,citext);
+ALTER EXTENSION citext ADD operator >(citext,citext);
+ALTER EXTENSION citext ADD operator >=(citext,citext);
+ALTER EXTENSION citext ADD operator <(citext,citext);
+ALTER EXTENSION citext ADD operator <=(citext,citext);
+ALTER EXTENSION citext ADD function citext_cmp(citext,citext);
+ALTER EXTENSION citext ADD function citext_hash(citext);
+ALTER EXTENSION citext ADD operator family citext_ops using btree;
+ALTER EXTENSION citext ADD operator class citext_ops using btree;
+ALTER EXTENSION citext ADD operator family citext_ops using hash;
+ALTER EXTENSION citext ADD operator class citext_ops using hash;
+ALTER EXTENSION citext ADD function citext_smaller(citext,citext);
+ALTER EXTENSION citext ADD function citext_larger(citext,citext);
+ALTER EXTENSION citext ADD function min(citext);
+ALTER EXTENSION citext ADD function max(citext);
+ALTER EXTENSION citext ADD function texticlike(citext,citext);
+ALTER EXTENSION citext ADD function texticnlike(citext,citext);
+ALTER EXTENSION citext ADD function texticregexeq(citext,citext);
+ALTER EXTENSION citext ADD function texticregexne(citext,citext);
+ALTER EXTENSION citext ADD operator !~(citext,citext);
+ALTER EXTENSION citext ADD operator ~(citext,citext);
+ALTER EXTENSION citext ADD operator !~*(citext,citext);
+ALTER EXTENSION citext ADD operator ~*(citext,citext);
+ALTER EXTENSION citext ADD operator !~~(citext,citext);
+ALTER EXTENSION citext ADD operator ~~(citext,citext);
+ALTER EXTENSION citext ADD operator !~~*(citext,citext);
+ALTER EXTENSION citext ADD operator ~~*(citext,citext);
+ALTER EXTENSION citext ADD function texticlike(citext,text);
+ALTER EXTENSION citext ADD function texticnlike(citext,text);
+ALTER EXTENSION citext ADD function texticregexeq(citext,text);
+ALTER EXTENSION citext ADD function texticregexne(citext,text);
+ALTER EXTENSION citext ADD operator !~(citext,text);
+ALTER EXTENSION citext ADD operator ~(citext,text);
+ALTER EXTENSION citext ADD operator !~*(citext,text);
+ALTER EXTENSION citext ADD operator ~*(citext,text);
+ALTER EXTENSION citext ADD operator !~~(citext,text);
+ALTER EXTENSION citext ADD operator ~~(citext,text);
+ALTER EXTENSION citext ADD operator !~~*(citext,text);
+ALTER EXTENSION citext ADD operator ~~*(citext,text);
+ALTER EXTENSION citext ADD function regexp_matches(citext,citext);
+ALTER EXTENSION citext ADD function regexp_matches(citext,citext,text);
+ALTER EXTENSION citext ADD function regexp_replace(citext,citext,text);
+ALTER EXTENSION citext ADD function regexp_replace(citext,citext,text,text);
+ALTER EXTENSION citext ADD function regexp_split_to_array(citext,citext);
+ALTER EXTENSION citext ADD function regexp_split_to_array(citext,citext,text);
+ALTER EXTENSION citext ADD function regexp_split_to_table(citext,citext);
+ALTER EXTENSION citext ADD function regexp_split_to_table(citext,citext,text);
+ALTER EXTENSION citext ADD function strpos(citext,citext);
+ALTER EXTENSION citext ADD function replace(citext,citext,citext);
+ALTER EXTENSION citext ADD function split_part(citext,citext,integer);
+ALTER EXTENSION citext ADD function translate(citext,citext,text);
+
+--
+-- As of 9.1, type citext should be marked collatable. There is no ALTER TYPE
+-- command for this, so we have to do it by poking the pg_type entry directly.
+-- Notes: 100 is the OID of the "pg_catalog.default" collation --- it seems
+-- easier and more reliable to hard-wire that here than to pull it out of
+-- pg_collation. Also, we don't need a pg_depend entry since the default
+-- collation is pinned.
+--
+
+UPDATE pg_catalog.pg_type SET typcollation = 100
+WHERE oid = 'citext'::pg_catalog.regtype;
diff --git a/contrib/citext/citext.c b/contrib/citext/citext.c
index 371e70f74d..31b952b3f7 100644
--- a/contrib/citext/citext.c
+++ b/contrib/citext/citext.c
@@ -1,9 +1,10 @@
/*
- * $PostgreSQL: pgsql/contrib/citext/citext.c,v 1.2 2009/06/11 14:48:50 momjian Exp $
+ * contrib/citext/citext.c
*/
#include "postgres.h"
#include "access/hash.h"
+#include "catalog/pg_collation.h"
#include "fmgr.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
@@ -18,7 +19,7 @@ PG_MODULE_MAGIC;
* ====================
*/
-static int32 citextcmp(text *left, text *right);
+static int32 citextcmp(text *left, text *right, Oid collid);
extern Datum citext_cmp(PG_FUNCTION_ARGS);
extern Datum citext_hash(PG_FUNCTION_ARGS);
extern Datum citext_eq(PG_FUNCTION_ARGS);
@@ -42,17 +43,26 @@ extern Datum citext_larger(PG_FUNCTION_ARGS);
* Returns int32 negative, zero, or positive.
*/
static int32
-citextcmp(text *left, text *right)
+citextcmp(text *left, text *right, Oid collid)
{
char *lcstr,
*rcstr;
int32 result;
- lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
- rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
+ /*
+ * We must do our str_tolower calls with DEFAULT_COLLATION_OID, not the
+ * input collation as you might expect. This is so that the behavior of
+ * citext's equality and hashing functions is not collation-dependent. We
+ * should change this once the core infrastructure is able to cope with
+ * collation-dependent equality and hashing functions.
+ */
+
+ lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
+ rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
result = varstr_cmp(lcstr, strlen(lcstr),
- rcstr, strlen(rcstr));
+ rcstr, strlen(rcstr),
+ collid);
pfree(lcstr);
pfree(rcstr);
@@ -75,7 +85,7 @@ citext_cmp(PG_FUNCTION_ARGS)
text *right = PG_GETARG_TEXT_PP(1);
int32 result;
- result = citextcmp(left, right);
+ result = citextcmp(left, right, PG_GET_COLLATION());
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
@@ -92,7 +102,7 @@ citext_hash(PG_FUNCTION_ARGS)
char *str;
Datum result;
- str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt));
+ str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID);
result = hash_any((unsigned char *) str, strlen(str));
pfree(str);
@@ -121,8 +131,8 @@ citext_eq(PG_FUNCTION_ARGS)
/* We can't compare lengths in advance of downcasing ... */
- lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
- rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
+ lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
+ rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
/*
* Since we only care about equality or not-equality, we can avoid all the
@@ -151,8 +161,8 @@ citext_ne(PG_FUNCTION_ARGS)
/* We can't compare lengths in advance of downcasing ... */
- lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
- rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
+ lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
+ rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
/*
* Since we only care about equality or not-equality, we can avoid all the
@@ -177,7 +187,7 @@ citext_lt(PG_FUNCTION_ARGS)
text *right = PG_GETARG_TEXT_PP(1);
bool result;
- result = citextcmp(left, right) < 0;
+ result = citextcmp(left, right, PG_GET_COLLATION()) < 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
@@ -194,7 +204,7 @@ citext_le(PG_FUNCTION_ARGS)
text *right = PG_GETARG_TEXT_PP(1);
bool result;
- result = citextcmp(left, right) <= 0;
+ result = citextcmp(left, right, PG_GET_COLLATION()) <= 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
@@ -211,7 +221,7 @@ citext_gt(PG_FUNCTION_ARGS)
text *right = PG_GETARG_TEXT_PP(1);
bool result;
- result = citextcmp(left, right) > 0;
+ result = citextcmp(left, right, PG_GET_COLLATION()) > 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
@@ -228,7 +238,7 @@ citext_ge(PG_FUNCTION_ARGS)
text *right = PG_GETARG_TEXT_PP(1);
bool result;
- result = citextcmp(left, right) >= 0;
+ result = citextcmp(left, right, PG_GET_COLLATION()) >= 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
@@ -251,7 +261,7 @@ citext_smaller(PG_FUNCTION_ARGS)
text *right = PG_GETARG_TEXT_PP(1);
text *result;
- result = citextcmp(left, right) < 0 ? left : right;
+ result = citextcmp(left, right, PG_GET_COLLATION()) < 0 ? left : right;
PG_RETURN_TEXT_P(result);
}
@@ -264,6 +274,6 @@ citext_larger(PG_FUNCTION_ARGS)
text *right = PG_GETARG_TEXT_PP(1);
text *result;
- result = citextcmp(left, right) > 0 ? left : right;
+ result = citextcmp(left, right, PG_GET_COLLATION()) > 0 ? left : right;
PG_RETURN_TEXT_P(result);
}
diff --git a/contrib/citext/citext.control b/contrib/citext/citext.control
new file mode 100644
index 0000000000..3eb01a3360
--- /dev/null
+++ b/contrib/citext/citext.control
@@ -0,0 +1,5 @@
+# citext extension
+comment = 'data type for case-insensitive character strings'
+default_version = '1.0'
+module_pathname = '$libdir/citext'
+relocatable = true
diff --git a/contrib/citext/expected/citext.out b/contrib/citext/expected/citext.out
index 21e73be2d7..5392a7d1f3 100644
--- a/contrib/citext/expected/citext.out
+++ b/contrib/citext/expected/citext.out
@@ -1,12 +1,7 @@
--
-- Test citext datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of citext.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
+CREATE EXTENSION citext;
-- Test the operators and indexing functions
-- Test = and <>.
SELECT 'a'::citext = 'a'::citext AS t;
@@ -1046,7 +1041,7 @@ CREATE TABLE caster (
bpchar bpchar,
char char,
chr "char",
- name name,
+ name name,
bytea bytea,
boolean boolean,
float4 float4,
@@ -1055,7 +1050,7 @@ CREATE TABLE caster (
int8 int8,
int4 int4,
int2 int2,
- cidr cidr,
+ cidr cidr,
inet inet,
macaddr macaddr,
money money,
diff --git a/contrib/citext/expected/citext_1.out b/contrib/citext/expected/citext_1.out
index 5fa537bc19..5316ad0cda 100644
--- a/contrib/citext/expected/citext_1.out
+++ b/contrib/citext/expected/citext_1.out
@@ -1,12 +1,7 @@
--
-- Test citext datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of citext.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
+CREATE EXTENSION citext;
-- Test the operators and indexing functions
-- Test = and <>.
SELECT 'a'::citext = 'a'::citext AS t;
@@ -1046,7 +1041,7 @@ CREATE TABLE caster (
bpchar bpchar,
char char,
chr "char",
- name name,
+ name name,
bytea bytea,
boolean boolean,
float4 float4,
@@ -1055,7 +1050,7 @@ CREATE TABLE caster (
int8 int8,
int4 int4,
int2 int2,
- cidr cidr,
+ cidr cidr,
inet inet,
macaddr macaddr,
money money,
diff --git a/contrib/citext/sql/citext.sql b/contrib/citext/sql/citext.sql
index 9014e5d931..07497401a4 100644
--- a/contrib/citext/sql/citext.sql
+++ b/contrib/citext/sql/citext.sql
@@ -2,15 +2,7 @@
-- Test citext datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of citext.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i citext.sql
-RESET client_min_messages;
-\set ECHO all
+CREATE EXTENSION citext;
-- Test the operators and indexing functions
@@ -302,7 +294,7 @@ CREATE TABLE caster (
bpchar bpchar,
char char,
chr "char",
- name name,
+ name name,
bytea bytea,
boolean boolean,
float4 float4,
@@ -311,7 +303,7 @@ CREATE TABLE caster (
int8 int8,
int4 int4,
int2 int2,
- cidr cidr,
+ cidr cidr,
inet inet,
macaddr macaddr,
money money,
diff --git a/contrib/citext/uninstall_citext.sql b/contrib/citext/uninstall_citext.sql
deleted file mode 100644
index 2d1ecbed09..0000000000
--- a/contrib/citext/uninstall_citext.sql
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/citext/uninstall_citext.sql,v 1.3 2008/09/05 18:25:16 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR CLASS citext_ops USING btree CASCADE;
-DROP OPERATOR CLASS citext_ops USING hash CASCADE;
-
-DROP AGGREGATE min(citext);
-DROP AGGREGATE max(citext);
-
-DROP OPERATOR = (citext, citext);
-DROP OPERATOR <> (citext, citext);
-DROP OPERATOR < (citext, citext);
-DROP OPERATOR <= (citext, citext);
-DROP OPERATOR >= (citext, citext);
-DROP OPERATOR > (citext, citext);
-
-DROP OPERATOR ~ (citext, citext);
-DROP OPERATOR ~* (citext, citext);
-DROP OPERATOR !~ (citext, citext);
-DROP OPERATOR !~* (citext, citext);
-DROP OPERATOR ~~ (citext, citext);
-DROP OPERATOR ~~* (citext, citext);
-DROP OPERATOR !~~ (citext, citext);
-DROP OPERATOR !~~* (citext, citext);
-
-DROP OPERATOR ~ (citext, text);
-DROP OPERATOR ~* (citext, text);
-DROP OPERATOR !~ (citext, text);
-DROP OPERATOR !~* (citext, text);
-DROP OPERATOR ~~ (citext, text);
-DROP OPERATOR ~~* (citext, text);
-DROP OPERATOR !~~ (citext, text);
-DROP OPERATOR !~~* (citext, text);
-
-DROP CAST (citext AS text);
-DROP CAST (citext AS varchar);
-DROP CAST (citext AS bpchar);
-DROP CAST (text AS citext);
-DROP CAST (varchar AS citext);
-DROP CAST (bpchar AS citext);
-DROP CAST (boolean AS citext);
-DROP CAST (inet AS citext);
-
-DROP FUNCTION citext(bpchar);
-DROP FUNCTION citext(boolean);
-DROP FUNCTION citext(inet);
-DROP FUNCTION citext_eq(citext, citext);
-DROP FUNCTION citext_ne(citext, citext);
-DROP FUNCTION citext_lt(citext, citext);
-DROP FUNCTION citext_le(citext, citext);
-DROP FUNCTION citext_gt(citext, citext);
-DROP FUNCTION citext_ge(citext, citext);
-DROP FUNCTION citext_cmp(citext, citext);
-DROP FUNCTION citext_hash(citext);
-DROP FUNCTION citext_smaller(citext, citext);
-DROP FUNCTION citext_larger(citext, citext);
-DROP FUNCTION texticlike(citext, citext);
-DROP FUNCTION texticnlike(citext, citext);
-DROP FUNCTION texticregexeq(citext, citext);
-DROP FUNCTION texticregexne(citext, citext);
-DROP FUNCTION texticlike(citext, text);
-DROP FUNCTION texticnlike(citext, text);
-DROP FUNCTION texticregexeq(citext, text);
-DROP FUNCTION texticregexne(citext, text);
-DROP FUNCTION regexp_matches( citext, citext );
-DROP FUNCTION regexp_matches( citext, citext, text );
-DROP FUNCTION regexp_replace( citext, citext, text );
-DROP FUNCTION regexp_replace( citext, citext, text, text );
-DROP FUNCTION regexp_split_to_array( citext, citext );
-DROP FUNCTION regexp_split_to_array( citext, citext, text );
-DROP FUNCTION regexp_split_to_table( citext, citext );
-DROP FUNCTION regexp_split_to_table( citext, citext, text );
-DROP FUNCTION strpos( citext, citext );
-DROP FUNCTION replace( citext, citext, citext );
-DROP FUNCTION split_part( citext, citext, int );
-DROP FUNCTION translate( citext, citext, text );
-
-DROP TYPE citext CASCADE;
diff --git a/contrib/contrib-global.mk b/contrib/contrib-global.mk
index 13c76b82b6..6ac8e9b13d 100644
--- a/contrib/contrib-global.mk
+++ b/contrib/contrib-global.mk
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/contrib/contrib-global.mk,v 1.10 2005/09/27 17:43:31 tgl Exp $
+# contrib/contrib-global.mk
NO_PGXS = 1
include $(top_srcdir)/src/makefiles/pgxs.mk
diff --git a/contrib/cube/.cvsignore b/contrib/cube/.cvsignore
deleted file mode 100644
index 19ecc85b58..0000000000
--- a/contrib/cube/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-cubeparse.c
-cubescan.c
diff --git a/contrib/cube/.gitignore b/contrib/cube/.gitignore
new file mode 100644
index 0000000000..cb4c989fff
--- /dev/null
+++ b/contrib/cube/.gitignore
@@ -0,0 +1,6 @@
+/cubeparse.c
+/cubescan.c
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/cube/CHANGES b/contrib/cube/CHANGES
index d3eca90f6d..7c5590c16f 100644
--- a/contrib/cube/CHANGES
+++ b/contrib/cube/CHANGES
@@ -6,10 +6,10 @@ Code Cleanup:
Update the calling convention for all external facing functions. By external
facing, I mean all functions that are directly referenced in cube.sql. Prior
-to my update, all functions used the older V0 calling convention. They now
+to my update, all functions used the older V0 calling convention. They now
use V1.
-New Functions:
+New Functions:
cube(float[]), which makes a zero volume cube from a float array
diff --git a/contrib/cube/Makefile b/contrib/cube/Makefile
index 2f3da437e5..19fd7dc658 100644
--- a/contrib/cube/Makefile
+++ b/contrib/cube/Makefile
@@ -1,10 +1,11 @@
-# $PostgreSQL: pgsql/contrib/cube/Makefile,v 1.23 2009/08/28 20:26:18 petere Exp $
+# contrib/cube/Makefile
MODULE_big = cube
OBJS= cube.o cubeparse.o
-DATA_built = cube.sql
-DATA = uninstall_cube.sql
+EXTENSION = cube
+DATA = cube--1.0.sql cube--unpackaged--1.0.sql
+
REGRESS = cube
EXTRA_CLEAN = y.tab.c y.tab.h
diff --git a/contrib/cube/cube.sql.in b/contrib/cube/cube--1.0.sql
index 41f493ed41..ee9febe005 100644
--- a/contrib/cube/cube.sql.in
+++ b/contrib/cube/cube--1.0.sql
@@ -1,25 +1,21 @@
-/* $PostgreSQL: pgsql/contrib/cube/cube.sql.in,v 1.25 2009/06/11 18:30:03 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/cube/cube--1.0.sql */
-- Create the user-defined type for N-dimensional boxes
---
-CREATE OR REPLACE FUNCTION cube_in(cstring)
+CREATE FUNCTION cube_in(cstring)
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube(float8[], float8[]) RETURNS cube
+CREATE FUNCTION cube(float8[], float8[]) RETURNS cube
AS 'MODULE_PATHNAME', 'cube_a_f8_f8'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube(float8[]) RETURNS cube
+CREATE FUNCTION cube(float8[]) RETURNS cube
AS 'MODULE_PATHNAME', 'cube_a_f8'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube_out(cube)
+CREATE FUNCTION cube_out(cube)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -39,70 +35,70 @@ COMMENT ON TYPE cube IS 'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-
-- Comparison methods
-CREATE OR REPLACE FUNCTION cube_eq(cube, cube)
+CREATE FUNCTION cube_eq(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_eq(cube, cube) IS 'same as';
-CREATE OR REPLACE FUNCTION cube_ne(cube, cube)
+CREATE FUNCTION cube_ne(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_ne(cube, cube) IS 'different';
-CREATE OR REPLACE FUNCTION cube_lt(cube, cube)
+CREATE FUNCTION cube_lt(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_lt(cube, cube) IS 'lower than';
-CREATE OR REPLACE FUNCTION cube_gt(cube, cube)
+CREATE FUNCTION cube_gt(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_gt(cube, cube) IS 'greater than';
-CREATE OR REPLACE FUNCTION cube_le(cube, cube)
+CREATE FUNCTION cube_le(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_le(cube, cube) IS 'lower than or equal to';
-CREATE OR REPLACE FUNCTION cube_ge(cube, cube)
+CREATE FUNCTION cube_ge(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_ge(cube, cube) IS 'greater than or equal to';
-CREATE OR REPLACE FUNCTION cube_cmp(cube, cube)
+CREATE FUNCTION cube_cmp(cube, cube)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_cmp(cube, cube) IS 'btree comparison function';
-CREATE OR REPLACE FUNCTION cube_contains(cube, cube)
+CREATE FUNCTION cube_contains(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_contains(cube, cube) IS 'contains';
-CREATE OR REPLACE FUNCTION cube_contained(cube, cube)
+CREATE FUNCTION cube_contained(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube_contained(cube, cube) IS 'contained in';
-CREATE OR REPLACE FUNCTION cube_overlap(cube, cube)
+CREATE FUNCTION cube_overlap(cube, cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -111,17 +107,17 @@ COMMENT ON FUNCTION cube_overlap(cube, cube) IS 'overlaps';
-- support routines for indexing
-CREATE OR REPLACE FUNCTION cube_union(cube, cube)
+CREATE FUNCTION cube_union(cube, cube)
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube_inter(cube, cube)
+CREATE FUNCTION cube_inter(cube, cube)
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube_size(cube)
+CREATE FUNCTION cube_size(cube)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -129,61 +125,61 @@ LANGUAGE C IMMUTABLE STRICT;
-- Misc N-dimensional functions
-CREATE OR REPLACE FUNCTION cube_subset(cube, int4[])
+CREATE FUNCTION cube_subset(cube, int4[])
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- proximity routines
-CREATE OR REPLACE FUNCTION cube_distance(cube, cube)
+CREATE FUNCTION cube_distance(cube, cube)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Extracting elements functions
-CREATE OR REPLACE FUNCTION cube_dim(cube)
+CREATE FUNCTION cube_dim(cube)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube_ll_coord(cube, int4)
+CREATE FUNCTION cube_ll_coord(cube, int4)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube_ur_coord(cube, int4)
+CREATE FUNCTION cube_ur_coord(cube, int4)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube(float8) RETURNS cube
+CREATE FUNCTION cube(float8) RETURNS cube
AS 'MODULE_PATHNAME', 'cube_f8'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube(float8, float8) RETURNS cube
+CREATE FUNCTION cube(float8, float8) RETURNS cube
AS 'MODULE_PATHNAME', 'cube_f8_f8'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube(cube, float8) RETURNS cube
+CREATE FUNCTION cube(cube, float8) RETURNS cube
AS 'MODULE_PATHNAME', 'cube_c_f8'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION cube(cube, float8, float8) RETURNS cube
+CREATE FUNCTION cube(cube, float8, float8) RETURNS cube
AS 'MODULE_PATHNAME', 'cube_c_f8_f8'
LANGUAGE C IMMUTABLE STRICT;
-- Test if cube is also a point
-CREATE OR REPLACE FUNCTION cube_is_point(cube)
+CREATE FUNCTION cube_is_point(cube)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Increasing the size of a cube by a radius in at least n dimensions
-CREATE OR REPLACE FUNCTION cube_enlarge(cube, float8, int4)
+CREATE FUNCTION cube_enlarge(cube, float8, int4)
RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -262,38 +258,38 @@ CREATE OPERATOR ~ (
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION g_cube_consistent(internal,cube,int,oid,internal)
+CREATE FUNCTION g_cube_consistent(internal,cube,int,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_cube_compress(internal)
-RETURNS internal
+CREATE FUNCTION g_cube_compress(internal)
+RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_cube_decompress(internal)
-RETURNS internal
+CREATE FUNCTION g_cube_decompress(internal)
+RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_cube_penalty(internal,internal,internal)
+CREATE FUNCTION g_cube_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_cube_picksplit(internal, internal)
+CREATE FUNCTION g_cube_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_cube_union(internal, internal)
-RETURNS cube
+CREATE FUNCTION g_cube_union(internal, internal)
+RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_cube_same(cube, cube, internal)
-RETURNS internal
+CREATE FUNCTION g_cube_same(cube, cube, internal)
+RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
diff --git a/contrib/cube/cube--unpackaged--1.0.sql b/contrib/cube/cube--unpackaged--1.0.sql
new file mode 100644
index 0000000000..866c18a289
--- /dev/null
+++ b/contrib/cube/cube--unpackaged--1.0.sql
@@ -0,0 +1,53 @@
+/* contrib/cube/cube--unpackaged--1.0.sql */
+
+ALTER EXTENSION cube ADD type cube;
+ALTER EXTENSION cube ADD function cube_in(cstring);
+ALTER EXTENSION cube ADD function cube(double precision[],double precision[]);
+ALTER EXTENSION cube ADD function cube(double precision[]);
+ALTER EXTENSION cube ADD function cube_out(cube);
+ALTER EXTENSION cube ADD function cube_eq(cube,cube);
+ALTER EXTENSION cube ADD function cube_ne(cube,cube);
+ALTER EXTENSION cube ADD function cube_lt(cube,cube);
+ALTER EXTENSION cube ADD function cube_gt(cube,cube);
+ALTER EXTENSION cube ADD function cube_le(cube,cube);
+ALTER EXTENSION cube ADD function cube_ge(cube,cube);
+ALTER EXTENSION cube ADD function cube_cmp(cube,cube);
+ALTER EXTENSION cube ADD function cube_contains(cube,cube);
+ALTER EXTENSION cube ADD function cube_contained(cube,cube);
+ALTER EXTENSION cube ADD function cube_overlap(cube,cube);
+ALTER EXTENSION cube ADD function cube_union(cube,cube);
+ALTER EXTENSION cube ADD function cube_inter(cube,cube);
+ALTER EXTENSION cube ADD function cube_size(cube);
+ALTER EXTENSION cube ADD function cube_subset(cube,integer[]);
+ALTER EXTENSION cube ADD function cube_distance(cube,cube);
+ALTER EXTENSION cube ADD function cube_dim(cube);
+ALTER EXTENSION cube ADD function cube_ll_coord(cube,integer);
+ALTER EXTENSION cube ADD function cube_ur_coord(cube,integer);
+ALTER EXTENSION cube ADD function cube(double precision);
+ALTER EXTENSION cube ADD function cube(double precision,double precision);
+ALTER EXTENSION cube ADD function cube(cube,double precision);
+ALTER EXTENSION cube ADD function cube(cube,double precision,double precision);
+ALTER EXTENSION cube ADD function cube_is_point(cube);
+ALTER EXTENSION cube ADD function cube_enlarge(cube,double precision,integer);
+ALTER EXTENSION cube ADD operator >(cube,cube);
+ALTER EXTENSION cube ADD operator >=(cube,cube);
+ALTER EXTENSION cube ADD operator <(cube,cube);
+ALTER EXTENSION cube ADD operator <=(cube,cube);
+ALTER EXTENSION cube ADD operator &&(cube,cube);
+ALTER EXTENSION cube ADD operator <>(cube,cube);
+ALTER EXTENSION cube ADD operator =(cube,cube);
+ALTER EXTENSION cube ADD operator <@(cube,cube);
+ALTER EXTENSION cube ADD operator @>(cube,cube);
+ALTER EXTENSION cube ADD operator ~(cube,cube);
+ALTER EXTENSION cube ADD operator @(cube,cube);
+ALTER EXTENSION cube ADD function g_cube_consistent(internal,cube,integer,oid,internal);
+ALTER EXTENSION cube ADD function g_cube_compress(internal);
+ALTER EXTENSION cube ADD function g_cube_decompress(internal);
+ALTER EXTENSION cube ADD function g_cube_penalty(internal,internal,internal);
+ALTER EXTENSION cube ADD function g_cube_picksplit(internal,internal);
+ALTER EXTENSION cube ADD function g_cube_union(internal,internal);
+ALTER EXTENSION cube ADD function g_cube_same(cube,cube,internal);
+ALTER EXTENSION cube ADD operator family cube_ops using btree;
+ALTER EXTENSION cube ADD operator class cube_ops using btree;
+ALTER EXTENSION cube ADD operator family gist_cube_ops using gist;
+ALTER EXTENSION cube ADD operator class gist_cube_ops using gist;
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index 62cd3a2d02..4a207ccb98 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -1,5 +1,5 @@
/******************************************************************************
- $PostgreSQL: pgsql/contrib/cube/cube.c,v 1.37 2009/06/11 14:48:50 momjian Exp $
+ contrib/cube/cube.c
This file contains routines that can be bound to a Postgres backend and
called by the backend in the process of processing queries. The calling
@@ -187,7 +187,7 @@ cube_a_f8_f8(PG_FUNCTION_ARGS)
double *dur,
*dll;
- if (ARR_HASNULL(ur) || ARR_HASNULL(ll))
+ if (array_contains_nulls(ur) || array_contains_nulls(ll))
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
errmsg("cannot work with arrays containing NULLs")));
@@ -228,7 +228,7 @@ cube_a_f8(PG_FUNCTION_ARGS)
int size;
double *dur;
- if (ARR_HASNULL(ur))
+ if (array_contains_nulls(ur))
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
errmsg("cannot work with arrays containing NULLs")));
@@ -262,7 +262,7 @@ cube_subset(PG_FUNCTION_ARGS)
i;
int *dx;
- if (ARR_HASNULL(idx))
+ if (array_contains_nulls(idx))
ereport(ERROR,
(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
errmsg("cannot work with arrays containing NULLs")));
@@ -615,7 +615,7 @@ g_cube_picksplit(PG_FUNCTION_ARGS)
else
{
datum_r = union_dr;
- size_r = size_alpha;
+ size_r = size_beta;
*right++ = i;
v->spl_nright++;
}
diff --git a/contrib/cube/cube.control b/contrib/cube/cube.control
new file mode 100644
index 0000000000..ddc8d2e5d1
--- /dev/null
+++ b/contrib/cube/cube.control
@@ -0,0 +1,5 @@
+# cube extension
+comment = 'data type for multidimensional cubes'
+default_version = '1.0'
+module_pathname = '$libdir/cube'
+relocatable = true
diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h
index 1100602cfc..fd0c26a381 100644
--- a/contrib/cube/cubedata.h
+++ b/contrib/cube/cubedata.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/cube/cubedata.h,v 1.10 2009/06/11 14:48:50 momjian Exp $ */
+/* contrib/cube/cubedata.h */
#define CUBE_MAX_DIM (100)
diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y
index 13dc4f55b0..9e7c87e903 100644
--- a/contrib/cube/cubeparse.y
+++ b/contrib/cube/cubeparse.y
@@ -2,7 +2,7 @@
/* NdBox = [(lowerleft),(upperright)] */
/* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
-/* $PostgreSQL: pgsql/contrib/cube/cubeparse.y,v 1.19 2008/11/26 08:45:11 petere Exp $ */
+/* contrib/cube/cubeparse.y */
#define YYPARSE_PARAM result /* need this to pass a pointer (void *) to yyparse */
#define YYSTYPE char *
@@ -51,7 +51,7 @@ box:
O_BRACKET paren_list COMMA paren_list C_BRACKET {
int dim;
-
+
dim = delim_count($2, ',') + 1;
if ( (delim_count($4, ',') + 1) != dim ) {
ereport(ERROR,
@@ -69,16 +69,16 @@ box:
CUBE_MAX_DIM)));
YYABORT;
}
-
+
*((void **)result) = write_box( dim, $2, $4 );
-
+
}
|
paren_list COMMA paren_list {
int dim;
dim = delim_count($1, ',') + 1;
-
+
if ( (delim_count($3, ',') + 1) != dim ) {
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -95,7 +95,7 @@ box:
CUBE_MAX_DIM)));
YYABORT;
}
-
+
*((void **)result) = write_box( dim, $1, $3 );
}
|
@@ -146,7 +146,7 @@ list:
$$ = palloc(scanbuflen + 1);
strcpy($$, $1);
}
- |
+ |
list COMMA CUBEFLOAT {
$$ = $1;
strcat($$, ",");
@@ -169,31 +169,31 @@ delim_count(char *s, char delim)
return (ndelim);
}
-static NDBOX *
+static NDBOX *
write_box(unsigned int dim, char *str1, char *str2)
{
NDBOX * bp;
char * s;
- int i;
+ int i;
int size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
-
+
bp = palloc0(size);
SET_VARSIZE(bp, size);
bp->dim = dim;
-
+
s = str1;
bp->x[i=0] = strtod(s, NULL);
while ((s = strchr(s, ',')) != NULL) {
s++; i++;
bp->x[i] = strtod(s, NULL);
- }
-
+ }
+
s = str2;
bp->x[i=dim] = strtod(s, NULL);
while ((s = strchr(s, ',')) != NULL) {
s++; i++;
bp->x[i] = strtod(s, NULL);
- }
+ }
return(bp);
}
@@ -206,13 +206,13 @@ write_point_as_box(char *str, int dim)
int i, size;
double x;
char * s = str;
-
+
size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
bp = palloc0(size);
SET_VARSIZE(bp, size);
bp->dim = dim;
-
+
i = 0;
x = strtod(s, NULL);
bp->x[0] = x;
@@ -222,7 +222,7 @@ write_point_as_box(char *str, int dim)
x = strtod(s, NULL);
bp->x[i] = x;
bp->x[i+dim] = x;
- }
+ }
return(bp);
}
diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index f373d353f2..eb71b11adf 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -1,8 +1,8 @@
%{
-/*
-** A scanner for EMP-style numeric ranges
- * $PostgreSQL: pgsql/contrib/cube/cubescan.l,v 1.12 2008/08/25 23:12:45 tgl Exp $
-*/
+/*
+ * A scanner for EMP-style numeric ranges
+ * contrib/cube/cubescan.l
+ */
#include "postgres.h"
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index 101a63b723..05cf3eae3c 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -1,13 +1,7 @@
--
-- Test cube datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of cube.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION cube;
--
-- testing the input and output functions
--
@@ -473,13 +467,13 @@ SELECT cube('{0,1,2}'::float[]);
(0, 1, 2)
(1 row)
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
cube_subset
---------------------------
(5, 3, 1, 1),(8, 7, 6, 6)
(1 row)
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
ERROR: Index out of bounds
--
-- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
@@ -1107,11 +1101,11 @@ SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
(1 row)
-- Load some example data and build the index
---
+--
CREATE TABLE test_cube (c cube);
\copy test_cube from 'data/test_cube.data'
CREATE INDEX test_cube_ix ON test_cube USING gist (c);
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
c
--------------------------
(337, 455),(240, 359)
@@ -1121,8 +1115,8 @@ SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
(2424, 160),(2424, 81)
(5 rows)
--- Test sorting
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
+-- Test sorting
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
c
--------------------------
(337, 455),(240, 359)
diff --git a/contrib/cube/expected/cube_1.out b/contrib/cube/expected/cube_1.out
index 55f6861daf..fefebf5fb9 100644
--- a/contrib/cube/expected/cube_1.out
+++ b/contrib/cube/expected/cube_1.out
@@ -1,13 +1,7 @@
--
-- Test cube datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of cube.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION cube;
--
-- testing the input and output functions
--
@@ -473,13 +467,13 @@ SELECT cube('{0,1,2}'::float[]);
(0, 1, 2)
(1 row)
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
cube_subset
---------------------------
(5, 3, 1, 1),(8, 7, 6, 6)
(1 row)
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
ERROR: Index out of bounds
--
-- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
@@ -1107,11 +1101,11 @@ SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
(1 row)
-- Load some example data and build the index
---
+--
CREATE TABLE test_cube (c cube);
\copy test_cube from 'data/test_cube.data'
CREATE INDEX test_cube_ix ON test_cube USING gist (c);
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
c
--------------------------
(337, 455),(240, 359)
@@ -1121,8 +1115,8 @@ SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
(2424, 160),(2424, 81)
(5 rows)
--- Test sorting
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
+-- Test sorting
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
c
--------------------------
(337, 455),(240, 359)
diff --git a/contrib/cube/expected/cube_2.out b/contrib/cube/expected/cube_2.out
index c449395818..6d15d63570 100644
--- a/contrib/cube/expected/cube_2.out
+++ b/contrib/cube/expected/cube_2.out
@@ -1,13 +1,7 @@
--
-- Test cube datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of cube.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION cube;
--
-- testing the input and output functions
--
@@ -473,13 +467,13 @@ SELECT cube('{0,1,2}'::float[]);
(0, 1, 2)
(1 row)
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
cube_subset
---------------------------
(5, 3, 1, 1),(8, 7, 6, 6)
(1 row)
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
ERROR: Index out of bounds
--
-- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
@@ -1107,11 +1101,11 @@ SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
(1 row)
-- Load some example data and build the index
---
+--
CREATE TABLE test_cube (c cube);
\copy test_cube from 'data/test_cube.data'
CREATE INDEX test_cube_ix ON test_cube USING gist (c);
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
c
--------------------------
(337, 455),(240, 359)
@@ -1121,8 +1115,8 @@ SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
(2424, 160),(2424, 81)
(5 rows)
--- Test sorting
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
+-- Test sorting
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
c
--------------------------
(337, 455),(240, 359)
diff --git a/contrib/cube/expected/cube_3.out b/contrib/cube/expected/cube_3.out
new file mode 100644
index 0000000000..22b4e1f207
--- /dev/null
+++ b/contrib/cube/expected/cube_3.out
@@ -0,0 +1,1128 @@
+--
+-- Test cube datatype
+--
+CREATE EXTENSION cube;
+--
+-- testing the input and output functions
+--
+-- Any number (a one-dimensional point)
+SELECT '1'::cube AS cube;
+ cube
+------
+ (1)
+(1 row)
+
+SELECT '-1'::cube AS cube;
+ cube
+------
+ (-1)
+(1 row)
+
+SELECT '1.'::cube AS cube;
+ cube
+------
+ (1)
+(1 row)
+
+SELECT '-1.'::cube AS cube;
+ cube
+------
+ (-1)
+(1 row)
+
+SELECT '.1'::cube AS cube;
+ cube
+-------
+ (0.1)
+(1 row)
+
+SELECT '-.1'::cube AS cube;
+ cube
+--------
+ (-0.1)
+(1 row)
+
+SELECT '1.0'::cube AS cube;
+ cube
+------
+ (1)
+(1 row)
+
+SELECT '-1.0'::cube AS cube;
+ cube
+------
+ (-1)
+(1 row)
+
+SELECT '1e27'::cube AS cube;
+ cube
+----------
+ (1e+027)
+(1 row)
+
+SELECT '-1e27'::cube AS cube;
+ cube
+-----------
+ (-1e+027)
+(1 row)
+
+SELECT '1.0e27'::cube AS cube;
+ cube
+----------
+ (1e+027)
+(1 row)
+
+SELECT '-1.0e27'::cube AS cube;
+ cube
+-----------
+ (-1e+027)
+(1 row)
+
+SELECT '1e+27'::cube AS cube;
+ cube
+----------
+ (1e+027)
+(1 row)
+
+SELECT '-1e+27'::cube AS cube;
+ cube
+-----------
+ (-1e+027)
+(1 row)
+
+SELECT '1.0e+27'::cube AS cube;
+ cube
+----------
+ (1e+027)
+(1 row)
+
+SELECT '-1.0e+27'::cube AS cube;
+ cube
+-----------
+ (-1e+027)
+(1 row)
+
+SELECT '1e-7'::cube AS cube;
+ cube
+----------
+ (1e-007)
+(1 row)
+
+SELECT '-1e-7'::cube AS cube;
+ cube
+-----------
+ (-1e-007)
+(1 row)
+
+SELECT '1.0e-7'::cube AS cube;
+ cube
+----------
+ (1e-007)
+(1 row)
+
+SELECT '-1.0e-7'::cube AS cube;
+ cube
+-----------
+ (-1e-007)
+(1 row)
+
+SELECT '1e-700'::cube AS cube;
+ cube
+------
+ (0)
+(1 row)
+
+SELECT '-1e-700'::cube AS cube;
+ cube
+------
+ (-0)
+(1 row)
+
+SELECT '1234567890123456'::cube AS cube;
+ cube
+-------------------------
+ (1.23456789012346e+015)
+(1 row)
+
+SELECT '+1234567890123456'::cube AS cube;
+ cube
+-------------------------
+ (1.23456789012346e+015)
+(1 row)
+
+SELECT '-1234567890123456'::cube AS cube;
+ cube
+--------------------------
+ (-1.23456789012346e+015)
+(1 row)
+
+SELECT '.1234567890123456'::cube AS cube;
+ cube
+---------------------
+ (0.123456789012346)
+(1 row)
+
+SELECT '+.1234567890123456'::cube AS cube;
+ cube
+---------------------
+ (0.123456789012346)
+(1 row)
+
+SELECT '-.1234567890123456'::cube AS cube;
+ cube
+----------------------
+ (-0.123456789012346)
+(1 row)
+
+-- simple lists (points)
+SELECT '1,2'::cube AS cube;
+ cube
+--------
+ (1, 2)
+(1 row)
+
+SELECT '(1,2)'::cube AS cube;
+ cube
+--------
+ (1, 2)
+(1 row)
+
+SELECT '1,2,3,4,5'::cube AS cube;
+ cube
+-----------------
+ (1, 2, 3, 4, 5)
+(1 row)
+
+SELECT '(1,2,3,4,5)'::cube AS cube;
+ cube
+-----------------
+ (1, 2, 3, 4, 5)
+(1 row)
+
+-- double lists (cubes)
+SELECT '(0),(0)'::cube AS cube;
+ cube
+------
+ (0)
+(1 row)
+
+SELECT '(0),(1)'::cube AS cube;
+ cube
+---------
+ (0),(1)
+(1 row)
+
+SELECT '[(0),(0)]'::cube AS cube;
+ cube
+------
+ (0)
+(1 row)
+
+SELECT '[(0),(1)]'::cube AS cube;
+ cube
+---------
+ (0),(1)
+(1 row)
+
+SELECT '(0,0,0,0),(0,0,0,0)'::cube AS cube;
+ cube
+--------------
+ (0, 0, 0, 0)
+(1 row)
+
+SELECT '(0,0,0,0),(1,0,0,0)'::cube AS cube;
+ cube
+---------------------------
+ (0, 0, 0, 0),(1, 0, 0, 0)
+(1 row)
+
+SELECT '[(0,0,0,0),(0,0,0,0)]'::cube AS cube;
+ cube
+--------------
+ (0, 0, 0, 0)
+(1 row)
+
+SELECT '[(0,0,0,0),(1,0,0,0)]'::cube AS cube;
+ cube
+---------------------------
+ (0, 0, 0, 0),(1, 0, 0, 0)
+(1 row)
+
+-- invalid input: parse errors
+SELECT ''::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT ''::cube AS cube;
+ ^
+DETAIL: syntax error at end of input
+SELECT 'ABC'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT 'ABC'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "A"
+SELECT '()'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '()'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ")"
+SELECT '[]'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '[]'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "]"
+SELECT '[()]'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '[()]'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ")"
+SELECT '[(1)]'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '[(1)]'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "]"
+SELECT '[(1),]'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '[(1),]'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "]"
+SELECT '[(1),2]'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '[(1),2]'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "2"
+SELECT '[(1),(2),(3)]'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '[(1),(2),(3)]'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ","
+SELECT '1,'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '1,'::cube AS cube;
+ ^
+DETAIL: syntax error at end of input
+SELECT '1,2,'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '1,2,'::cube AS cube;
+ ^
+DETAIL: syntax error at end of input
+SELECT '1,,2'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '1,,2'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ","
+SELECT '(1,)'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '(1,)'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ")"
+SELECT '(1,2,)'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '(1,2,)'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ")"
+SELECT '(1,,2)'::cube AS cube;
+ERROR: bad cube representation
+LINE 1: SELECT '(1,,2)'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ","
+-- invalid input: semantic errors and trailing garbage
+SELECT '[(1),(2)],'::cube AS cube; -- 0
+ERROR: bad cube representation
+LINE 1: SELECT '[(1),(2)],'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ","
+SELECT '[(1,2,3),(2,3)]'::cube AS cube; -- 1
+ERROR: bad cube representation
+LINE 1: SELECT '[(1,2,3),(2,3)]'::cube AS cube;
+ ^
+DETAIL: Different point dimensions in (1,2,3) and (2,3).
+SELECT '[(1,2),(1,2,3)]'::cube AS cube; -- 1
+ERROR: bad cube representation
+LINE 1: SELECT '[(1,2),(1,2,3)]'::cube AS cube;
+ ^
+DETAIL: Different point dimensions in (1,2) and (1,2,3).
+SELECT '(1),(2),'::cube AS cube; -- 2
+ERROR: bad cube representation
+LINE 1: SELECT '(1),(2),'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ","
+SELECT '(1,2,3),(2,3)'::cube AS cube; -- 3
+ERROR: bad cube representation
+LINE 1: SELECT '(1,2,3),(2,3)'::cube AS cube;
+ ^
+DETAIL: Different point dimensions in (1,2,3) and (2,3).
+SELECT '(1,2),(1,2,3)'::cube AS cube; -- 3
+ERROR: bad cube representation
+LINE 1: SELECT '(1,2),(1,2,3)'::cube AS cube;
+ ^
+DETAIL: Different point dimensions in (1,2) and (1,2,3).
+SELECT '(1,2,3)ab'::cube AS cube; -- 4
+ERROR: bad cube representation
+LINE 1: SELECT '(1,2,3)ab'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "a"
+SELECT '(1,2,3)a'::cube AS cube; -- 5
+ERROR: bad cube representation
+LINE 1: SELECT '(1,2,3)a'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "a"
+SELECT '(1,2)('::cube AS cube; -- 5
+ERROR: bad cube representation
+LINE 1: SELECT '(1,2)('::cube AS cube;
+ ^
+DETAIL: syntax error at or near "("
+SELECT '1,2ab'::cube AS cube; -- 6
+ERROR: bad cube representation
+LINE 1: SELECT '1,2ab'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "a"
+SELECT '1 e7'::cube AS cube; -- 6
+ERROR: bad cube representation
+LINE 1: SELECT '1 e7'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "e"
+SELECT '1,2a'::cube AS cube; -- 7
+ERROR: bad cube representation
+LINE 1: SELECT '1,2a'::cube AS cube;
+ ^
+DETAIL: syntax error at or near "a"
+SELECT '1..2'::cube AS cube; -- 7
+ERROR: bad cube representation
+LINE 1: SELECT '1..2'::cube AS cube;
+ ^
+DETAIL: syntax error at or near ".2"
+--
+-- Testing building cubes from float8 values
+--
+SELECT cube(0::float8);
+ cube
+------
+ (0)
+(1 row)
+
+SELECT cube(1::float8);
+ cube
+------
+ (1)
+(1 row)
+
+SELECT cube(1,2);
+ cube
+---------
+ (1),(2)
+(1 row)
+
+SELECT cube(cube(1,2),3);
+ cube
+---------------
+ (1, 3),(2, 3)
+(1 row)
+
+SELECT cube(cube(1,2),3,4);
+ cube
+---------------
+ (1, 3),(2, 4)
+(1 row)
+
+SELECT cube(cube(cube(1,2),3,4),5);
+ cube
+---------------------
+ (1, 3, 5),(2, 4, 5)
+(1 row)
+
+SELECT cube(cube(cube(1,2),3,4),5,6);
+ cube
+---------------------
+ (1, 3, 5),(2, 4, 6)
+(1 row)
+
+--
+-- Test that the text -> cube cast was installed.
+--
+SELECT '(0)'::text::cube;
+ cube
+------
+ (0)
+(1 row)
+
+--
+-- Test the float[] -> cube cast
+--
+SELECT cube('{0,1,2}'::float[], '{3,4,5}'::float[]);
+ cube
+---------------------
+ (0, 1, 2),(3, 4, 5)
+(1 row)
+
+SELECT cube('{0,1,2}'::float[], '{3}'::float[]);
+ERROR: UR and LL arrays must be of same length
+SELECT cube(NULL::float[], '{3}'::float[]);
+ cube
+------
+
+(1 row)
+
+SELECT cube('{0,1,2}'::float[]);
+ cube
+-----------
+ (0, 1, 2)
+(1 row)
+
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
+ cube_subset
+---------------------------
+ (5, 3, 1, 1),(8, 7, 6, 6)
+(1 row)
+
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
+ERROR: Index out of bounds
+--
+-- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
+--
+select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
+ERROR: bad cube representation
+LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...
+ ^
+DETAIL: A cube cannot have more than 100 dimensions.
+select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
+ERROR: bad cube representation
+LINE 1: select '(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...
+ ^
+DETAIL: A cube cannot have more than 100 dimensions.
+--
+-- testing the operators
+--
+-- equality/inequality:
+--
+SELECT '24, 33.20'::cube = '24, 33.20'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '24, 33.20'::cube != '24, 33.20'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '24, 33.20'::cube = '24, 33.21'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '24, 33.20'::cube != '24, 33.21'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube = '(2,0,0,0,0),(3,1,0,0,0)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube = '(2,0,0,0,0),(3,1,0,0,1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+-- "lower than" / "greater than"
+-- (these operators are not useful for anything but ordering)
+--
+SELECT '1'::cube > '2'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '1'::cube < '2'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '1,1'::cube > '1,2'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '1,1'::cube < '1,2'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube > '(2,0,0,0,0),(3,1,0,0,1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube < '(2,0,0,0,0),(3,1,0,0,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube > '(2,0,0,0,1),(3,1,0,0,0)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube < '(2,0,0,0,1),(3,1,0,0,0)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube > '(2,0,0,0,0),(3,1,0,0,0)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(2,0),(3,1)'::cube < '(2,0,0,0,0),(3,1,0,0,0)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0,0,0,0),(3,1,0,0,1)'::cube > '(2,0),(3,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0,0,0,0),(3,1,0,0,1)'::cube < '(2,0),(3,1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(2,0,0,0,1),(3,1,0,0,0)'::cube > '(2,0),(3,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0,0,0,1),(3,1,0,0,0)'::cube < '(2,0),(3,1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(2,0,0,0,0),(3,1,0,0,0)'::cube > '(2,0),(3,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(2,0,0,0,0),(3,1,0,0,0)'::cube < '(2,0),(3,1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+-- "overlap"
+--
+SELECT '1'::cube && '1'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '1'::cube && '2'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '[(-1,-1,-1),(1,1,1)]'::cube && '0'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '[(-1,-1,-1),(1,1,1)]'::cube && '1'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '[(-1,-1,-1),(1,1,1)]'::cube && '1,1,1'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '[(-1,-1,-1),(1,1,1)]'::cube && '[(1,1,1),(2,2,2)]'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '[(-1,-1,-1),(1,1,1)]'::cube && '[(1,1),(2,2)]'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '[(-1,-1,-1),(1,1,1)]'::cube && '[(2,1,1),(2,2,2)]'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+-- "contained in" (the left operand is the cube entirely enclosed by
+-- the right operand):
+--
+SELECT '0'::cube <@ '0'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '0,0,0'::cube <@ '0,0,0'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '0,0'::cube <@ '0,0,1'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '0,0,0'::cube <@ '0,0,1'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '1,0,0'::cube <@ '0,0,1'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(1,0,0),(0,0,1)'::cube <@ '(1,0,0),(0,0,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(1,0,0),(0,0,1)'::cube <@ '(-1,-1,-1),(1,1,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(1,0,0),(0,0,1)'::cube <@ '(-1,-1,-1,-1),(1,1,1,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '0'::cube <@ '(-1),(1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '1'::cube <@ '(-1),(1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '-1'::cube <@ '(-1),(1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1),(1)'::cube <@ '(-1),(1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1),(1)'::cube <@ '(-1,-1),(1,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-2),(1)'::cube <@ '(-1),(1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(-2),(1)'::cube <@ '(-1,-1),(1,1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+-- "contains" (the left operand is the cube that entirely encloses the
+-- right operand)
+--
+SELECT '0'::cube @> '0'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '0,0,0'::cube @> '0,0,0'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '0,0,1'::cube @> '0,0'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '0,0,1'::cube @> '0,0,0'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '0,0,1'::cube @> '1,0,0'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(1,0,0),(0,0,1)'::cube @> '(1,0,0),(0,0,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1,-1,-1),(1,1,1)'::cube @> '(1,0,0),(0,0,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1,-1,-1,-1),(1,1,1,1)'::cube @> '(1,0,0),(0,0,1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1),(1)'::cube @> '0'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1),(1)'::cube @> '1'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1),(1)'::cube @> '-1'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1),(1)'::cube @> '(-1),(1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1,-1),(1,1)'::cube @> '(-1),(1)'::cube AS bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT '(-1),(1)'::cube @> '(-2),(1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT '(-1,-1),(1,1)'::cube @> '(-2),(1)'::cube AS bool;
+ bool
+------
+ f
+(1 row)
+
+-- Test of distance function
+--
+SELECT cube_distance('(0)'::cube,'(2,2,2,2)'::cube);
+ cube_distance
+---------------
+ 4
+(1 row)
+
+SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
+ cube_distance
+---------------
+ 0.5
+(1 row)
+
+-- Test of cube function (text to cube)
+--
+SELECT cube('(1,1.2)'::text);
+ cube
+----------
+ (1, 1.2)
+(1 row)
+
+SELECT cube(NULL);
+ cube
+------
+
+(1 row)
+
+-- Test of cube_dim function (dimensions stored in cube)
+--
+SELECT cube_dim('(0)'::cube);
+ cube_dim
+----------
+ 1
+(1 row)
+
+SELECT cube_dim('(0,0)'::cube);
+ cube_dim
+----------
+ 2
+(1 row)
+
+SELECT cube_dim('(0,0,0)'::cube);
+ cube_dim
+----------
+ 3
+(1 row)
+
+-- Test of cube_ll_coord function (retrieves LL coodinate values)
+--
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 1);
+ cube_ll_coord
+---------------
+ -1
+(1 row)
+
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 2);
+ cube_ll_coord
+---------------
+ -2
+(1 row)
+
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 3);
+ cube_ll_coord
+---------------
+ 0
+(1 row)
+
+-- Test of cube_ur_coord function (retrieves UR coodinate values)
+--
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 1);
+ cube_ur_coord
+---------------
+ 2
+(1 row)
+
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 2);
+ cube_ur_coord
+---------------
+ 1
+(1 row)
+
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 3);
+ cube_ur_coord
+---------------
+ 0
+(1 row)
+
+-- Test of cube_is_point
+--
+SELECT cube_is_point('(0)'::cube);
+ cube_is_point
+---------------
+ t
+(1 row)
+
+SELECT cube_is_point('(0,1,2)'::cube);
+ cube_is_point
+---------------
+ t
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(0,1,2)'::cube);
+ cube_is_point
+---------------
+ t
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(-1,1,2)'::cube);
+ cube_is_point
+---------------
+ f
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(0,-1,2)'::cube);
+ cube_is_point
+---------------
+ f
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(0,1,-2)'::cube);
+ cube_is_point
+---------------
+ f
+(1 row)
+
+-- Test of cube_enlarge (enlarging and shrinking cubes)
+--
+SELECT cube_enlarge('(0)'::cube, 0, 0);
+ cube_enlarge
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 0, 1);
+ cube_enlarge
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 0, 2);
+ cube_enlarge
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(2),(-2)'::cube, 0, 4);
+ cube_enlarge
+--------------
+ (-2),(2)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 1, 0);
+ cube_enlarge
+--------------
+ (-1),(1)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 1, 1);
+ cube_enlarge
+--------------
+ (-1),(1)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 1, 2);
+ cube_enlarge
+-----------------
+ (-1, -1),(1, 1)
+(1 row)
+
+SELECT cube_enlarge('(2),(-2)'::cube, 1, 4);
+ cube_enlarge
+-------------------------------
+ (-3, -1, -1, -1),(3, 1, 1, 1)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, -1, 0);
+ cube_enlarge
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, -1, 1);
+ cube_enlarge
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, -1, 2);
+ cube_enlarge
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(2),(-2)'::cube, -1, 4);
+ cube_enlarge
+--------------
+ (-1),(1)
+(1 row)
+
+SELECT cube_enlarge('(0,0,0)'::cube, 1, 0);
+ cube_enlarge
+------------------------
+ (-1, -1, -1),(1, 1, 1)
+(1 row)
+
+SELECT cube_enlarge('(0,0,0)'::cube, 1, 2);
+ cube_enlarge
+------------------------
+ (-1, -1, -1),(1, 1, 1)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, 1, 2);
+ cube_enlarge
+-----------------
+ (-4, -3),(3, 8)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, 3, 2);
+ cube_enlarge
+------------------
+ (-6, -5),(5, 10)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -1, 2);
+ cube_enlarge
+-----------------
+ (-2, -1),(1, 6)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
+ cube_enlarge
+---------------------
+ (-0.5, 1),(-0.5, 4)
+(1 row)
+
+-- Load some example data and build the index
+--
+CREATE TABLE test_cube (c cube);
+\copy test_cube from 'data/test_cube.data'
+CREATE INDEX test_cube_ix ON test_cube USING gist (c);
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
+ c
+--------------------------
+ (337, 455),(240, 359)
+ (759, 187),(662, 163)
+ (1444, 403),(1346, 344)
+ (1594, 1043),(1517, 971)
+ (2424, 160),(2424, 81)
+(5 rows)
+
+-- Test sorting
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
+ c
+--------------------------
+ (337, 455),(240, 359)
+ (759, 187),(662, 163)
+ (1444, 403),(1346, 344)
+ (1594, 1043),(1517, 971)
+ (2424, 160),(2424, 81)
+(5 rows)
+
diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql
index 1931dfbc80..02e068edf4 100644
--- a/contrib/cube/sql/cube.sql
+++ b/contrib/cube/sql/cube.sql
@@ -2,15 +2,7 @@
-- Test cube datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of cube.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i cube.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION cube;
--
-- testing the input and output functions
@@ -119,8 +111,8 @@ SELECT cube('{0,1,2}'::float[], '{3,4,5}'::float[]);
SELECT cube('{0,1,2}'::float[], '{3}'::float[]);
SELECT cube(NULL::float[], '{3}'::float[]);
SELECT cube('{0,1,2}'::float[]);
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
-SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
+SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
--
-- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
@@ -275,13 +267,13 @@ SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -1, 2);
SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
-- Load some example data and build the index
---
+--
CREATE TABLE test_cube (c cube);
\copy test_cube from 'data/test_cube.data'
CREATE INDEX test_cube_ix ON test_cube USING gist (c);
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' ORDER BY c;
--- Test sorting
-SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
+-- Test sorting
+SELECT * FROM test_cube WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
diff --git a/contrib/cube/uninstall_cube.sql b/contrib/cube/uninstall_cube.sql
deleted file mode 100644
index abdb5a2db3..0000000000
--- a/contrib/cube/uninstall_cube.sql
+++ /dev/null
@@ -1,98 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/cube/uninstall_cube.sql,v 1.8 2008/04/14 17:05:32 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR CLASS gist_cube_ops USING gist;
-
-DROP OPERATOR CLASS cube_ops USING btree;
-
-DROP FUNCTION g_cube_same(cube, cube, internal);
-
-DROP FUNCTION g_cube_union(internal, internal);
-
-DROP FUNCTION g_cube_picksplit(internal, internal);
-
-DROP FUNCTION g_cube_penalty(internal,internal,internal);
-
-DROP FUNCTION g_cube_decompress(internal);
-
-DROP FUNCTION g_cube_compress(internal);
-
-DROP FUNCTION g_cube_consistent(internal,cube,int,oid,internal);
-
-DROP OPERATOR ~ (cube, cube);
-
-DROP OPERATOR @ (cube, cube);
-
-DROP OPERATOR <@ (cube, cube);
-
-DROP OPERATOR @> (cube, cube);
-
-DROP OPERATOR <> (cube, cube);
-
-DROP OPERATOR = (cube, cube);
-
-DROP OPERATOR && (cube, cube);
-
-DROP OPERATOR >= (cube, cube);
-
-DROP OPERATOR <= (cube, cube);
-
-DROP OPERATOR > (cube, cube);
-
-DROP OPERATOR < (cube, cube);
-
-DROP FUNCTION cube_enlarge(cube, float8, int4);
-
-DROP FUNCTION cube_is_point(cube);
-
-DROP FUNCTION cube(cube, float8, float8);
-
-DROP FUNCTION cube(cube, float8);
-
-DROP FUNCTION cube(float8, float8);
-
-DROP FUNCTION cube(float8[], float8[]);
-
-DROP FUNCTION cube(float8[]);
-
-DROP FUNCTION cube_subset(cube, int4[]);
-
-DROP FUNCTION cube(float8);
-
-DROP FUNCTION cube_ur_coord(cube, int4);
-
-DROP FUNCTION cube_ll_coord(cube, int4);
-
-DROP FUNCTION cube_dim(cube);
-
-DROP FUNCTION cube_distance(cube, cube);
-
-DROP FUNCTION cube_size(cube);
-
-DROP FUNCTION cube_inter(cube, cube);
-
-DROP FUNCTION cube_union(cube, cube);
-
-DROP FUNCTION cube_overlap(cube, cube);
-
-DROP FUNCTION cube_contained(cube, cube);
-
-DROP FUNCTION cube_contains(cube, cube);
-
-DROP FUNCTION cube_cmp(cube, cube);
-
-DROP FUNCTION cube_ge(cube, cube);
-
-DROP FUNCTION cube_le(cube, cube);
-
-DROP FUNCTION cube_gt(cube, cube);
-
-DROP FUNCTION cube_lt(cube, cube);
-
-DROP FUNCTION cube_ne(cube, cube);
-
-DROP FUNCTION cube_eq(cube, cube);
-
-DROP TYPE cube CASCADE;
diff --git a/contrib/dblink/.gitignore b/contrib/dblink/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/dblink/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/dblink/Makefile b/contrib/dblink/Makefile
index 519c73b68f..ac637480eb 100644
--- a/contrib/dblink/Makefile
+++ b/contrib/dblink/Makefile
@@ -1,14 +1,15 @@
-# $PostgreSQL: pgsql/contrib/dblink/Makefile,v 1.15 2007/11/10 23:59:50 momjian Exp $
+# contrib/dblink/Makefile
MODULE_big = dblink
-PG_CPPFLAGS = -I$(libpq_srcdir)
OBJS = dblink.o
+PG_CPPFLAGS = -I$(libpq_srcdir)
SHLIB_LINK = $(libpq)
+SHLIB_PREREQS = submake-libpq
-DATA_built = dblink.sql
-DATA = uninstall_dblink.sql
-REGRESS = dblink
+EXTENSION = dblink
+DATA = dblink--1.0.sql dblink--unpackaged--1.0.sql
+REGRESS = dblink
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/dblink/dblink.sql.in b/contrib/dblink/dblink--1.0.sql
index ff656736a4..4ac5514461 100644
--- a/contrib/dblink/dblink.sql.in
+++ b/contrib/dblink/dblink--1.0.sql
@@ -1,16 +1,13 @@
-/* $PostgreSQL: pgsql/contrib/dblink/dblink.sql.in,v 1.19 2009/08/05 16:11:07 joe Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/dblink/dblink--1.0.sql */
-- dblink_connect now restricts non-superusers to password
-- authenticated connections
-CREATE OR REPLACE FUNCTION dblink_connect (text)
+CREATE FUNCTION dblink_connect (text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_connect'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_connect (text, text)
+CREATE FUNCTION dblink_connect (text, text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_connect'
LANGUAGE C STRICT;
@@ -18,12 +15,12 @@ LANGUAGE C STRICT;
-- dblink_connect_u allows non-superusers to use
-- non-password authenticated connections, but initially
-- privileges are revoked from public
-CREATE OR REPLACE FUNCTION dblink_connect_u (text)
+CREATE FUNCTION dblink_connect_u (text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_connect'
LANGUAGE C STRICT SECURITY DEFINER;
-CREATE OR REPLACE FUNCTION dblink_connect_u (text, text)
+CREATE FUNCTION dblink_connect_u (text, text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_connect'
LANGUAGE C STRICT SECURITY DEFINER;
@@ -31,193 +28,193 @@ LANGUAGE C STRICT SECURITY DEFINER;
REVOKE ALL ON FUNCTION dblink_connect_u (text) FROM public;
REVOKE ALL ON FUNCTION dblink_connect_u (text, text) FROM public;
-CREATE OR REPLACE FUNCTION dblink_disconnect ()
+CREATE FUNCTION dblink_disconnect ()
RETURNS text
AS 'MODULE_PATHNAME','dblink_disconnect'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_disconnect (text)
+CREATE FUNCTION dblink_disconnect (text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_disconnect'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_open (text, text)
+CREATE FUNCTION dblink_open (text, text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_open'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_open (text, text, boolean)
+CREATE FUNCTION dblink_open (text, text, boolean)
RETURNS text
AS 'MODULE_PATHNAME','dblink_open'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_open (text, text, text)
+CREATE FUNCTION dblink_open (text, text, text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_open'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_open (text, text, text, boolean)
+CREATE FUNCTION dblink_open (text, text, text, boolean)
RETURNS text
AS 'MODULE_PATHNAME','dblink_open'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_fetch (text, int)
+CREATE FUNCTION dblink_fetch (text, int)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_fetch'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_fetch (text, int, boolean)
+CREATE FUNCTION dblink_fetch (text, int, boolean)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_fetch'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_fetch (text, text, int)
+CREATE FUNCTION dblink_fetch (text, text, int)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_fetch'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_fetch (text, text, int, boolean)
+CREATE FUNCTION dblink_fetch (text, text, int, boolean)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_fetch'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_close (text)
+CREATE FUNCTION dblink_close (text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_close'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_close (text, boolean)
+CREATE FUNCTION dblink_close (text, boolean)
RETURNS text
AS 'MODULE_PATHNAME','dblink_close'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_close (text, text)
+CREATE FUNCTION dblink_close (text, text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_close'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_close (text, text, boolean)
+CREATE FUNCTION dblink_close (text, text, boolean)
RETURNS text
AS 'MODULE_PATHNAME','dblink_close'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink (text, text)
+CREATE FUNCTION dblink (text, text)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_record'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink (text, text, boolean)
+CREATE FUNCTION dblink (text, text, boolean)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_record'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink (text)
+CREATE FUNCTION dblink (text)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_record'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink (text, boolean)
+CREATE FUNCTION dblink (text, boolean)
RETURNS setof record
AS 'MODULE_PATHNAME','dblink_record'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_exec (text, text)
+CREATE FUNCTION dblink_exec (text, text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_exec'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_exec (text, text, boolean)
+CREATE FUNCTION dblink_exec (text, text, boolean)
RETURNS text
AS 'MODULE_PATHNAME','dblink_exec'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_exec (text)
+CREATE FUNCTION dblink_exec (text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_exec'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_exec (text,boolean)
+CREATE FUNCTION dblink_exec (text,boolean)
RETURNS text
AS 'MODULE_PATHNAME','dblink_exec'
LANGUAGE C STRICT;
CREATE TYPE dblink_pkey_results AS (position int, colname text);
-CREATE OR REPLACE FUNCTION dblink_get_pkey (text)
+CREATE FUNCTION dblink_get_pkey (text)
RETURNS setof dblink_pkey_results
AS 'MODULE_PATHNAME','dblink_get_pkey'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_build_sql_insert (text, int2vector, int, _text, _text)
+CREATE FUNCTION dblink_build_sql_insert (text, int2vector, int, _text, _text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_build_sql_insert'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_build_sql_delete (text, int2vector, int, _text)
+CREATE FUNCTION dblink_build_sql_delete (text, int2vector, int, _text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_build_sql_delete'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_build_sql_update (text, int2vector, int, _text, _text)
+CREATE FUNCTION dblink_build_sql_update (text, int2vector, int, _text, _text)
RETURNS text
AS 'MODULE_PATHNAME','dblink_build_sql_update'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_current_query ()
+CREATE FUNCTION dblink_current_query ()
RETURNS text
AS 'MODULE_PATHNAME','dblink_current_query'
LANGUAGE C;
-CREATE OR REPLACE FUNCTION dblink_send_query(text, text)
+CREATE FUNCTION dblink_send_query(text, text)
RETURNS int4
AS 'MODULE_PATHNAME', 'dblink_send_query'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_is_busy(text)
+CREATE FUNCTION dblink_is_busy(text)
RETURNS int4
AS 'MODULE_PATHNAME', 'dblink_is_busy'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_get_result(text)
+CREATE FUNCTION dblink_get_result(text)
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'dblink_get_result'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_get_result(text, bool)
+CREATE FUNCTION dblink_get_result(text, bool)
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'dblink_get_result'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_get_connections()
+CREATE FUNCTION dblink_get_connections()
RETURNS text[]
AS 'MODULE_PATHNAME', 'dblink_get_connections'
LANGUAGE C;
-CREATE OR REPLACE FUNCTION dblink_cancel_query(text)
+CREATE FUNCTION dblink_cancel_query(text)
RETURNS text
AS 'MODULE_PATHNAME', 'dblink_cancel_query'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_error_message(text)
+CREATE FUNCTION dblink_error_message(text)
RETURNS text
AS 'MODULE_PATHNAME', 'dblink_error_message'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_get_notify(
+CREATE FUNCTION dblink_get_notify(
OUT notify_name TEXT,
OUT be_pid INT4,
OUT extra TEXT
-)
+)
RETURNS setof record
AS 'MODULE_PATHNAME', 'dblink_get_notify'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dblink_get_notify(
+CREATE FUNCTION dblink_get_notify(
conname TEXT,
OUT notify_name TEXT,
OUT be_pid INT4,
OUT extra TEXT
-)
+)
RETURNS setof record
AS 'MODULE_PATHNAME', 'dblink_get_notify'
LANGUAGE C STRICT;
diff --git a/contrib/dblink/dblink--unpackaged--1.0.sql b/contrib/dblink/dblink--unpackaged--1.0.sql
new file mode 100644
index 0000000000..b6d184b4a2
--- /dev/null
+++ b/contrib/dblink/dblink--unpackaged--1.0.sql
@@ -0,0 +1,43 @@
+/* contrib/dblink/dblink--unpackaged--1.0.sql */
+
+ALTER EXTENSION dblink ADD function dblink_connect(text);
+ALTER EXTENSION dblink ADD function dblink_connect(text,text);
+ALTER EXTENSION dblink ADD function dblink_connect_u(text);
+ALTER EXTENSION dblink ADD function dblink_connect_u(text,text);
+ALTER EXTENSION dblink ADD function dblink_disconnect();
+ALTER EXTENSION dblink ADD function dblink_disconnect(text);
+ALTER EXTENSION dblink ADD function dblink_open(text,text);
+ALTER EXTENSION dblink ADD function dblink_open(text,text,boolean);
+ALTER EXTENSION dblink ADD function dblink_open(text,text,text);
+ALTER EXTENSION dblink ADD function dblink_open(text,text,text,boolean);
+ALTER EXTENSION dblink ADD function dblink_fetch(text,integer);
+ALTER EXTENSION dblink ADD function dblink_fetch(text,integer,boolean);
+ALTER EXTENSION dblink ADD function dblink_fetch(text,text,integer);
+ALTER EXTENSION dblink ADD function dblink_fetch(text,text,integer,boolean);
+ALTER EXTENSION dblink ADD function dblink_close(text);
+ALTER EXTENSION dblink ADD function dblink_close(text,boolean);
+ALTER EXTENSION dblink ADD function dblink_close(text,text);
+ALTER EXTENSION dblink ADD function dblink_close(text,text,boolean);
+ALTER EXTENSION dblink ADD function dblink(text,text);
+ALTER EXTENSION dblink ADD function dblink(text,text,boolean);
+ALTER EXTENSION dblink ADD function dblink(text);
+ALTER EXTENSION dblink ADD function dblink(text,boolean);
+ALTER EXTENSION dblink ADD function dblink_exec(text,text);
+ALTER EXTENSION dblink ADD function dblink_exec(text,text,boolean);
+ALTER EXTENSION dblink ADD function dblink_exec(text);
+ALTER EXTENSION dblink ADD function dblink_exec(text,boolean);
+ALTER EXTENSION dblink ADD type dblink_pkey_results;
+ALTER EXTENSION dblink ADD function dblink_get_pkey(text);
+ALTER EXTENSION dblink ADD function dblink_build_sql_insert(text,int2vector,integer,text[],text[]);
+ALTER EXTENSION dblink ADD function dblink_build_sql_delete(text,int2vector,integer,text[]);
+ALTER EXTENSION dblink ADD function dblink_build_sql_update(text,int2vector,integer,text[],text[]);
+ALTER EXTENSION dblink ADD function dblink_current_query();
+ALTER EXTENSION dblink ADD function dblink_send_query(text,text);
+ALTER EXTENSION dblink ADD function dblink_is_busy(text);
+ALTER EXTENSION dblink ADD function dblink_get_result(text);
+ALTER EXTENSION dblink ADD function dblink_get_result(text,boolean);
+ALTER EXTENSION dblink ADD function dblink_get_connections();
+ALTER EXTENSION dblink ADD function dblink_cancel_query(text);
+ALTER EXTENSION dblink ADD function dblink_error_message(text);
+ALTER EXTENSION dblink ADD function dblink_get_notify();
+ALTER EXTENSION dblink ADD function dblink_get_notify(text);
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 4bfa7670fd..19b98fb73d 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -8,8 +8,8 @@
* Darko Prenosil <Darko.Prenosil@finteh.hr>
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
*
- * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.99 2010/07/06 19:18:54 momjian Exp $
- * Copyright (c) 2001-2010, PostgreSQL Global Development Group
+ * contrib/dblink/dblink.c
+ * Copyright (c) 2001-2011, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
* Permission to use, copy, modify, and distribute this software and its
@@ -91,7 +91,6 @@ static char **get_text_array_contents(ArrayType *array, int *numitems);
static char *get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals);
static char *get_sql_delete(Relation rel, int *pkattnums, int pknumatts, char **tgt_pkattvals);
static char *get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals);
-static char *quote_literal_cstr(char *rawstr);
static char *quote_ident_cstr(char *rawstr);
static int get_attnum_pk_pos(int *pkattnums, int pknumatts, int key);
static HeapTuple get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals);
@@ -1894,25 +1893,6 @@ get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals
}
/*
- * Return a properly quoted literal value.
- * Uses quote_literal in quote.c
- */
-static char *
-quote_literal_cstr(char *rawstr)
-{
- text *rawstr_text;
- text *result_text;
- char *result;
-
- rawstr_text = cstring_to_text(rawstr);
- result_text = DatumGetTextP(DirectFunctionCall1(quote_literal,
- PointerGetDatum(rawstr_text)));
- result = text_to_cstring(result_text);
-
- return result;
-}
-
-/*
* Return a properly quoted identifier.
* Uses quote_ident in quote.c
*/
@@ -2109,7 +2089,7 @@ getConnectionByName(const char *name)
remoteConnHash = createConnHash();
key = pstrdup(name);
- truncate_identifier(key, strlen(key), true);
+ truncate_identifier(key, strlen(key), false);
hentry = (remoteConnHashEnt *) hash_search(remoteConnHash,
key, HASH_FIND, NULL);
@@ -2170,7 +2150,7 @@ deleteConnection(const char *name)
remoteConnHash = createConnHash();
key = pstrdup(name);
- truncate_identifier(key, strlen(key), true);
+ truncate_identifier(key, strlen(key), false);
hentry = (remoteConnHashEnt *) hash_search(remoteConnHash,
key, HASH_REMOVE, &found);
diff --git a/contrib/dblink/dblink.control b/contrib/dblink/dblink.control
new file mode 100644
index 0000000000..4333a9b618
--- /dev/null
+++ b/contrib/dblink/dblink.control
@@ -0,0 +1,5 @@
+# dblink extension
+comment = 'connect to other PostgreSQL databases from within a database'
+default_version = '1.0'
+module_pathname = '$libdir/dblink'
+relocatable = true
diff --git a/contrib/dblink/dblink.h b/contrib/dblink/dblink.h
index 1918fdee44..40de83f2b6 100644
--- a/contrib/dblink/dblink.h
+++ b/contrib/dblink/dblink.h
@@ -8,8 +8,8 @@
* Darko Prenosil <Darko.Prenosil@finteh.hr>
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
*
- * $PostgreSQL: pgsql/contrib/dblink/dblink.h,v 1.24 2010/01/02 16:57:32 momjian Exp $
- * Copyright (c) 2001-2010, PostgreSQL Global Development Group
+ * contrib/dblink/dblink.h
+ * Copyright (c) 2001-2011, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
* Permission to use, copy, modify, and distribute this software and its
diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out
index c59a67c737..511dd5efcf 100644
--- a/contrib/dblink/expected/dblink.out
+++ b/contrib/dblink/expected/dblink.out
@@ -1,14 +1,4 @@
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
---
--- Define the functions and test data
--- therein.
---
--- Turn off echoing so that expected file does not depend on
--- contents of dblink.sql.
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION dblink;
CREATE TABLE foo(f1 int, f2 text, f3 text[], primary key (f1,f2));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
INSERT INTO foo VALUES (0,'a','{"a0","b0","c0"}');
@@ -668,7 +658,7 @@ SELECT dblink_connect('dtest1', 'dbname=contrib_regression');
OK
(1 row)
-SELECT * from
+SELECT * from
dblink_send_query('dtest1', 'select * from foo where f1 < 3') as t1;
t1
----
@@ -681,7 +671,7 @@ SELECT dblink_connect('dtest2', 'dbname=contrib_regression');
OK
(1 row)
-SELECT * from
+SELECT * from
dblink_send_query('dtest2', 'select * from foo where f1 > 2 and f1 < 7') as t1;
t1
----
@@ -694,7 +684,7 @@ SELECT dblink_connect('dtest3', 'dbname=contrib_regression');
OK
(1 row)
-SELECT * from
+SELECT * from
dblink_send_query('dtest3', 'select * from foo where f1 > 6') as t1;
t1
----
@@ -768,7 +758,7 @@ SELECT dblink_connect('dtest1', 'dbname=contrib_regression');
OK
(1 row)
-SELECT * from
+SELECT * from
dblink_send_query('dtest1', 'select * from foo where f1 < 3') as t1;
t1
----
diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql
index a6d7811bfc..8c8ffe233c 100644
--- a/contrib/dblink/sql/dblink.sql
+++ b/contrib/dblink/sql/dblink.sql
@@ -1,17 +1,4 @@
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
---
--- Define the functions and test data
--- therein.
---
--- Turn off echoing so that expected file does not depend on
--- contents of dblink.sql.
-SET client_min_messages = warning;
-\set ECHO none
-\i dblink.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION dblink;
CREATE TABLE foo(f1 int, f2 text, f3 text[], primary key (f1,f2));
INSERT INTO foo VALUES (0,'a','{"a0","b0","c0"}');
@@ -327,15 +314,15 @@ SELECT dblink_disconnect('myconn');
-- test asynchronous queries
SELECT dblink_connect('dtest1', 'dbname=contrib_regression');
-SELECT * from
+SELECT * from
dblink_send_query('dtest1', 'select * from foo where f1 < 3') as t1;
SELECT dblink_connect('dtest2', 'dbname=contrib_regression');
-SELECT * from
+SELECT * from
dblink_send_query('dtest2', 'select * from foo where f1 > 2 and f1 < 7') as t1;
SELECT dblink_connect('dtest3', 'dbname=contrib_regression');
-SELECT * from
+SELECT * from
dblink_send_query('dtest3', 'select * from foo where f1 > 6') as t1;
CREATE TEMPORARY TABLE result AS
@@ -364,7 +351,7 @@ SELECT dblink_disconnect('dtest3');
SELECT * from result;
SELECT dblink_connect('dtest1', 'dbname=contrib_regression');
-SELECT * from
+SELECT * from
dblink_send_query('dtest1', 'select * from foo where f1 < 3') as t1;
SELECT dblink_cancel_query('dtest1');
diff --git a/contrib/dblink/uninstall_dblink.sql b/contrib/dblink/uninstall_dblink.sql
deleted file mode 100644
index 98478115f1..0000000000
--- a/contrib/dblink/uninstall_dblink.sql
+++ /dev/null
@@ -1,86 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/dblink/uninstall_dblink.sql,v 1.9 2010/06/07 15:14:36 teodor Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION dblink_current_query ();
-
-DROP FUNCTION dblink_build_sql_update (text, int2vector, int4, _text, _text);
-
-DROP FUNCTION dblink_build_sql_delete (text, int2vector, int4, _text);
-
-DROP FUNCTION dblink_build_sql_insert (text, int2vector, int4, _text, _text);
-
-DROP FUNCTION dblink_get_pkey (text);
-
-DROP TYPE dblink_pkey_results;
-
-DROP FUNCTION dblink_exec (text,bool);
-
-DROP FUNCTION dblink_exec (text);
-
-DROP FUNCTION dblink_exec (text,text,bool);
-
-DROP FUNCTION dblink_exec (text,text);
-
-DROP FUNCTION dblink (text,bool);
-
-DROP FUNCTION dblink (text);
-
-DROP FUNCTION dblink (text,text,bool);
-
-DROP FUNCTION dblink (text,text);
-
-DROP FUNCTION dblink_close (text,text,bool);
-
-DROP FUNCTION dblink_close (text,text);
-
-DROP FUNCTION dblink_close (text,bool);
-
-DROP FUNCTION dblink_close (text);
-
-DROP FUNCTION dblink_fetch (text,text,int,bool);
-
-DROP FUNCTION dblink_fetch (text,text,int);
-
-DROP FUNCTION dblink_fetch (text,int,bool);
-
-DROP FUNCTION dblink_fetch (text,int);
-
-DROP FUNCTION dblink_open (text,text,text,bool);
-
-DROP FUNCTION dblink_open (text,text,text);
-
-DROP FUNCTION dblink_open (text,text,bool);
-
-DROP FUNCTION dblink_open (text,text);
-
-DROP FUNCTION dblink_disconnect (text);
-
-DROP FUNCTION dblink_disconnect ();
-
-DROP FUNCTION dblink_connect (text, text);
-
-DROP FUNCTION dblink_connect (text);
-
-DROP FUNCTION dblink_connect_u (text, text);
-
-DROP FUNCTION dblink_connect_u (text);
-
-DROP FUNCTION dblink_cancel_query(text);
-
-DROP FUNCTION dblink_error_message(text);
-
-DROP FUNCTION dblink_get_connections();
-
-DROP FUNCTION dblink_get_result(text);
-
-DROP FUNCTION dblink_get_result(text, boolean);
-
-DROP FUNCTION dblink_is_busy(text);
-
-DROP FUNCTION dblink_send_query(text, text);
-
-DROP FUNCTION dblink_get_notify();
-
-DROP FUNCTION dblink_get_notify(text);
diff --git a/contrib/dict_int/.gitignore b/contrib/dict_int/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/dict_int/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/dict_int/Makefile b/contrib/dict_int/Makefile
index adf7b685b5..3a3fc368dc 100644
--- a/contrib/dict_int/Makefile
+++ b/contrib/dict_int/Makefile
@@ -1,9 +1,11 @@
-# $PostgreSQL: pgsql/contrib/dict_int/Makefile,v 1.2 2007/12/02 21:15:38 tgl Exp $
+# contrib/dict_int/Makefile
MODULE_big = dict_int
OBJS = dict_int.o
-DATA_built = dict_int.sql
-DATA = uninstall_dict_int.sql
+
+EXTENSION = dict_int
+DATA = dict_int--1.0.sql dict_int--unpackaged--1.0.sql
+
REGRESS = dict_int
ifdef USE_PGXS
diff --git a/contrib/dict_int/dict_int.sql.in b/contrib/dict_int/dict_int--1.0.sql
index 5245349ae1..585a56552d 100644
--- a/contrib/dict_int/dict_int.sql.in
+++ b/contrib/dict_int/dict_int--1.0.sql
@@ -1,14 +1,11 @@
-/* $PostgreSQL: pgsql/contrib/dict_int/dict_int.sql.in,v 1.3 2007/11/13 04:24:27 momjian Exp $ */
+/* contrib/dict_int/dict_int--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION dintdict_init(internal)
+CREATE FUNCTION dintdict_init(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dintdict_lexize(internal, internal, internal, internal)
+CREATE FUNCTION dintdict_lexize(internal, internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
diff --git a/contrib/dict_int/dict_int--unpackaged--1.0.sql b/contrib/dict_int/dict_int--unpackaged--1.0.sql
new file mode 100644
index 0000000000..f89218a565
--- /dev/null
+++ b/contrib/dict_int/dict_int--unpackaged--1.0.sql
@@ -0,0 +1,6 @@
+/* contrib/dict_int/dict_int--unpackaged--1.0.sql */
+
+ALTER EXTENSION dict_int ADD function dintdict_init(internal);
+ALTER EXTENSION dict_int ADD function dintdict_lexize(internal,internal,internal,internal);
+ALTER EXTENSION dict_int ADD text search template intdict_template;
+ALTER EXTENSION dict_int ADD text search dictionary intdict;
diff --git a/contrib/dict_int/dict_int.c b/contrib/dict_int/dict_int.c
index 8e1918613f..c4ad6ef343 100644
--- a/contrib/dict_int/dict_int.c
+++ b/contrib/dict_int/dict_int.c
@@ -3,10 +3,10 @@
* dict_int.c
* Text search dictionary for integers
*
- * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2007-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/dict_int/dict_int.c,v 1.6 2010/01/02 16:57:32 momjian Exp $
+ * contrib/dict_int/dict_int.c
*
*-------------------------------------------------------------------------
*/
diff --git a/contrib/dict_int/dict_int.control b/contrib/dict_int/dict_int.control
new file mode 100644
index 0000000000..6e2d2b351a
--- /dev/null
+++ b/contrib/dict_int/dict_int.control
@@ -0,0 +1,5 @@
+# dict_int extension
+comment = 'text search dictionary template for integers'
+default_version = '1.0'
+module_pathname = '$libdir/dict_int'
+relocatable = true
diff --git a/contrib/dict_int/expected/dict_int.out b/contrib/dict_int/expected/dict_int.out
index 7feb493e15..3b766ec52a 100644
--- a/contrib/dict_int/expected/dict_int.out
+++ b/contrib/dict_int/expected/dict_int.out
@@ -1,10 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of this file.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION dict_int;
--lexize
select ts_lexize('intdict', '511673');
ts_lexize
diff --git a/contrib/dict_int/sql/dict_int.sql b/contrib/dict_int/sql/dict_int.sql
index 3a335f8f3d..8ffec6b770 100644
--- a/contrib/dict_int/sql/dict_int.sql
+++ b/contrib/dict_int/sql/dict_int.sql
@@ -1,12 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of this file.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i dict_int.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION dict_int;
--lexize
select ts_lexize('intdict', '511673');
diff --git a/contrib/dict_int/uninstall_dict_int.sql b/contrib/dict_int/uninstall_dict_int.sql
deleted file mode 100644
index d94343fd36..0000000000
--- a/contrib/dict_int/uninstall_dict_int.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/dict_int/uninstall_dict_int.sql,v 1.3 2007/11/13 04:24:27 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP TEXT SEARCH DICTIONARY intdict;
-
-DROP TEXT SEARCH TEMPLATE intdict_template;
-
-DROP FUNCTION dintdict_init(internal);
-
-DROP FUNCTION dintdict_lexize(internal,internal,internal,internal);
diff --git a/contrib/dict_xsyn/.gitignore b/contrib/dict_xsyn/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/dict_xsyn/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/dict_xsyn/Makefile b/contrib/dict_xsyn/Makefile
index 2a879b7eff..ce92baa478 100644
--- a/contrib/dict_xsyn/Makefile
+++ b/contrib/dict_xsyn/Makefile
@@ -1,10 +1,12 @@
-# $PostgreSQL: pgsql/contrib/dict_xsyn/Makefile,v 1.3 2007/12/02 21:15:38 tgl Exp $
+# contrib/dict_xsyn/Makefile
MODULE_big = dict_xsyn
OBJS = dict_xsyn.o
-DATA_built = dict_xsyn.sql
-DATA = uninstall_dict_xsyn.sql
+
+EXTENSION = dict_xsyn
+DATA = dict_xsyn--1.0.sql dict_xsyn--unpackaged--1.0.sql
DATA_TSEARCH = xsyn_sample.rules
+
REGRESS = dict_xsyn
ifdef USE_PGXS
diff --git a/contrib/dict_xsyn/dict_xsyn.sql.in b/contrib/dict_xsyn/dict_xsyn--1.0.sql
index ac014a757d..30eaff4db5 100644
--- a/contrib/dict_xsyn/dict_xsyn.sql.in
+++ b/contrib/dict_xsyn/dict_xsyn--1.0.sql
@@ -1,14 +1,11 @@
-/* $PostgreSQL: pgsql/contrib/dict_xsyn/dict_xsyn.sql.in,v 1.3 2007/11/13 04:24:27 momjian Exp $ */
+/* contrib/dict_xsyn/dict_xsyn--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION dxsyn_init(internal)
+CREATE FUNCTION dxsyn_init(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION dxsyn_lexize(internal, internal, internal, internal)
+CREATE FUNCTION dxsyn_lexize(internal, internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
diff --git a/contrib/dict_xsyn/dict_xsyn--unpackaged--1.0.sql b/contrib/dict_xsyn/dict_xsyn--unpackaged--1.0.sql
new file mode 100644
index 0000000000..6fe0285f79
--- /dev/null
+++ b/contrib/dict_xsyn/dict_xsyn--unpackaged--1.0.sql
@@ -0,0 +1,6 @@
+/* contrib/dict_xsyn/dict_xsyn--unpackaged--1.0.sql */
+
+ALTER EXTENSION dict_xsyn ADD function dxsyn_init(internal);
+ALTER EXTENSION dict_xsyn ADD function dxsyn_lexize(internal,internal,internal,internal);
+ALTER EXTENSION dict_xsyn ADD text search template xsyn_template;
+ALTER EXTENSION dict_xsyn ADD text search dictionary xsyn;
diff --git a/contrib/dict_xsyn/dict_xsyn.c b/contrib/dict_xsyn/dict_xsyn.c
index dc16d9583e..ded20facd4 100644
--- a/contrib/dict_xsyn/dict_xsyn.c
+++ b/contrib/dict_xsyn/dict_xsyn.c
@@ -3,10 +3,10 @@
* dict_xsyn.c
* Extended synonym dictionary
*
- * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2007-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/dict_xsyn/dict_xsyn.c,v 1.9 2010/02/26 02:00:32 momjian Exp $
+ * contrib/dict_xsyn/dict_xsyn.c
*
*-------------------------------------------------------------------------
*/
diff --git a/contrib/dict_xsyn/dict_xsyn.control b/contrib/dict_xsyn/dict_xsyn.control
new file mode 100644
index 0000000000..3fd465a955
--- /dev/null
+++ b/contrib/dict_xsyn/dict_xsyn.control
@@ -0,0 +1,5 @@
+# dict_xsyn extension
+comment = 'text search dictionary template for extended synonym processing'
+default_version = '1.0'
+module_pathname = '$libdir/dict_xsyn'
+relocatable = true
diff --git a/contrib/dict_xsyn/expected/dict_xsyn.out b/contrib/dict_xsyn/expected/dict_xsyn.out
index d91697a97e..9b95e13559 100644
--- a/contrib/dict_xsyn/expected/dict_xsyn.out
+++ b/contrib/dict_xsyn/expected/dict_xsyn.out
@@ -1,10 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of this file.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION dict_xsyn;
-- default configuration - match first word and return it among with all synonyms
ALTER TEXT SEARCH DICTIONARY xsyn (RULES='xsyn_sample', KEEPORIG=true, MATCHORIG=true, KEEPSYNONYMS=true, MATCHSYNONYMS=false);
--lexize
diff --git a/contrib/dict_xsyn/sql/dict_xsyn.sql b/contrib/dict_xsyn/sql/dict_xsyn.sql
index 9db0851700..49511061d0 100644
--- a/contrib/dict_xsyn/sql/dict_xsyn.sql
+++ b/contrib/dict_xsyn/sql/dict_xsyn.sql
@@ -1,12 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of this file.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i dict_xsyn.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION dict_xsyn;
-- default configuration - match first word and return it among with all synonyms
ALTER TEXT SEARCH DICTIONARY xsyn (RULES='xsyn_sample', KEEPORIG=true, MATCHORIG=true, KEEPSYNONYMS=true, MATCHSYNONYMS=false);
diff --git a/contrib/dict_xsyn/uninstall_dict_xsyn.sql b/contrib/dict_xsyn/uninstall_dict_xsyn.sql
deleted file mode 100644
index 844d2e9997..0000000000
--- a/contrib/dict_xsyn/uninstall_dict_xsyn.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/dict_xsyn/uninstall_dict_xsyn.sql,v 1.3 2007/11/13 04:24:27 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP TEXT SEARCH DICTIONARY xsyn;
-
-DROP TEXT SEARCH TEMPLATE xsyn_template;
-
-DROP FUNCTION dxsyn_init(internal);
-
-DROP FUNCTION dxsyn_lexize(internal,internal,internal,internal);
diff --git a/contrib/dummy_seclabel/Makefile b/contrib/dummy_seclabel/Makefile
new file mode 100644
index 0000000000..105400f5f9
--- /dev/null
+++ b/contrib/dummy_seclabel/Makefile
@@ -0,0 +1,14 @@
+# contrib/dummy_seclabel/Makefile
+
+MODULES = dummy_seclabel
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/dummy_seclabel
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/dummy_seclabel/dummy_seclabel.c b/contrib/dummy_seclabel/dummy_seclabel.c
new file mode 100644
index 0000000000..5deb43fa9b
--- /dev/null
+++ b/contrib/dummy_seclabel/dummy_seclabel.c
@@ -0,0 +1,49 @@
+/*
+ * dummy_seclabel.c
+ *
+ * Dummy security label provider.
+ *
+ * This module does not provide anything worthwhile from a security
+ * perspective, but allows regression testing independent of platform-specific
+ * features like SELinux.
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ */
+#include "postgres.h"
+
+#include "commands/seclabel.h"
+#include "miscadmin.h"
+
+PG_MODULE_MAGIC;
+
+/* Entrypoint of the module */
+void _PG_init(void);
+
+static void
+dummy_object_relabel(const ObjectAddress *object, const char *seclabel)
+{
+ if (seclabel == NULL ||
+ strcmp(seclabel, "unclassified") == 0 ||
+ strcmp(seclabel, "classified") == 0)
+ return;
+
+ if (strcmp(seclabel, "secret") == 0 ||
+ strcmp(seclabel, "top secret") == 0)
+ {
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("only superuser can set '%s' label", seclabel)));
+ return;
+ }
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("'%s' is not a valid security label", seclabel)));
+}
+
+void
+_PG_init(void)
+{
+ register_label_provider("dummy", dummy_object_relabel);
+}
diff --git a/contrib/earthdistance/.gitignore b/contrib/earthdistance/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/earthdistance/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/earthdistance/Makefile b/contrib/earthdistance/Makefile
index ab72ac7fc9..48a7cf8c7c 100644
--- a/contrib/earthdistance/Makefile
+++ b/contrib/earthdistance/Makefile
@@ -1,9 +1,12 @@
-# $PostgreSQL: pgsql/contrib/earthdistance/Makefile,v 1.20 2010/07/05 23:15:55 tgl Exp $
+# contrib/earthdistance/Makefile
MODULES = earthdistance
-DATA_built = earthdistance.sql
-DATA = uninstall_earthdistance.sql
+
+EXTENSION = earthdistance
+DATA = earthdistance--1.0.sql earthdistance--unpackaged--1.0.sql
+
REGRESS = earthdistance
+REGRESS_OPTS = --extra-install=contrib/cube
LDFLAGS_SL += $(filter -lm, $(LIBS))
diff --git a/contrib/earthdistance/earthdistance.sql.in b/contrib/earthdistance/earthdistance--1.0.sql
index 2b8041b131..71e4025f6f 100644
--- a/contrib/earthdistance/earthdistance.sql.in
+++ b/contrib/earthdistance/earthdistance--1.0.sql
@@ -1,15 +1,10 @@
-/* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.sql.in,v 1.11 2007/11/13 04:24:27 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
--- The earth functions rely on contrib/cube having been installed and loaded.
+/* contrib/earthdistance/earthdistance--1.0.sql */
-- earth() returns the radius of the earth in meters. This is the only
-- place you need to change things for the cube base distance functions
-- in order to use different units (or a better value for the Earth's radius).
-CREATE OR REPLACE FUNCTION earth() RETURNS float8
+CREATE FUNCTION earth() RETURNS float8
LANGUAGE SQL IMMUTABLE
AS 'SELECT ''6378168''::float8';
@@ -18,7 +13,7 @@ AS 'SELECT ''6378168''::float8';
-- uncomment the one below. Note that doing this will break the regression
-- tests.
--
--- CREATE OR REPLACE FUNCTION earth() RETURNS float8
+-- CREATE FUNCTION earth() RETURNS float8
-- LANGUAGE SQL IMMUTABLE
-- AS 'SELECT 180/pi()';
@@ -35,51 +30,51 @@ CREATE DOMAIN earth AS cube
CONSTRAINT on_surface check(abs(cube_distance(value, '(0)'::cube) /
earth() - 1) < '10e-7'::float8);
-CREATE OR REPLACE FUNCTION sec_to_gc(float8)
+CREATE FUNCTION sec_to_gc(float8)
RETURNS float8
LANGUAGE SQL
IMMUTABLE STRICT
AS 'SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/(2*earth()) > 1 THEN pi()*earth() ELSE 2*earth()*asin($1/(2*earth())) END';
-CREATE OR REPLACE FUNCTION gc_to_sec(float8)
+CREATE FUNCTION gc_to_sec(float8)
RETURNS float8
LANGUAGE SQL
IMMUTABLE STRICT
AS 'SELECT CASE WHEN $1 < 0 THEN 0::float8 WHEN $1/earth() > pi() THEN 2*earth() ELSE 2*earth()*sin($1/(2*earth())) END';
-CREATE OR REPLACE FUNCTION ll_to_earth(float8, float8)
+CREATE FUNCTION ll_to_earth(float8, float8)
RETURNS earth
LANGUAGE SQL
IMMUTABLE STRICT
AS 'SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth';
-CREATE OR REPLACE FUNCTION latitude(earth)
+CREATE FUNCTION latitude(earth)
RETURNS float8
LANGUAGE SQL
IMMUTABLE STRICT
AS 'SELECT CASE WHEN cube_ll_coord($1, 3)/earth() < -1 THEN -90::float8 WHEN cube_ll_coord($1, 3)/earth() > 1 THEN 90::float8 ELSE degrees(asin(cube_ll_coord($1, 3)/earth())) END';
-CREATE OR REPLACE FUNCTION longitude(earth)
+CREATE FUNCTION longitude(earth)
RETURNS float8
LANGUAGE SQL
IMMUTABLE STRICT
AS 'SELECT degrees(atan2(cube_ll_coord($1, 2), cube_ll_coord($1, 1)))';
-CREATE OR REPLACE FUNCTION earth_distance(earth, earth)
+CREATE FUNCTION earth_distance(earth, earth)
RETURNS float8
LANGUAGE SQL
IMMUTABLE STRICT
AS 'SELECT sec_to_gc(cube_distance($1, $2))';
-CREATE OR REPLACE FUNCTION earth_box(earth, float8)
+CREATE FUNCTION earth_box(earth, float8)
RETURNS cube
LANGUAGE SQL
IMMUTABLE STRICT
AS 'SELECT cube_enlarge($1, gc_to_sec($2), 3)';
-
+
--------------- geo_distance
-CREATE OR REPLACE FUNCTION geo_distance (point, point)
+CREATE FUNCTION geo_distance (point, point)
RETURNS float8
LANGUAGE C IMMUTABLE STRICT AS 'MODULE_PATHNAME';
diff --git a/contrib/earthdistance/earthdistance--unpackaged--1.0.sql b/contrib/earthdistance/earthdistance--unpackaged--1.0.sql
new file mode 100644
index 0000000000..2d5919cc72
--- /dev/null
+++ b/contrib/earthdistance/earthdistance--unpackaged--1.0.sql
@@ -0,0 +1,13 @@
+/* contrib/earthdistance/earthdistance--unpackaged--1.0.sql */
+
+ALTER EXTENSION earthdistance ADD function earth();
+ALTER EXTENSION earthdistance ADD type earth;
+ALTER EXTENSION earthdistance ADD function sec_to_gc(double precision);
+ALTER EXTENSION earthdistance ADD function gc_to_sec(double precision);
+ALTER EXTENSION earthdistance ADD function ll_to_earth(double precision,double precision);
+ALTER EXTENSION earthdistance ADD function latitude(earth);
+ALTER EXTENSION earthdistance ADD function longitude(earth);
+ALTER EXTENSION earthdistance ADD function earth_distance(earth,earth);
+ALTER EXTENSION earthdistance ADD function earth_box(earth,double precision);
+ALTER EXTENSION earthdistance ADD function geo_distance(point,point);
+ALTER EXTENSION earthdistance ADD operator <@>(point,point);
diff --git a/contrib/earthdistance/earthdistance.c b/contrib/earthdistance/earthdistance.c
index 4dce1f828e..2f344a7011 100644
--- a/contrib/earthdistance/earthdistance.c
+++ b/contrib/earthdistance/earthdistance.c
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.c,v 1.16 2009/06/11 14:48:51 momjian Exp $ */
+/* contrib/earthdistance/earthdistance.c */
#include "postgres.h"
diff --git a/contrib/earthdistance/earthdistance.control b/contrib/earthdistance/earthdistance.control
new file mode 100644
index 0000000000..afd2ff4f95
--- /dev/null
+++ b/contrib/earthdistance/earthdistance.control
@@ -0,0 +1,6 @@
+# earthdistance extension
+comment = 'calculate great-circle distances on the surface of the Earth'
+default_version = '1.0'
+module_pathname = '$libdir/earthdistance'
+relocatable = true
+requires = 'cube'
diff --git a/contrib/earthdistance/expected/earthdistance.out b/contrib/earthdistance/expected/earthdistance.out
index 5f5645b700..8a3fc749c1 100644
--- a/contrib/earthdistance/expected/earthdistance.out
+++ b/contrib/earthdistance/expected/earthdistance.out
@@ -1,13 +1,8 @@
--
-- Test earth distance functions
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of earthdistance.sql or cube.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION cube;
+CREATE EXTENSION earthdistance;
--
-- The radius of the Earth we are using.
--
diff --git a/contrib/earthdistance/sql/earthdistance.sql b/contrib/earthdistance/sql/earthdistance.sql
index ad68b5635d..e494c350ce 100644
--- a/contrib/earthdistance/sql/earthdistance.sql
+++ b/contrib/earthdistance/sql/earthdistance.sql
@@ -2,16 +2,8 @@
-- Test earth distance functions
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of earthdistance.sql or cube.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i ../cube/cube.sql
-\i earthdistance.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION cube;
+CREATE EXTENSION earthdistance;
--
-- The radius of the Earth we are using.
diff --git a/contrib/earthdistance/uninstall_earthdistance.sql b/contrib/earthdistance/uninstall_earthdistance.sql
deleted file mode 100644
index dfad24aa4f..0000000000
--- a/contrib/earthdistance/uninstall_earthdistance.sql
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/earthdistance/uninstall_earthdistance.sql,v 1.3 2007/11/13 04:24:27 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR <@> (point, point);
-
-DROP FUNCTION geo_distance (point, point);
-
-DROP FUNCTION earth_box(earth, float8);
-
-DROP FUNCTION earth_distance(earth, earth);
-
-DROP FUNCTION longitude(earth);
-
-DROP FUNCTION latitude(earth);
-
-DROP FUNCTION ll_to_earth(float8, float8);
-
-DROP FUNCTION gc_to_sec(float8);
-
-DROP FUNCTION sec_to_gc(float8);
-
-DROP DOMAIN earth;
-
-DROP FUNCTION earth();
diff --git a/contrib/file_fdw/.gitignore b/contrib/file_fdw/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/file_fdw/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/file_fdw/Makefile b/contrib/file_fdw/Makefile
new file mode 100644
index 0000000000..4616cec633
--- /dev/null
+++ b/contrib/file_fdw/Makefile
@@ -0,0 +1,21 @@
+# contrib/file_fdw/Makefile
+
+MODULES = file_fdw
+
+EXTENSION = file_fdw
+DATA = file_fdw--1.0.sql
+
+REGRESS = file_fdw
+
+EXTRA_CLEAN = sql/file_fdw.sql expected/file_fdw.out
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/file_fdw
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/file_fdw/data/agg.bad b/contrib/file_fdw/data/agg.bad
new file mode 100644
index 0000000000..3415b15007
--- /dev/null
+++ b/contrib/file_fdw/data/agg.bad
@@ -0,0 +1,4 @@
+56;@7.8@
+100;@99.097@
+0;@aaa@
+42;@324.78@
diff --git a/contrib/file_fdw/data/agg.csv b/contrib/file_fdw/data/agg.csv
new file mode 100644
index 0000000000..3ee6bf24db
--- /dev/null
+++ b/contrib/file_fdw/data/agg.csv
@@ -0,0 +1,4 @@
+56;@7.8@
+100;@99.097@
+0;@0.09561@
+42;@324.78@
diff --git a/contrib/file_fdw/data/agg.data b/contrib/file_fdw/data/agg.data
new file mode 100644
index 0000000000..d92c7df4d0
--- /dev/null
+++ b/contrib/file_fdw/data/agg.data
@@ -0,0 +1,4 @@
+56 7.8
+100 99.097
+0 0.09561
+42 324.78
diff --git a/contrib/file_fdw/expected/.gitignore b/contrib/file_fdw/expected/.gitignore
new file mode 100644
index 0000000000..a464ad144f
--- /dev/null
+++ b/contrib/file_fdw/expected/.gitignore
@@ -0,0 +1 @@
+/file_fdw.out
diff --git a/contrib/file_fdw/file_fdw--1.0.sql b/contrib/file_fdw/file_fdw--1.0.sql
new file mode 100644
index 0000000000..0cca65f463
--- /dev/null
+++ b/contrib/file_fdw/file_fdw--1.0.sql
@@ -0,0 +1,15 @@
+/* contrib/file_fdw/file_fdw--1.0.sql */
+
+CREATE FUNCTION file_fdw_handler()
+RETURNS fdw_handler
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION file_fdw_validator(text[], oid)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+CREATE FOREIGN DATA WRAPPER file_fdw
+ HANDLER file_fdw_handler
+ VALIDATOR file_fdw_validator;
diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c
new file mode 100644
index 0000000000..466c015107
--- /dev/null
+++ b/contrib/file_fdw/file_fdw.c
@@ -0,0 +1,536 @@
+/*-------------------------------------------------------------------------
+ *
+ * file_fdw.c
+ * foreign-data wrapper for server-side flat files.
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * contrib/file_fdw/file_fdw.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "access/reloptions.h"
+#include "catalog/pg_foreign_table.h"
+#include "commands/copy.h"
+#include "commands/defrem.h"
+#include "commands/explain.h"
+#include "foreign/fdwapi.h"
+#include "foreign/foreign.h"
+#include "miscadmin.h"
+#include "optimizer/cost.h"
+
+PG_MODULE_MAGIC;
+
+/*
+ * Describes the valid options for objects that use this wrapper.
+ */
+struct FileFdwOption
+{
+ const char *optname;
+ Oid optcontext; /* Oid of catalog in which option may appear */
+};
+
+/*
+ * Valid options for file_fdw.
+ * These options are based on the options for COPY FROM command.
+ *
+ * Note: If you are adding new option for user mapping, you need to modify
+ * fileGetOptions(), which currently doesn't bother to look at user mappings.
+ */
+static struct FileFdwOption valid_options[] = {
+ /* File options */
+ {"filename", ForeignTableRelationId},
+
+ /* Format options */
+ /* oids option is not supported */
+ {"format", ForeignTableRelationId},
+ {"header", ForeignTableRelationId},
+ {"delimiter", ForeignTableRelationId},
+ {"quote", ForeignTableRelationId},
+ {"escape", ForeignTableRelationId},
+ {"null", ForeignTableRelationId},
+ {"encoding", ForeignTableRelationId},
+
+ /*
+ * force_quote is not supported by file_fdw because it's for COPY TO.
+ */
+
+ /*
+ * force_not_null is not supported by file_fdw. It would need a parser
+ * for list of columns, not to mention a way to check the column list
+ * against the table.
+ */
+
+ /* Sentinel */
+ {NULL, InvalidOid}
+};
+
+/*
+ * FDW-specific information for ForeignScanState.fdw_state.
+ */
+typedef struct FileFdwExecutionState
+{
+ char *filename; /* file to read */
+ List *options; /* merged COPY options, excluding filename */
+ CopyState cstate; /* state of reading file */
+} FileFdwExecutionState;
+
+/*
+ * SQL functions
+ */
+extern Datum file_fdw_handler(PG_FUNCTION_ARGS);
+extern Datum file_fdw_validator(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(file_fdw_handler);
+PG_FUNCTION_INFO_V1(file_fdw_validator);
+
+/*
+ * FDW callback routines
+ */
+static FdwPlan *filePlanForeignScan(Oid foreigntableid,
+ PlannerInfo *root,
+ RelOptInfo *baserel);
+static void fileExplainForeignScan(ForeignScanState *node, ExplainState *es);
+static void fileBeginForeignScan(ForeignScanState *node, int eflags);
+static TupleTableSlot *fileIterateForeignScan(ForeignScanState *node);
+static void fileReScanForeignScan(ForeignScanState *node);
+static void fileEndForeignScan(ForeignScanState *node);
+
+/*
+ * Helper functions
+ */
+static bool is_valid_option(const char *option, Oid context);
+static void fileGetOptions(Oid foreigntableid,
+ char **filename, List **other_options);
+static void estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
+ const char *filename,
+ Cost *startup_cost, Cost *total_cost);
+
+
+/*
+ * Foreign-data wrapper handler function: return a struct with pointers
+ * to my callback routines.
+ */
+Datum
+file_fdw_handler(PG_FUNCTION_ARGS)
+{
+ FdwRoutine *fdwroutine = makeNode(FdwRoutine);
+
+ fdwroutine->PlanForeignScan = filePlanForeignScan;
+ fdwroutine->ExplainForeignScan = fileExplainForeignScan;
+ fdwroutine->BeginForeignScan = fileBeginForeignScan;
+ fdwroutine->IterateForeignScan = fileIterateForeignScan;
+ fdwroutine->ReScanForeignScan = fileReScanForeignScan;
+ fdwroutine->EndForeignScan = fileEndForeignScan;
+
+ PG_RETURN_POINTER(fdwroutine);
+}
+
+/*
+ * Validate the generic options given to a FOREIGN DATA WRAPPER, SERVER,
+ * USER MAPPING or FOREIGN TABLE that uses file_fdw.
+ *
+ * Raise an ERROR if the option or its value is considered invalid.
+ */
+Datum
+file_fdw_validator(PG_FUNCTION_ARGS)
+{
+ List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
+ Oid catalog = PG_GETARG_OID(1);
+ char *filename = NULL;
+ List *other_options = NIL;
+ ListCell *cell;
+
+ /*
+ * Only superusers are allowed to set options of a file_fdw foreign table.
+ * This is because the filename is one of those options, and we don't want
+ * non-superusers to be able to determine which file gets read.
+ *
+ * Putting this sort of permissions check in a validator is a bit of a
+ * crock, but there doesn't seem to be any other place that can enforce
+ * the check more cleanly.
+ *
+ * Note that the valid_options[] array disallows setting filename at any
+ * options level other than foreign table --- otherwise there'd still be a
+ * security hole.
+ */
+ if (catalog == ForeignTableRelationId && !superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("only superuser can change options of a file_fdw foreign table")));
+
+ /*
+ * Check that only options supported by file_fdw, and allowed for the
+ * current object type, are given.
+ */
+ foreach(cell, options_list)
+ {
+ DefElem *def = (DefElem *) lfirst(cell);
+
+ if (!is_valid_option(def->defname, catalog))
+ {
+ struct FileFdwOption *opt;
+ StringInfoData buf;
+
+ /*
+ * Unknown option specified, complain about it. Provide a hint
+ * with list of valid options for the object.
+ */
+ initStringInfo(&buf);
+ for (opt = valid_options; opt->optname; opt++)
+ {
+ if (catalog == opt->optcontext)
+ appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
+ opt->optname);
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
+ errmsg("invalid option \"%s\"", def->defname),
+ errhint("Valid options in this context are: %s",
+ buf.data)));
+ }
+
+ /* Separate out filename, since ProcessCopyOptions won't allow it */
+ if (strcmp(def->defname, "filename") == 0)
+ {
+ if (filename)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ filename = defGetString(def);
+ }
+ else
+ other_options = lappend(other_options, def);
+ }
+
+ /*
+ * Now apply the core COPY code's validation logic for more checks.
+ */
+ ProcessCopyOptions(NULL, true, other_options);
+
+ PG_RETURN_VOID();
+}
+
+/*
+ * Check if the provided option is one of the valid options.
+ * context is the Oid of the catalog holding the object the option is for.
+ */
+static bool
+is_valid_option(const char *option, Oid context)
+{
+ struct FileFdwOption *opt;
+
+ for (opt = valid_options; opt->optname; opt++)
+ {
+ if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Fetch the options for a file_fdw foreign table.
+ *
+ * We have to separate out "filename" from the other options because
+ * it must not appear in the options list passed to the core COPY code.
+ */
+static void
+fileGetOptions(Oid foreigntableid,
+ char **filename, List **other_options)
+{
+ ForeignTable *table;
+ ForeignServer *server;
+ ForeignDataWrapper *wrapper;
+ List *options;
+ ListCell *lc,
+ *prev;
+
+ /*
+ * Extract options from FDW objects. We ignore user mappings because
+ * file_fdw doesn't have any options that can be specified there.
+ *
+ * (XXX Actually, given the current contents of valid_options[], there's
+ * no point in examining anything except the foreign table's own options.
+ * Simplify?)
+ */
+ table = GetForeignTable(foreigntableid);
+ server = GetForeignServer(table->serverid);
+ wrapper = GetForeignDataWrapper(server->fdwid);
+
+ options = NIL;
+ options = list_concat(options, wrapper->options);
+ options = list_concat(options, server->options);
+ options = list_concat(options, table->options);
+
+ /*
+ * Separate out the filename.
+ */
+ *filename = NULL;
+ prev = NULL;
+ foreach(lc, options)
+ {
+ DefElem *def = (DefElem *) lfirst(lc);
+
+ if (strcmp(def->defname, "filename") == 0)
+ {
+ *filename = defGetString(def);
+ options = list_delete_cell(options, lc, prev);
+ break;
+ }
+ prev = lc;
+ }
+ if (*filename == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FDW_UNABLE_TO_CREATE_REPLY),
+ errmsg("filename is required for file_fdw foreign tables")));
+ *other_options = options;
+}
+
+/*
+ * filePlanForeignScan
+ * Create a FdwPlan for a scan on the foreign table
+ */
+static FdwPlan *
+filePlanForeignScan(Oid foreigntableid,
+ PlannerInfo *root,
+ RelOptInfo *baserel)
+{
+ FdwPlan *fdwplan;
+ char *filename;
+ List *options;
+
+ /* Fetch options --- we only need filename at this point */
+ fileGetOptions(foreigntableid, &filename, &options);
+
+ /* Construct FdwPlan with cost estimates */
+ fdwplan = makeNode(FdwPlan);
+ estimate_costs(root, baserel, filename,
+ &fdwplan->startup_cost, &fdwplan->total_cost);
+ fdwplan->fdw_private = NIL; /* not used */
+
+ return fdwplan;
+}
+
+/*
+ * fileExplainForeignScan
+ * Produce extra output for EXPLAIN
+ */
+static void
+fileExplainForeignScan(ForeignScanState *node, ExplainState *es)
+{
+ char *filename;
+ List *options;
+
+ /* Fetch options --- we only need filename at this point */
+ fileGetOptions(RelationGetRelid(node->ss.ss_currentRelation),
+ &filename, &options);
+
+ ExplainPropertyText("Foreign File", filename, es);
+
+ /* Suppress file size if we're not showing cost details */
+ if (es->costs)
+ {
+ struct stat stat_buf;
+
+ if (stat(filename, &stat_buf) == 0)
+ ExplainPropertyLong("Foreign File Size", (long) stat_buf.st_size,
+ es);
+ }
+}
+
+/*
+ * fileBeginForeignScan
+ * Initiate access to the file by creating CopyState
+ */
+static void
+fileBeginForeignScan(ForeignScanState *node, int eflags)
+{
+ char *filename;
+ List *options;
+ CopyState cstate;
+ FileFdwExecutionState *festate;
+
+ /*
+ * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL.
+ */
+ if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
+ return;
+
+ /* Fetch options of foreign table */
+ fileGetOptions(RelationGetRelid(node->ss.ss_currentRelation),
+ &filename, &options);
+
+ /*
+ * Create CopyState from FDW options. We always acquire all columns, so
+ * as to match the expected ScanTupleSlot signature.
+ */
+ cstate = BeginCopyFrom(node->ss.ss_currentRelation,
+ filename,
+ NIL,
+ options);
+
+ /*
+ * Save state in node->fdw_state. We must save enough information to call
+ * BeginCopyFrom() again.
+ */
+ festate = (FileFdwExecutionState *) palloc(sizeof(FileFdwExecutionState));
+ festate->filename = filename;
+ festate->options = options;
+ festate->cstate = cstate;
+
+ node->fdw_state = (void *) festate;
+}
+
+/*
+ * fileIterateForeignScan
+ * Read next record from the data file and store it into the
+ * ScanTupleSlot as a virtual tuple
+ */
+static TupleTableSlot *
+fileIterateForeignScan(ForeignScanState *node)
+{
+ FileFdwExecutionState *festate = (FileFdwExecutionState *) node->fdw_state;
+ TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
+ bool found;
+ ErrorContextCallback errcontext;
+
+ /* Set up callback to identify error line number. */
+ errcontext.callback = CopyFromErrorCallback;
+ errcontext.arg = (void *) festate->cstate;
+ errcontext.previous = error_context_stack;
+ error_context_stack = &errcontext;
+
+ /*
+ * The protocol for loading a virtual tuple into a slot is first
+ * ExecClearTuple, then fill the values/isnull arrays, then
+ * ExecStoreVirtualTuple. If we don't find another row in the file, we
+ * just skip the last step, leaving the slot empty as required.
+ *
+ * We can pass ExprContext = NULL because we read all columns from the
+ * file, so no need to evaluate default expressions.
+ *
+ * We can also pass tupleOid = NULL because we don't allow oids for
+ * foreign tables.
+ */
+ ExecClearTuple(slot);
+ found = NextCopyFrom(festate->cstate, NULL,
+ slot->tts_values, slot->tts_isnull,
+ NULL);
+ if (found)
+ ExecStoreVirtualTuple(slot);
+
+ /* Remove error callback. */
+ error_context_stack = errcontext.previous;
+
+ return slot;
+}
+
+/*
+ * fileEndForeignScan
+ * Finish scanning foreign table and dispose objects used for this scan
+ */
+static void
+fileEndForeignScan(ForeignScanState *node)
+{
+ FileFdwExecutionState *festate = (FileFdwExecutionState *) node->fdw_state;
+
+ /* if festate is NULL, we are in EXPLAIN; nothing to do */
+ if (festate)
+ EndCopyFrom(festate->cstate);
+}
+
+/*
+ * fileReScanForeignScan
+ * Rescan table, possibly with new parameters
+ */
+static void
+fileReScanForeignScan(ForeignScanState *node)
+{
+ FileFdwExecutionState *festate = (FileFdwExecutionState *) node->fdw_state;
+
+ EndCopyFrom(festate->cstate);
+
+ festate->cstate = BeginCopyFrom(node->ss.ss_currentRelation,
+ festate->filename,
+ NIL,
+ festate->options);
+}
+
+/*
+ * Estimate costs of scanning a foreign table.
+ */
+static void
+estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
+ const char *filename,
+ Cost *startup_cost, Cost *total_cost)
+{
+ struct stat stat_buf;
+ BlockNumber pages;
+ int tuple_width;
+ double ntuples;
+ double nrows;
+ Cost run_cost = 0;
+ Cost cpu_per_tuple;
+
+ /*
+ * Get size of the file. It might not be there at plan time, though, in
+ * which case we have to use a default estimate.
+ */
+ if (stat(filename, &stat_buf) < 0)
+ stat_buf.st_size = 10 * BLCKSZ;
+
+ /*
+ * Convert size to pages for use in I/O cost estimate below.
+ */
+ pages = (stat_buf.st_size + (BLCKSZ - 1)) / BLCKSZ;
+ if (pages < 1)
+ pages = 1;
+
+ /*
+ * Estimate the number of tuples in the file. We back into this estimate
+ * using the planner's idea of the relation width; which is bogus if not
+ * all columns are being read, not to mention that the text representation
+ * of a row probably isn't the same size as its internal representation.
+ * FIXME later.
+ */
+ tuple_width = MAXALIGN(baserel->width) + MAXALIGN(sizeof(HeapTupleHeaderData));
+
+ ntuples = clamp_row_est((double) stat_buf.st_size / (double) tuple_width);
+
+ /*
+ * Now estimate the number of rows returned by the scan after applying the
+ * baserestrictinfo quals. This is pretty bogus too, since the planner
+ * will have no stats about the relation, but it's better than nothing.
+ */
+ nrows = ntuples *
+ clauselist_selectivity(root,
+ baserel->baserestrictinfo,
+ 0,
+ JOIN_INNER,
+ NULL);
+
+ nrows = clamp_row_est(nrows);
+
+ /* Save the output-rows estimate for the planner */
+ baserel->rows = nrows;
+
+ /*
+ * Now estimate costs. We estimate costs almost the same way as
+ * cost_seqscan(), thus assuming that I/O costs are equivalent to a
+ * regular table file of the same size. However, we take per-tuple CPU
+ * costs as 10x of a seqscan, to account for the cost of parsing records.
+ */
+ run_cost += seq_page_cost * pages;
+
+ *startup_cost = baserel->baserestrictcost.startup;
+ cpu_per_tuple = cpu_tuple_cost * 10 + baserel->baserestrictcost.per_tuple;
+ run_cost += cpu_per_tuple * ntuples;
+ *total_cost = *startup_cost + run_cost;
+}
diff --git a/contrib/file_fdw/file_fdw.control b/contrib/file_fdw/file_fdw.control
new file mode 100644
index 0000000000..f0fccab53b
--- /dev/null
+++ b/contrib/file_fdw/file_fdw.control
@@ -0,0 +1,5 @@
+# file_fdw extension
+comment = 'foreign-data wrapper for flat file access'
+default_version = '1.0'
+module_pathname = '$libdir/file_fdw'
+relocatable = true
diff --git a/contrib/file_fdw/input/file_fdw.source b/contrib/file_fdw/input/file_fdw.source
new file mode 100644
index 0000000000..9ff7235a12
--- /dev/null
+++ b/contrib/file_fdw/input/file_fdw.source
@@ -0,0 +1,131 @@
+--
+-- Test foreign-data wrapper file_fdw.
+--
+
+-- Clean up in case a prior regression run failed
+SET client_min_messages TO 'error';
+DROP ROLE IF EXISTS file_fdw_superuser, file_fdw_user, no_priv_user;
+RESET client_min_messages;
+
+CREATE ROLE file_fdw_superuser LOGIN SUPERUSER; -- is a superuser
+CREATE ROLE file_fdw_user LOGIN; -- has priv and user mapping
+CREATE ROLE no_priv_user LOGIN; -- has priv but no user mapping
+
+-- Install file_fdw
+CREATE EXTENSION file_fdw;
+
+-- file_fdw_superuser owns fdw-related objects
+SET ROLE file_fdw_superuser;
+CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
+
+-- privilege tests
+SET ROLE file_fdw_user;
+CREATE FOREIGN DATA WRAPPER file_fdw2 HANDLER file_fdw_handler VALIDATOR file_fdw_validator; -- ERROR
+CREATE SERVER file_server2 FOREIGN DATA WRAPPER file_fdw; -- ERROR
+CREATE USER MAPPING FOR file_fdw_user SERVER file_server; -- ERROR
+
+SET ROLE file_fdw_superuser;
+GRANT USAGE ON FOREIGN SERVER file_server TO file_fdw_user;
+
+SET ROLE file_fdw_user;
+CREATE USER MAPPING FOR file_fdw_user SERVER file_server;
+
+-- create user mappings and grant privilege to test users
+SET ROLE file_fdw_superuser;
+CREATE USER MAPPING FOR file_fdw_superuser SERVER file_server;
+CREATE USER MAPPING FOR no_priv_user SERVER file_server;
+
+-- validator tests
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'xml'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', header 'true'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', quote ':'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', escape ':'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', header 'true'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', quote ':'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', escape ':'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter 'a'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', escape '-'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', quote '-', null '=-='); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '-', null '=-='); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '-', quote '-'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '---'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', quote '---'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', escape '---'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter '\'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter '.'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter '1'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter 'a'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '
+'); -- ERROR
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', null '
+'); -- ERROR
+
+CREATE FOREIGN TABLE agg_text (
+ a int2,
+ b float4
+) SERVER file_server
+OPTIONS (format 'text', filename '@abs_srcdir@/data/agg.data', delimiter ' ', null '\N');
+GRANT SELECT ON agg_text TO file_fdw_user;
+CREATE FOREIGN TABLE agg_csv (
+ a int2,
+ b float4
+) SERVER file_server
+OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.csv', header 'true', delimiter ';', quote '@', escape '"', null '');
+CREATE FOREIGN TABLE agg_bad (
+ a int2,
+ b float4
+) SERVER file_server
+OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.bad', header 'true', delimiter ';', quote '@', escape '"', null '');
+
+-- basic query tests
+SELECT * FROM agg_text WHERE b > 10.0 ORDER BY a;
+SELECT * FROM agg_csv ORDER BY a;
+SELECT * FROM agg_csv c JOIN agg_text t ON (t.a = c.a) ORDER BY c.a;
+
+-- error context report tests
+SELECT * FROM agg_bad; -- ERROR
+
+-- misc query tests
+\t on
+EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv;
+\t off
+PREPARE st(int) AS SELECT * FROM agg_csv WHERE a = $1;
+EXECUTE st(100);
+EXECUTE st(100);
+DEALLOCATE st;
+
+-- tableoid
+SELECT tableoid::regclass, b FROM agg_csv;
+
+-- updates aren't supported
+INSERT INTO agg_csv VALUES(1,2.0);
+UPDATE agg_csv SET a = 1;
+DELETE FROM agg_csv WHERE a = 100;
+SELECT * FROM agg_csv FOR UPDATE OF agg_csv;
+-- but this should be ignored
+SELECT * FROM agg_csv FOR UPDATE;
+
+-- privilege tests
+SET ROLE file_fdw_superuser;
+SELECT * FROM agg_text ORDER BY a;
+SET ROLE file_fdw_user;
+SELECT * FROM agg_text ORDER BY a;
+SET ROLE no_priv_user;
+SELECT * FROM agg_text ORDER BY a; -- ERROR
+SET ROLE file_fdw_user;
+\t on
+EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_text WHERE a > 0;
+\t off
+
+-- privilege tests for object
+SET ROLE file_fdw_superuser;
+ALTER FOREIGN TABLE agg_text OWNER TO file_fdw_user;
+ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
+SET ROLE file_fdw_user;
+ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
+SET ROLE file_fdw_superuser;
+
+-- cleanup
+RESET ROLE;
+DROP EXTENSION file_fdw CASCADE;
+DROP ROLE file_fdw_superuser, file_fdw_user, no_priv_user;
diff --git a/contrib/file_fdw/output/file_fdw.source b/contrib/file_fdw/output/file_fdw.source
new file mode 100644
index 0000000000..2ba36c9368
--- /dev/null
+++ b/contrib/file_fdw/output/file_fdw.source
@@ -0,0 +1,225 @@
+--
+-- Test foreign-data wrapper file_fdw.
+--
+-- Clean up in case a prior regression run failed
+SET client_min_messages TO 'error';
+DROP ROLE IF EXISTS file_fdw_superuser, file_fdw_user, no_priv_user;
+RESET client_min_messages;
+CREATE ROLE file_fdw_superuser LOGIN SUPERUSER; -- is a superuser
+CREATE ROLE file_fdw_user LOGIN; -- has priv and user mapping
+CREATE ROLE no_priv_user LOGIN; -- has priv but no user mapping
+-- Install file_fdw
+CREATE EXTENSION file_fdw;
+-- file_fdw_superuser owns fdw-related objects
+SET ROLE file_fdw_superuser;
+CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;
+-- privilege tests
+SET ROLE file_fdw_user;
+CREATE FOREIGN DATA WRAPPER file_fdw2 HANDLER file_fdw_handler VALIDATOR file_fdw_validator; -- ERROR
+ERROR: permission denied to create foreign-data wrapper "file_fdw2"
+HINT: Must be superuser to create a foreign-data wrapper.
+CREATE SERVER file_server2 FOREIGN DATA WRAPPER file_fdw; -- ERROR
+ERROR: permission denied for foreign-data wrapper file_fdw
+CREATE USER MAPPING FOR file_fdw_user SERVER file_server; -- ERROR
+ERROR: permission denied for foreign server file_server
+SET ROLE file_fdw_superuser;
+GRANT USAGE ON FOREIGN SERVER file_server TO file_fdw_user;
+SET ROLE file_fdw_user;
+CREATE USER MAPPING FOR file_fdw_user SERVER file_server;
+-- create user mappings and grant privilege to test users
+SET ROLE file_fdw_superuser;
+CREATE USER MAPPING FOR file_fdw_superuser SERVER file_server;
+CREATE USER MAPPING FOR no_priv_user SERVER file_server;
+-- validator tests
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'xml'); -- ERROR
+ERROR: COPY format "xml" not recognized
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', header 'true'); -- ERROR
+ERROR: COPY HEADER available only in CSV mode
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', quote ':'); -- ERROR
+ERROR: COPY quote available only in CSV mode
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', escape ':'); -- ERROR
+ERROR: COPY escape available only in CSV mode
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', header 'true'); -- ERROR
+ERROR: COPY HEADER available only in CSV mode
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', quote ':'); -- ERROR
+ERROR: COPY quote available only in CSV mode
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', escape ':'); -- ERROR
+ERROR: COPY escape available only in CSV mode
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter 'a'); -- ERROR
+ERROR: COPY delimiter cannot be "a"
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', escape '-'); -- ERROR
+ERROR: COPY escape available only in CSV mode
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', quote '-', null '=-='); -- ERROR
+ERROR: CSV quote character must not appear in the NULL specification
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '-', null '=-='); -- ERROR
+ERROR: COPY delimiter must not appear in the NULL specification
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '-', quote '-'); -- ERROR
+ERROR: COPY delimiter and quote must be different
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '---'); -- ERROR
+ERROR: COPY delimiter must be a single one-byte character
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', quote '---'); -- ERROR
+ERROR: COPY quote must be a single one-byte character
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', escape '---'); -- ERROR
+ERROR: COPY escape must be a single one-byte character
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter '\'); -- ERROR
+ERROR: COPY delimiter cannot be "\"
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter '.'); -- ERROR
+ERROR: COPY delimiter cannot be "."
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter '1'); -- ERROR
+ERROR: COPY delimiter cannot be "1"
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', delimiter 'a'); -- ERROR
+ERROR: COPY delimiter cannot be "a"
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '
+'); -- ERROR
+ERROR: COPY delimiter cannot be newline or carriage return
+CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', null '
+'); -- ERROR
+ERROR: COPY null representation cannot use newline or carriage return
+CREATE FOREIGN TABLE agg_text (
+ a int2,
+ b float4
+) SERVER file_server
+OPTIONS (format 'text', filename '@abs_srcdir@/data/agg.data', delimiter ' ', null '\N');
+GRANT SELECT ON agg_text TO file_fdw_user;
+CREATE FOREIGN TABLE agg_csv (
+ a int2,
+ b float4
+) SERVER file_server
+OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.csv', header 'true', delimiter ';', quote '@', escape '"', null '');
+CREATE FOREIGN TABLE agg_bad (
+ a int2,
+ b float4
+) SERVER file_server
+OPTIONS (format 'csv', filename '@abs_srcdir@/data/agg.bad', header 'true', delimiter ';', quote '@', escape '"', null '');
+-- basic query tests
+SELECT * FROM agg_text WHERE b > 10.0 ORDER BY a;
+ a | b
+-----+--------
+ 42 | 324.78
+ 100 | 99.097
+(2 rows)
+
+SELECT * FROM agg_csv ORDER BY a;
+ a | b
+-----+---------
+ 0 | 0.09561
+ 42 | 324.78
+ 100 | 99.097
+(3 rows)
+
+SELECT * FROM agg_csv c JOIN agg_text t ON (t.a = c.a) ORDER BY c.a;
+ a | b | a | b
+-----+---------+-----+---------
+ 0 | 0.09561 | 0 | 0.09561
+ 42 | 324.78 | 42 | 324.78
+ 100 | 99.097 | 100 | 99.097
+(3 rows)
+
+-- error context report tests
+SELECT * FROM agg_bad; -- ERROR
+ERROR: invalid input syntax for type real: "aaa"
+CONTEXT: COPY agg_bad, line 3, column b: "aaa"
+-- misc query tests
+\t on
+EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv;
+ Foreign Scan on public.agg_csv
+ Output: a, b
+ Foreign File: @abs_srcdir@/data/agg.csv
+
+\t off
+PREPARE st(int) AS SELECT * FROM agg_csv WHERE a = $1;
+EXECUTE st(100);
+ a | b
+-----+--------
+ 100 | 99.097
+(1 row)
+
+EXECUTE st(100);
+ a | b
+-----+--------
+ 100 | 99.097
+(1 row)
+
+DEALLOCATE st;
+-- tableoid
+SELECT tableoid::regclass, b FROM agg_csv;
+ tableoid | b
+----------+---------
+ agg_csv | 99.097
+ agg_csv | 0.09561
+ agg_csv | 324.78
+(3 rows)
+
+-- updates aren't supported
+INSERT INTO agg_csv VALUES(1,2.0);
+ERROR: cannot change foreign table "agg_csv"
+UPDATE agg_csv SET a = 1;
+ERROR: cannot change foreign table "agg_csv"
+DELETE FROM agg_csv WHERE a = 100;
+ERROR: cannot change foreign table "agg_csv"
+SELECT * FROM agg_csv FOR UPDATE OF agg_csv;
+ERROR: SELECT FOR UPDATE/SHARE cannot be used with foreign table "agg_csv"
+LINE 1: SELECT * FROM agg_csv FOR UPDATE OF agg_csv;
+ ^
+-- but this should be ignored
+SELECT * FROM agg_csv FOR UPDATE;
+ a | b
+-----+---------
+ 100 | 99.097
+ 0 | 0.09561
+ 42 | 324.78
+(3 rows)
+
+-- privilege tests
+SET ROLE file_fdw_superuser;
+SELECT * FROM agg_text ORDER BY a;
+ a | b
+-----+---------
+ 0 | 0.09561
+ 42 | 324.78
+ 56 | 7.8
+ 100 | 99.097
+(4 rows)
+
+SET ROLE file_fdw_user;
+SELECT * FROM agg_text ORDER BY a;
+ a | b
+-----+---------
+ 0 | 0.09561
+ 42 | 324.78
+ 56 | 7.8
+ 100 | 99.097
+(4 rows)
+
+SET ROLE no_priv_user;
+SELECT * FROM agg_text ORDER BY a; -- ERROR
+ERROR: permission denied for relation agg_text
+SET ROLE file_fdw_user;
+\t on
+EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_text WHERE a > 0;
+ Foreign Scan on public.agg_text
+ Output: a, b
+ Filter: (agg_text.a > 0)
+ Foreign File: @abs_srcdir@/data/agg.data
+
+\t off
+-- privilege tests for object
+SET ROLE file_fdw_superuser;
+ALTER FOREIGN TABLE agg_text OWNER TO file_fdw_user;
+ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
+SET ROLE file_fdw_user;
+ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
+ERROR: only superuser can change options of a file_fdw foreign table
+SET ROLE file_fdw_superuser;
+-- cleanup
+RESET ROLE;
+DROP EXTENSION file_fdw CASCADE;
+NOTICE: drop cascades to 7 other objects
+DETAIL: drop cascades to server file_server
+drop cascades to user mapping for file_fdw_user
+drop cascades to user mapping for file_fdw_superuser
+drop cascades to user mapping for no_priv_user
+drop cascades to foreign table agg_text
+drop cascades to foreign table agg_csv
+drop cascades to foreign table agg_bad
+DROP ROLE file_fdw_superuser, file_fdw_user, no_priv_user;
diff --git a/contrib/file_fdw/sql/.gitignore b/contrib/file_fdw/sql/.gitignore
new file mode 100644
index 0000000000..ebf16fed94
--- /dev/null
+++ b/contrib/file_fdw/sql/.gitignore
@@ -0,0 +1 @@
+/file_fdw.sql
diff --git a/contrib/fuzzystrmatch/Makefile b/contrib/fuzzystrmatch/Makefile
index 723830950d..834b679b10 100644
--- a/contrib/fuzzystrmatch/Makefile
+++ b/contrib/fuzzystrmatch/Makefile
@@ -1,9 +1,10 @@
-# $PostgreSQL: pgsql/contrib/fuzzystrmatch/Makefile,v 1.10 2007/11/10 23:59:50 momjian Exp $
+# contrib/fuzzystrmatch/Makefile
MODULE_big = fuzzystrmatch
OBJS = fuzzystrmatch.o dmetaphone.o
-DATA_built = fuzzystrmatch.sql
-DATA = uninstall_fuzzystrmatch.sql
+
+EXTENSION = fuzzystrmatch
+DATA = fuzzystrmatch--1.0.sql fuzzystrmatch--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
@@ -15,3 +16,6 @@ top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif
+
+# levenshtein.c is #included by fuzzystrmatch.c
+fuzzystrmatch.o: fuzzystrmatch.c levenshtein.c
diff --git a/contrib/fuzzystrmatch/dmetaphone.c b/contrib/fuzzystrmatch/dmetaphone.c
index f23a3a2aa6..6721e58f22 100644
--- a/contrib/fuzzystrmatch/dmetaphone.c
+++ b/contrib/fuzzystrmatch/dmetaphone.c
@@ -1,7 +1,7 @@
/*
* This is a port of the Double Metaphone algorithm for use in PostgreSQL.
*
- * $PostgreSQL: pgsql/contrib/fuzzystrmatch/dmetaphone.c,v 1.15 2010/07/06 19:18:55 momjian Exp $
+ * contrib/fuzzystrmatch/dmetaphone.c
*
* Double Metaphone computes 2 "sounds like" strings - a primary and an
* alternate. In most cases they are the same, but for foreign names
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch--1.0.sql b/contrib/fuzzystrmatch/fuzzystrmatch--1.0.sql
new file mode 100644
index 0000000000..d9b8987adf
--- /dev/null
+++ b/contrib/fuzzystrmatch/fuzzystrmatch--1.0.sql
@@ -0,0 +1,41 @@
+/* contrib/fuzzystrmatch/fuzzystrmatch--1.0.sql */
+
+CREATE FUNCTION levenshtein (text,text) RETURNS int
+AS 'MODULE_PATHNAME','levenshtein'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION levenshtein (text,text,int,int,int) RETURNS int
+AS 'MODULE_PATHNAME','levenshtein_with_costs'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION levenshtein_less_equal (text,text,int) RETURNS int
+AS 'MODULE_PATHNAME','levenshtein_less_equal'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION levenshtein_less_equal (text,text,int,int,int,int) RETURNS int
+AS 'MODULE_PATHNAME','levenshtein_less_equal_with_costs'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION metaphone (text,int) RETURNS text
+AS 'MODULE_PATHNAME','metaphone'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION soundex(text) RETURNS text
+AS 'MODULE_PATHNAME', 'soundex'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION text_soundex(text) RETURNS text
+AS 'MODULE_PATHNAME', 'soundex'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION difference(text,text) RETURNS int
+AS 'MODULE_PATHNAME', 'difference'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION dmetaphone (text) RETURNS text
+AS 'MODULE_PATHNAME', 'dmetaphone'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION dmetaphone_alt (text) RETURNS text
+AS 'MODULE_PATHNAME', 'dmetaphone_alt'
+LANGUAGE C IMMUTABLE STRICT;
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch--unpackaged--1.0.sql b/contrib/fuzzystrmatch/fuzzystrmatch--unpackaged--1.0.sql
new file mode 100644
index 0000000000..b99510bcdd
--- /dev/null
+++ b/contrib/fuzzystrmatch/fuzzystrmatch--unpackaged--1.0.sql
@@ -0,0 +1,20 @@
+/* contrib/fuzzystrmatch/fuzzystrmatch--unpackaged--1.0.sql */
+
+ALTER EXTENSION fuzzystrmatch ADD function levenshtein(text,text);
+ALTER EXTENSION fuzzystrmatch ADD function levenshtein(text,text,integer,integer,integer);
+ALTER EXTENSION fuzzystrmatch ADD function metaphone(text,integer);
+ALTER EXTENSION fuzzystrmatch ADD function soundex(text);
+ALTER EXTENSION fuzzystrmatch ADD function text_soundex(text);
+ALTER EXTENSION fuzzystrmatch ADD function difference(text,text);
+ALTER EXTENSION fuzzystrmatch ADD function dmetaphone(text);
+ALTER EXTENSION fuzzystrmatch ADD function dmetaphone_alt(text);
+
+-- these functions were not in 9.0
+
+CREATE FUNCTION levenshtein_less_equal (text,text,int) RETURNS int
+AS 'MODULE_PATHNAME','levenshtein_less_equal'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION levenshtein_less_equal (text,text,int,int,int,int) RETURNS int
+AS 'MODULE_PATHNAME','levenshtein_less_equal_with_costs'
+LANGUAGE C IMMUTABLE STRICT;
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c
index 0bf7c681a1..782bc1e4d4 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.c
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.c
@@ -5,19 +5,10 @@
*
* Joe Conway <mail@joeconway.com>
*
- * $PostgreSQL: pgsql/contrib/fuzzystrmatch/fuzzystrmatch.c,v 1.32 2010/01/02 16:57:32 momjian Exp $
- * Copyright (c) 2001-2010, PostgreSQL Global Development Group
+ * contrib/fuzzystrmatch/fuzzystrmatch.c
+ * Copyright (c) 2001-2011, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
- * levenshtein()
- * -------------
- * Written based on a description of the algorithm by Michael Gilleland
- * found at http://www.merriampark.com/ld.htm
- * Also looked at levenshtein.c in the PHP 4.0.6 distribution for
- * inspiration.
- * Configurable penalty costs extension is introduced by Volkan
- * YAZICI <volkan.yazici@gmail.com>.
- *
* metaphone()
* -----------
* Modified for PostgreSQL by Joe Conway.
@@ -50,6 +41,7 @@
#include <ctype.h>
#include "fmgr.h"
+#include "mb/pg_wchar.h"
#include "utils/builtins.h"
PG_MODULE_MAGIC;
@@ -60,6 +52,8 @@ PG_MODULE_MAGIC;
*/
extern Datum levenshtein_with_costs(PG_FUNCTION_ARGS);
extern Datum levenshtein(PG_FUNCTION_ARGS);
+extern Datum levenshtein_less_equal_with_costs(PG_FUNCTION_ARGS);
+extern Datum levenshtein_less_equal(PG_FUNCTION_ARGS);
extern Datum metaphone(PG_FUNCTION_ARGS);
extern Datum soundex(PG_FUNCTION_ARGS);
extern Datum difference(PG_FUNCTION_ARGS);
@@ -84,16 +78,6 @@ soundex_code(char letter)
return letter;
}
-
-/*
- * Levenshtein
- */
-#define MAX_LEVENSHTEIN_STRLEN 255
-
-static int levenshtein_internal(const char *s, const char *t,
- int ins_c, int del_c, int sub_c);
-
-
/*
* Metaphone
*/
@@ -183,113 +167,29 @@ getcode(char c)
/* These prevent GH from becoming F */
#define NOGHTOF(c) (getcode(c) & 16) /* BDH */
-
-/*
- * levenshtein_internal - Calculates Levenshtein distance metric
- * between supplied strings. Generally
- * (1, 1, 1) penalty costs suffices common
- * cases, but your mileage may vary.
- */
-static int
-levenshtein_internal(const char *s, const char *t,
- int ins_c, int del_c, int sub_c)
+/* Faster than memcmp(), for this use case. */
+static bool inline
+rest_of_char_same(const char *s1, const char *s2, int len)
{
- int m,
- n;
- int *prev;
- int *curr;
- int i,
- j;
- const char *x;
- const char *y;
-
- m = strlen(s);
- n = strlen(t);
-
- /*
- * We can transform an empty s into t with n insertions, or a non-empty t
- * into an empty s with m deletions.
- */
- if (!m)
- return n * ins_c;
- if (!n)
- return m * del_c;
-
- /*
- * For security concerns, restrict excessive CPU+RAM usage. (This
- * implementation uses O(m) memory and has O(mn) complexity.)
- */
- if (m > MAX_LEVENSHTEIN_STRLEN ||
- n > MAX_LEVENSHTEIN_STRLEN)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("argument exceeds the maximum length of %d bytes",
- MAX_LEVENSHTEIN_STRLEN)));
-
- /* One more cell for initialization column and row. */
- ++m;
- ++n;
-
- /*
- * Instead of building an (m+1)x(n+1) array, we'll use two different
- * arrays of size m+1 for storing accumulated values. At each step one
- * represents the "previous" row and one is the "current" row of the
- * notional large array.
- */
- prev = (int *) palloc(2 * m * sizeof(int));
- curr = prev + m;
-
- /* Initialize the "previous" row to 0..cols */
- for (i = 0; i < m; i++)
- prev[i] = i * del_c;
-
- /* Loop through rows of the notional array */
- for (y = t, j = 1; j < n; y++, j++)
+ while (len > 0)
{
- int *temp;
-
- /*
- * First cell must increment sequentially, as we're on the j'th row of
- * the (m+1)x(n+1) array.
- */
- curr[0] = j * ins_c;
-
- for (x = s, i = 1; i < m; x++, i++)
- {
- int ins;
- int del;
- int sub;
-
- /* Calculate costs for probable operations. */
- ins = prev[i] + ins_c; /* Insertion */
- del = curr[i - 1] + del_c; /* Deletion */
- sub = prev[i - 1] + ((*x == *y) ? 0 : sub_c); /* Substitution */
-
- /* Take the one with minimum cost. */
- curr[i] = Min(ins, del);
- curr[i] = Min(curr[i], sub);
- }
-
- /* Swap current row with previous row. */
- temp = curr;
- curr = prev;
- prev = temp;
+ len--;
+ if (s1[len] != s2[len])
+ return false;
}
-
- /*
- * Because the final value was swapped from the previous row to the
- * current row, that's where we'll find it.
- */
- return prev[m - 1];
+ return true;
}
+#include "levenshtein.c"
+#define LEVENSHTEIN_LESS_EQUAL
+#include "levenshtein.c"
PG_FUNCTION_INFO_V1(levenshtein_with_costs);
Datum
levenshtein_with_costs(PG_FUNCTION_ARGS)
{
- char *src = TextDatumGetCString(PG_GETARG_DATUM(0));
- char *dst = TextDatumGetCString(PG_GETARG_DATUM(1));
+ text *src = PG_GETARG_TEXT_PP(0);
+ text *dst = PG_GETARG_TEXT_PP(1);
int ins_c = PG_GETARG_INT32(2);
int del_c = PG_GETARG_INT32(3);
int sub_c = PG_GETARG_INT32(4);
@@ -302,13 +202,40 @@ PG_FUNCTION_INFO_V1(levenshtein);
Datum
levenshtein(PG_FUNCTION_ARGS)
{
- char *src = TextDatumGetCString(PG_GETARG_DATUM(0));
- char *dst = TextDatumGetCString(PG_GETARG_DATUM(1));
+ text *src = PG_GETARG_TEXT_PP(0);
+ text *dst = PG_GETARG_TEXT_PP(1);
PG_RETURN_INT32(levenshtein_internal(src, dst, 1, 1, 1));
}
+PG_FUNCTION_INFO_V1(levenshtein_less_equal_with_costs);
+Datum
+levenshtein_less_equal_with_costs(PG_FUNCTION_ARGS)
+{
+ text *src = PG_GETARG_TEXT_PP(0);
+ text *dst = PG_GETARG_TEXT_PP(1);
+ int ins_c = PG_GETARG_INT32(2);
+ int del_c = PG_GETARG_INT32(3);
+ int sub_c = PG_GETARG_INT32(4);
+ int max_d = PG_GETARG_INT32(5);
+
+ PG_RETURN_INT32(levenshtein_less_equal_internal(src, dst, ins_c, del_c, sub_c, max_d));
+}
+
+
+PG_FUNCTION_INFO_V1(levenshtein_less_equal);
+Datum
+levenshtein_less_equal(PG_FUNCTION_ARGS)
+{
+ text *src = PG_GETARG_TEXT_PP(0);
+ text *dst = PG_GETARG_TEXT_PP(1);
+ int max_d = PG_GETARG_INT32(2);
+
+ PG_RETURN_INT32(levenshtein_less_equal_internal(src, dst, 1, 1, 1, max_d));
+}
+
+
/*
* Calculates the metaphone of an input string.
* Returns number of characters requested
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.control b/contrib/fuzzystrmatch/fuzzystrmatch.control
new file mode 100644
index 0000000000..e257f09611
--- /dev/null
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.control
@@ -0,0 +1,5 @@
+# fuzzystrmatch extension
+comment = 'determine similarities and distance between strings'
+default_version = '1.0'
+module_pathname = '$libdir/fuzzystrmatch'
+relocatable = true
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.sql.in b/contrib/fuzzystrmatch/fuzzystrmatch.sql.in
deleted file mode 100644
index cab78997fa..0000000000
--- a/contrib/fuzzystrmatch/fuzzystrmatch.sql.in
+++ /dev/null
@@ -1,36 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/fuzzystrmatch/fuzzystrmatch.sql.in,v 1.10 2008/04/03 21:13:07 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION levenshtein (text,text) RETURNS int
-AS 'MODULE_PATHNAME','levenshtein'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION levenshtein (text,text,int,int,int) RETURNS int
-AS 'MODULE_PATHNAME','levenshtein_with_costs'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION metaphone (text,int) RETURNS text
-AS 'MODULE_PATHNAME','metaphone'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION soundex(text) RETURNS text
-AS 'MODULE_PATHNAME', 'soundex'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION text_soundex(text) RETURNS text
-AS 'MODULE_PATHNAME', 'soundex'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION difference(text,text) RETURNS int
-AS 'MODULE_PATHNAME', 'difference'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION dmetaphone (text) RETURNS text
-AS 'MODULE_PATHNAME', 'dmetaphone'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION dmetaphone_alt (text) RETURNS text
-AS 'MODULE_PATHNAME', 'dmetaphone_alt'
-LANGUAGE C IMMUTABLE STRICT;
diff --git a/contrib/fuzzystrmatch/levenshtein.c b/contrib/fuzzystrmatch/levenshtein.c
new file mode 100644
index 0000000000..a84c46a4a4
--- /dev/null
+++ b/contrib/fuzzystrmatch/levenshtein.c
@@ -0,0 +1,403 @@
+/*
+ * levenshtein.c
+ *
+ * Functions for "fuzzy" comparison of strings
+ *
+ * Joe Conway <mail@joeconway.com>
+ *
+ * Copyright (c) 2001-2011, PostgreSQL Global Development Group
+ * ALL RIGHTS RESERVED;
+ *
+ * levenshtein()
+ * -------------
+ * Written based on a description of the algorithm by Michael Gilleland
+ * found at http://www.merriampark.com/ld.htm
+ * Also looked at levenshtein.c in the PHP 4.0.6 distribution for
+ * inspiration.
+ * Configurable penalty costs extension is introduced by Volkan
+ * YAZICI <volkan.yazici@gmail.com>.
+ */
+
+/*
+ * External declarations for exported functions
+ */
+#ifdef LEVENSHTEIN_LESS_EQUAL
+static int levenshtein_less_equal_internal(text *s, text *t,
+ int ins_c, int del_c, int sub_c, int max_d);
+#else
+static int levenshtein_internal(text *s, text *t,
+ int ins_c, int del_c, int sub_c);
+#endif
+
+#define MAX_LEVENSHTEIN_STRLEN 255
+
+
+/*
+ * Calculates Levenshtein distance metric between supplied strings. Generally
+ * (1, 1, 1) penalty costs suffices for common cases, but your mileage may
+ * vary.
+ *
+ * One way to compute Levenshtein distance is to incrementally construct
+ * an (m+1)x(n+1) matrix where cell (i, j) represents the minimum number
+ * of operations required to transform the first i characters of s into
+ * the first j characters of t. The last column of the final row is the
+ * answer.
+ *
+ * We use that algorithm here with some modification. In lieu of holding
+ * the entire array in memory at once, we'll just use two arrays of size
+ * m+1 for storing accumulated values. At each step one array represents
+ * the "previous" row and one is the "current" row of the notional large
+ * array.
+ *
+ * If max_d >= 0, we only need to provide an accurate answer when that answer
+ * is less than or equal to the bound. From any cell in the matrix, there is
+ * theoretical "minimum residual distance" from that cell to the last column
+ * of the final row. This minimum residual distance is zero when the
+ * untransformed portions of the strings are of equal length (because we might
+ * get lucky and find all the remaining characters matching) and is otherwise
+ * based on the minimum number of insertions or deletions needed to make them
+ * equal length. The residual distance grows as we move toward the upper
+ * right or lower left corners of the matrix. When the max_d bound is
+ * usefully tight, we can use this property to avoid computing the entirety
+ * of each row; instead, we maintain a start_column and stop_column that
+ * identify the portion of the matrix close to the diagonal which can still
+ * affect the final answer.
+ */
+static int
+#ifdef LEVENSHTEIN_LESS_EQUAL
+levenshtein_less_equal_internal(text *s, text *t,
+ int ins_c, int del_c, int sub_c, int max_d)
+#else
+levenshtein_internal(text *s, text *t,
+ int ins_c, int del_c, int sub_c)
+#endif
+{
+ int m,
+ n,
+ s_bytes,
+ t_bytes;
+ int *prev;
+ int *curr;
+ int *s_char_len = NULL;
+ int i,
+ j;
+ const char *s_data;
+ const char *t_data;
+ const char *y;
+
+ /*
+ * For levenshtein_less_equal_internal, we have real variables called
+ * start_column and stop_column; otherwise it's just short-hand for 0 and
+ * m.
+ */
+#ifdef LEVENSHTEIN_LESS_EQUAL
+ int start_column,
+ stop_column;
+
+#undef START_COLUMN
+#undef STOP_COLUMN
+#define START_COLUMN start_column
+#define STOP_COLUMN stop_column
+#else
+#undef START_COLUMN
+#undef STOP_COLUMN
+#define START_COLUMN 0
+#define STOP_COLUMN m
+#endif
+
+ /* Extract a pointer to the actual character data. */
+ s_data = VARDATA_ANY(s);
+ t_data = VARDATA_ANY(t);
+
+ /* Determine length of each string in bytes and characters. */
+ s_bytes = VARSIZE_ANY_EXHDR(s);
+ t_bytes = VARSIZE_ANY_EXHDR(t);
+ m = pg_mbstrlen_with_len(s_data, s_bytes);
+ n = pg_mbstrlen_with_len(t_data, t_bytes);
+
+ /*
+ * We can transform an empty s into t with n insertions, or a non-empty t
+ * into an empty s with m deletions.
+ */
+ if (!m)
+ return n * ins_c;
+ if (!n)
+ return m * del_c;
+
+ /*
+ * For security concerns, restrict excessive CPU+RAM usage. (This
+ * implementation uses O(m) memory and has O(mn) complexity.)
+ */
+ if (m > MAX_LEVENSHTEIN_STRLEN ||
+ n > MAX_LEVENSHTEIN_STRLEN)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("argument exceeds the maximum length of %d bytes",
+ MAX_LEVENSHTEIN_STRLEN)));
+
+#ifdef LEVENSHTEIN_LESS_EQUAL
+ /* Initialize start and stop columns. */
+ start_column = 0;
+ stop_column = m + 1;
+
+ /*
+ * If max_d >= 0, determine whether the bound is impossibly tight. If so,
+ * return max_d + 1 immediately. Otherwise, determine whether it's tight
+ * enough to limit the computation we must perform. If so, figure out
+ * initial stop column.
+ */
+ if (max_d >= 0)
+ {
+ int min_theo_d; /* Theoretical minimum distance. */
+ int max_theo_d; /* Theoretical maximum distance. */
+ int net_inserts = n - m;
+
+ min_theo_d = net_inserts < 0 ?
+ -net_inserts * del_c : net_inserts * ins_c;
+ if (min_theo_d > max_d)
+ return max_d + 1;
+ if (ins_c + del_c < sub_c)
+ sub_c = ins_c + del_c;
+ max_theo_d = min_theo_d + sub_c * Min(m, n);
+ if (max_d >= max_theo_d)
+ max_d = -1;
+ else if (ins_c + del_c > 0)
+ {
+ /*
+ * Figure out how much of the first row of the notional matrix we
+ * need to fill in. If the string is growing, the theoretical
+ * minimum distance already incorporates the cost of deleting the
+ * number of characters necessary to make the two strings equal in
+ * length. Each additional deletion forces another insertion, so
+ * the best-case total cost increases by ins_c + del_c. If the
+ * string is shrinking, the minimum theoretical cost assumes no
+ * excess deletions; that is, we're starting no futher right than
+ * column n - m. If we do start further right, the best-case
+ * total cost increases by ins_c + del_c for each move right.
+ */
+ int slack_d = max_d - min_theo_d;
+ int best_column = net_inserts < 0 ? -net_inserts : 0;
+
+ stop_column = best_column + (slack_d / (ins_c + del_c)) + 1;
+ if (stop_column > m)
+ stop_column = m + 1;
+ }
+ }
+#endif
+
+ /*
+ * In order to avoid calling pg_mblen() repeatedly on each character in s,
+ * we cache all the lengths before starting the main loop -- but if all
+ * the characters in both strings are single byte, then we skip this and
+ * use a fast-path in the main loop. If only one string contains
+ * multi-byte characters, we still build the array, so that the fast-path
+ * needn't deal with the case where the array hasn't been initialized.
+ */
+ if (m != s_bytes || n != t_bytes)
+ {
+ int i;
+ const char *cp = s_data;
+
+ s_char_len = (int *) palloc((m + 1) * sizeof(int));
+ for (i = 0; i < m; ++i)
+ {
+ s_char_len[i] = pg_mblen(cp);
+ cp += s_char_len[i];
+ }
+ s_char_len[i] = 0;
+ }
+
+ /* One more cell for initialization column and row. */
+ ++m;
+ ++n;
+
+ /* Previous and current rows of notional array. */
+ prev = (int *) palloc(2 * m * sizeof(int));
+ curr = prev + m;
+
+ /*
+ * To transform the first i characters of s into the first 0 characters of
+ * t, we must perform i deletions.
+ */
+ for (i = START_COLUMN; i < STOP_COLUMN; i++)
+ prev[i] = i * del_c;
+
+ /* Loop through rows of the notional array */
+ for (y = t_data, j = 1; j < n; j++)
+ {
+ int *temp;
+ const char *x = s_data;
+ int y_char_len = n != t_bytes + 1 ? pg_mblen(y) : 1;
+
+#ifdef LEVENSHTEIN_LESS_EQUAL
+
+ /*
+ * In the best case, values percolate down the diagonal unchanged, so
+ * we must increment stop_column unless it's already on the right end
+ * of the array. The inner loop will read prev[stop_column], so we
+ * have to initialize it even though it shouldn't affect the result.
+ */
+ if (stop_column < m)
+ {
+ prev[stop_column] = max_d + 1;
+ ++stop_column;
+ }
+
+ /*
+ * The main loop fills in curr, but curr[0] needs a special case: to
+ * transform the first 0 characters of s into the first j characters
+ * of t, we must perform j insertions. However, if start_column > 0,
+ * this special case does not apply.
+ */
+ if (start_column == 0)
+ {
+ curr[0] = j * ins_c;
+ i = 1;
+ }
+ else
+ i = start_column;
+#else
+ curr[0] = j * ins_c;
+ i = 1;
+#endif
+
+ /*
+ * This inner loop is critical to performance, so we include a
+ * fast-path to handle the (fairly common) case where no multibyte
+ * characters are in the mix. The fast-path is entitled to assume
+ * that if s_char_len is not initialized then BOTH strings contain
+ * only single-byte characters.
+ */
+ if (s_char_len != NULL)
+ {
+ for (; i < STOP_COLUMN; i++)
+ {
+ int ins;
+ int del;
+ int sub;
+ int x_char_len = s_char_len[i - 1];
+
+ /*
+ * Calculate costs for insertion, deletion, and substitution.
+ *
+ * When calculating cost for substitution, we compare the last
+ * character of each possibly-multibyte character first,
+ * because that's enough to rule out most mis-matches. If we
+ * get past that test, then we compare the lengths and the
+ * remaining bytes.
+ */
+ ins = prev[i] + ins_c;
+ del = curr[i - 1] + del_c;
+ if (x[x_char_len - 1] == y[y_char_len - 1]
+ && x_char_len == y_char_len &&
+ (x_char_len == 1 || rest_of_char_same(x, y, x_char_len)))
+ sub = prev[i - 1];
+ else
+ sub = prev[i - 1] + sub_c;
+
+ /* Take the one with minimum cost. */
+ curr[i] = Min(ins, del);
+ curr[i] = Min(curr[i], sub);
+
+ /* Point to next character. */
+ x += x_char_len;
+ }
+ }
+ else
+ {
+ for (; i < STOP_COLUMN; i++)
+ {
+ int ins;
+ int del;
+ int sub;
+
+ /* Calculate costs for insertion, deletion, and substitution. */
+ ins = prev[i] + ins_c;
+ del = curr[i - 1] + del_c;
+ sub = prev[i - 1] + ((*x == *y) ? 0 : sub_c);
+
+ /* Take the one with minimum cost. */
+ curr[i] = Min(ins, del);
+ curr[i] = Min(curr[i], sub);
+
+ /* Point to next character. */
+ x++;
+ }
+ }
+
+ /* Swap current row with previous row. */
+ temp = curr;
+ curr = prev;
+ prev = temp;
+
+ /* Point to next character. */
+ y += y_char_len;
+
+#ifdef LEVENSHTEIN_LESS_EQUAL
+
+ /*
+ * This chunk of code represents a significant performance hit if used
+ * in the case where there is no max_d bound. This is probably not
+ * because the max_d >= 0 test itself is expensive, but rather because
+ * the possibility of needing to execute this code prevents tight
+ * optimization of the loop as a whole.
+ */
+ if (max_d >= 0)
+ {
+ /*
+ * The "zero point" is the column of the current row where the
+ * remaining portions of the strings are of equal length. There
+ * are (n - 1) characters in the target string, of which j have
+ * been transformed. There are (m - 1) characters in the source
+ * string, so we want to find the value for zp where where (n - 1)
+ * - j = (m - 1) - zp.
+ */
+ int zp = j - (n - m);
+
+ /* Check whether the stop column can slide left. */
+ while (stop_column > 0)
+ {
+ int ii = stop_column - 1;
+ int net_inserts = ii - zp;
+
+ if (prev[ii] + (net_inserts > 0 ? net_inserts * ins_c :
+ -net_inserts * del_c) <= max_d)
+ break;
+ stop_column--;
+ }
+
+ /* Check whether the start column can slide right. */
+ while (start_column < stop_column)
+ {
+ int net_inserts = start_column - zp;
+
+ if (prev[start_column] +
+ (net_inserts > 0 ? net_inserts * ins_c :
+ -net_inserts * del_c) <= max_d)
+ break;
+
+ /*
+ * We'll never again update these values, so we must make sure
+ * there's nothing here that could confuse any future
+ * iteration of the outer loop.
+ */
+ prev[start_column] = max_d + 1;
+ curr[start_column] = max_d + 1;
+ if (start_column != 0)
+ s_data += (s_char_len != NULL) ? s_char_len[start_column - 1] : 1;
+ start_column++;
+ }
+
+ /* If they cross, we're going to exceed the bound. */
+ if (start_column >= stop_column)
+ return max_d + 1;
+ }
+#endif
+ }
+
+ /*
+ * Because the final value was swapped from the previous row to the
+ * current row, that's where we'll find it.
+ */
+ return prev[m - 1];
+}
diff --git a/contrib/fuzzystrmatch/uninstall_fuzzystrmatch.sql b/contrib/fuzzystrmatch/uninstall_fuzzystrmatch.sql
deleted file mode 100644
index bcf05da132..0000000000
--- a/contrib/fuzzystrmatch/uninstall_fuzzystrmatch.sql
+++ /dev/null
@@ -1,20 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/fuzzystrmatch/uninstall_fuzzystrmatch.sql,v 1.4 2008/04/03 21:13:07 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION dmetaphone_alt (text);
-
-DROP FUNCTION dmetaphone (text);
-
-DROP FUNCTION difference(text,text);
-
-DROP FUNCTION text_soundex(text);
-
-DROP FUNCTION soundex(text);
-
-DROP FUNCTION metaphone (text,int);
-
-DROP FUNCTION levenshtein (text,text,int,int,int);
-
-DROP FUNCTION levenshtein (text,text);
diff --git a/contrib/hstore/.gitignore b/contrib/hstore/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/hstore/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/hstore/Makefile b/contrib/hstore/Makefile
index bb69d70805..fce1a32328 100644
--- a/contrib/hstore/Makefile
+++ b/contrib/hstore/Makefile
@@ -1,15 +1,21 @@
-# $PostgreSQL: pgsql/contrib/hstore/Makefile,v 1.7 2009/09/30 19:50:22 tgl Exp $
-
-subdir = contrib/hstore
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
+# contrib/hstore/Makefile
MODULE_big = hstore
OBJS = hstore_io.o hstore_op.o hstore_gist.o hstore_gin.o hstore_compat.o \
crc32.o
-DATA_built = hstore.sql
-DATA = uninstall_hstore.sql
+EXTENSION = hstore
+DATA = hstore--1.0.sql hstore--unpackaged--1.0.sql
+
REGRESS = hstore
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/hstore
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/hstore/crc32.c b/contrib/hstore/crc32.c
index dc5765d056..d541d0cc95 100644
--- a/contrib/hstore/crc32.c
+++ b/contrib/hstore/crc32.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/crc32.c,v 1.4 2009/06/11 14:48:51 momjian Exp $
+ * contrib/hstore/crc32.c
*
* Both POSIX and CRC32 checksums */
diff --git a/contrib/hstore/crc32.h b/contrib/hstore/crc32.h
index e008b1a664..f5bfd82517 100644
--- a/contrib/hstore/crc32.h
+++ b/contrib/hstore/crc32.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/crc32.h,v 1.3 2009/06/11 14:48:51 momjian Exp $
+ * contrib/hstore/crc32.h
*/
#ifndef _CRC32_H
#define _CRC32_H
diff --git a/contrib/hstore/expected/hstore.out b/contrib/hstore/expected/hstore.out
index e78264d12b..083faf8d9c 100644
--- a/contrib/hstore/expected/hstore.out
+++ b/contrib/hstore/expected/hstore.out
@@ -1,12 +1,6 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of hstore.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-psql:hstore.sql:228: WARNING: => is deprecated as an operator name
+CREATE EXTENSION hstore;
+WARNING: => is deprecated as an operator name
DETAIL: This name may be disallowed altogether in future versions of PostgreSQL.
-RESET client_min_messages;
set escape_string_warning=off;
--hstore;
select ''::hstore;
@@ -207,25 +201,25 @@ select 'aa=>"NuLl"'::hstore;
"aa"=>"NuLl"
(1 row)
-select '\\=a=>q=w'::hstore;
+select e'\\=a=>q=w'::hstore;
hstore
-------------
"=a"=>"q=w"
(1 row)
-select '"=a"=>q\\=w'::hstore;
+select e'"=a"=>q\\=w'::hstore;
hstore
-------------
"=a"=>"q=w"
(1 row)
-select '"\\"a"=>q>w'::hstore;
+select e'"\\"a"=>q>w'::hstore;
hstore
--------------
"\"a"=>"q>w"
(1 row)
-select '\\"a=>q"w'::hstore;
+select e'\\"a=>q"w'::hstore;
hstore
---------------
"\"a"=>"q\"w"
@@ -435,10 +429,10 @@ select hstore 'a=>NULL, b=>qq' ?& ARRAY['c','d'];
select hstore 'a=>NULL, b=>qq' ?& '{}'::text[];
?column?
----------
- f
+ t
(1 row)
--- delete
+-- delete
select delete('a=>1 , b=>2, c=>3'::hstore, 'a');
delete
--------------------
diff --git a/contrib/hstore/hstore.sql.in b/contrib/hstore/hstore--1.0.sql
index c7a5e8e556..247a2773f5 100644
--- a/contrib/hstore/hstore.sql.in
+++ b/contrib/hstore/hstore--1.0.sql
@@ -1,26 +1,23 @@
-/* $PostgreSQL: pgsql/contrib/hstore/hstore.sql.in,v 1.15 2010/07/02 20:36:48 rhaas Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/hstore/hstore--1.0.sql */
CREATE TYPE hstore;
-CREATE OR REPLACE FUNCTION hstore_in(cstring)
+CREATE FUNCTION hstore_in(cstring)
RETURNS hstore
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_out(hstore)
+CREATE FUNCTION hstore_out(hstore)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_recv(internal)
+CREATE FUNCTION hstore_recv(internal)
RETURNS hstore
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_send(hstore)
+CREATE FUNCTION hstore_send(hstore)
RETURNS bytea
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -34,12 +31,12 @@ CREATE TYPE hstore (
STORAGE = extended
);
-CREATE OR REPLACE FUNCTION hstore_version_diag(hstore)
+CREATE FUNCTION hstore_version_diag(hstore)
RETURNS integer
AS 'MODULE_PATHNAME','hstore_version_diag'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION fetchval(hstore,text)
+CREATE FUNCTION fetchval(hstore,text)
RETURNS text
AS 'MODULE_PATHNAME','hstore_fetchval'
LANGUAGE C STRICT IMMUTABLE;
@@ -50,7 +47,7 @@ CREATE OPERATOR -> (
PROCEDURE = fetchval
);
-CREATE OR REPLACE FUNCTION slice_array(hstore,text[])
+CREATE FUNCTION slice_array(hstore,text[])
RETURNS text[]
AS 'MODULE_PATHNAME','hstore_slice_to_array'
LANGUAGE C STRICT IMMUTABLE;
@@ -61,17 +58,17 @@ CREATE OPERATOR -> (
PROCEDURE = slice_array
);
-CREATE OR REPLACE FUNCTION slice(hstore,text[])
+CREATE FUNCTION slice(hstore,text[])
RETURNS hstore
AS 'MODULE_PATHNAME','hstore_slice_to_hstore'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION isexists(hstore,text)
+CREATE FUNCTION isexists(hstore,text)
RETURNS bool
AS 'MODULE_PATHNAME','hstore_exists'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION exist(hstore,text)
+CREATE FUNCTION exist(hstore,text)
RETURNS bool
AS 'MODULE_PATHNAME','hstore_exists'
LANGUAGE C STRICT IMMUTABLE;
@@ -84,7 +81,7 @@ CREATE OPERATOR ? (
JOIN = contjoinsel
);
-CREATE OR REPLACE FUNCTION exists_any(hstore,text[])
+CREATE FUNCTION exists_any(hstore,text[])
RETURNS bool
AS 'MODULE_PATHNAME','hstore_exists_any'
LANGUAGE C STRICT IMMUTABLE;
@@ -97,7 +94,7 @@ CREATE OPERATOR ?| (
JOIN = contjoinsel
);
-CREATE OR REPLACE FUNCTION exists_all(hstore,text[])
+CREATE FUNCTION exists_all(hstore,text[])
RETURNS bool
AS 'MODULE_PATHNAME','hstore_exists_all'
LANGUAGE C STRICT IMMUTABLE;
@@ -110,27 +107,27 @@ CREATE OPERATOR ?& (
JOIN = contjoinsel
);
-CREATE OR REPLACE FUNCTION isdefined(hstore,text)
+CREATE FUNCTION isdefined(hstore,text)
RETURNS bool
AS 'MODULE_PATHNAME','hstore_defined'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION defined(hstore,text)
+CREATE FUNCTION defined(hstore,text)
RETURNS bool
AS 'MODULE_PATHNAME','hstore_defined'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION delete(hstore,text)
+CREATE FUNCTION delete(hstore,text)
RETURNS hstore
AS 'MODULE_PATHNAME','hstore_delete'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION delete(hstore,text[])
+CREATE FUNCTION delete(hstore,text[])
RETURNS hstore
AS 'MODULE_PATHNAME','hstore_delete_array'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION delete(hstore,hstore)
+CREATE FUNCTION delete(hstore,hstore)
RETURNS hstore
AS 'MODULE_PATHNAME','hstore_delete_hstore'
LANGUAGE C STRICT IMMUTABLE;
@@ -153,7 +150,7 @@ CREATE OPERATOR - (
PROCEDURE = delete
);
-CREATE OR REPLACE FUNCTION hs_concat(hstore,hstore)
+CREATE FUNCTION hs_concat(hstore,hstore)
RETURNS hstore
AS 'MODULE_PATHNAME','hstore_concat'
LANGUAGE C STRICT IMMUTABLE;
@@ -164,12 +161,12 @@ CREATE OPERATOR || (
PROCEDURE = hs_concat
);
-CREATE OR REPLACE FUNCTION hs_contains(hstore,hstore)
+CREATE FUNCTION hs_contains(hstore,hstore)
RETURNS bool
AS 'MODULE_PATHNAME','hstore_contains'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hs_contained(hstore,hstore)
+CREATE FUNCTION hs_contained(hstore,hstore)
RETURNS bool
AS 'MODULE_PATHNAME','hstore_contained'
LANGUAGE C STRICT IMMUTABLE;
@@ -211,12 +208,12 @@ CREATE OPERATOR ~ (
JOIN = contjoinsel
);
-CREATE OR REPLACE FUNCTION tconvert(text,text)
+CREATE FUNCTION tconvert(text,text)
RETURNS hstore
AS 'MODULE_PATHNAME','hstore_from_text'
LANGUAGE C IMMUTABLE; -- not STRICT; needs to allow (key,NULL)
-CREATE OR REPLACE FUNCTION hstore(text,text)
+CREATE FUNCTION hstore(text,text)
RETURNS hstore
AS 'MODULE_PATHNAME','hstore_from_text'
LANGUAGE C IMMUTABLE; -- not STRICT; needs to allow (key,NULL)
@@ -227,7 +224,7 @@ CREATE OPERATOR => (
PROCEDURE = hstore
);
-CREATE OR REPLACE FUNCTION hstore(text[],text[])
+CREATE FUNCTION hstore(text[],text[])
RETURNS hstore
AS 'MODULE_PATHNAME', 'hstore_from_arrays'
LANGUAGE C IMMUTABLE; -- not STRICT; allows (keys,null)
@@ -240,12 +237,12 @@ LANGUAGE C IMMUTABLE STRICT;
CREATE CAST (text[] AS hstore)
WITH FUNCTION hstore(text[]);
-CREATE OR REPLACE FUNCTION hstore(record)
+CREATE FUNCTION hstore(record)
RETURNS hstore
AS 'MODULE_PATHNAME', 'hstore_from_record'
LANGUAGE C IMMUTABLE; -- not STRICT; allows (null::recordtype)
-CREATE OR REPLACE FUNCTION hstore_to_array(hstore)
+CREATE FUNCTION hstore_to_array(hstore)
RETURNS text[]
AS 'MODULE_PATHNAME','hstore_to_array'
LANGUAGE C STRICT IMMUTABLE;
@@ -255,7 +252,7 @@ CREATE OPERATOR %% (
PROCEDURE = hstore_to_array
);
-CREATE OR REPLACE FUNCTION hstore_to_matrix(hstore)
+CREATE FUNCTION hstore_to_matrix(hstore)
RETURNS text[]
AS 'MODULE_PATHNAME','hstore_to_matrix'
LANGUAGE C STRICT IMMUTABLE;
@@ -265,34 +262,34 @@ CREATE OPERATOR %# (
PROCEDURE = hstore_to_matrix
);
-CREATE OR REPLACE FUNCTION akeys(hstore)
+CREATE FUNCTION akeys(hstore)
RETURNS text[]
AS 'MODULE_PATHNAME','hstore_akeys'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION avals(hstore)
+CREATE FUNCTION avals(hstore)
RETURNS text[]
AS 'MODULE_PATHNAME','hstore_avals'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION skeys(hstore)
+CREATE FUNCTION skeys(hstore)
RETURNS setof text
AS 'MODULE_PATHNAME','hstore_skeys'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION svals(hstore)
+CREATE FUNCTION svals(hstore)
RETURNS setof text
AS 'MODULE_PATHNAME','hstore_svals'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION each(IN hs hstore,
+CREATE FUNCTION each(IN hs hstore,
OUT key text,
OUT value text)
RETURNS SETOF record
AS 'MODULE_PATHNAME','hstore_each'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION populate_record(anyelement,hstore)
+CREATE FUNCTION populate_record(anyelement,hstore)
RETURNS anyelement
AS 'MODULE_PATHNAME', 'hstore_populate_record'
LANGUAGE C IMMUTABLE; -- not STRICT; allows (null::rectype,hstore)
@@ -305,37 +302,37 @@ CREATE OPERATOR #= (
-- btree support
-CREATE OR REPLACE FUNCTION hstore_eq(hstore,hstore)
+CREATE FUNCTION hstore_eq(hstore,hstore)
RETURNS boolean
AS 'MODULE_PATHNAME','hstore_eq'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_ne(hstore,hstore)
+CREATE FUNCTION hstore_ne(hstore,hstore)
RETURNS boolean
AS 'MODULE_PATHNAME','hstore_ne'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_gt(hstore,hstore)
+CREATE FUNCTION hstore_gt(hstore,hstore)
RETURNS boolean
AS 'MODULE_PATHNAME','hstore_gt'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_ge(hstore,hstore)
+CREATE FUNCTION hstore_ge(hstore,hstore)
RETURNS boolean
AS 'MODULE_PATHNAME','hstore_ge'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_lt(hstore,hstore)
+CREATE FUNCTION hstore_lt(hstore,hstore)
RETURNS boolean
AS 'MODULE_PATHNAME','hstore_lt'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_le(hstore,hstore)
+CREATE FUNCTION hstore_le(hstore,hstore)
RETURNS boolean
AS 'MODULE_PATHNAME','hstore_le'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION hstore_cmp(hstore,hstore)
+CREATE FUNCTION hstore_cmp(hstore,hstore)
RETURNS integer
AS 'MODULE_PATHNAME','hstore_cmp'
LANGUAGE C STRICT IMMUTABLE;
@@ -414,7 +411,7 @@ AS
-- hash support
-CREATE OR REPLACE FUNCTION hstore_hash(hstore)
+CREATE FUNCTION hstore_hash(hstore)
RETURNS integer
AS 'MODULE_PATHNAME','hstore_hash'
LANGUAGE C STRICT IMMUTABLE;
@@ -429,12 +426,12 @@ AS
CREATE TYPE ghstore;
-CREATE OR REPLACE FUNCTION ghstore_in(cstring)
+CREATE FUNCTION ghstore_in(cstring)
RETURNS ghstore
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ghstore_out(ghstore)
+CREATE FUNCTION ghstore_out(ghstore)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -445,37 +442,37 @@ CREATE TYPE ghstore (
OUTPUT = ghstore_out
);
-CREATE OR REPLACE FUNCTION ghstore_compress(internal)
+CREATE FUNCTION ghstore_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ghstore_decompress(internal)
+CREATE FUNCTION ghstore_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ghstore_penalty(internal,internal,internal)
+CREATE FUNCTION ghstore_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ghstore_picksplit(internal, internal)
+CREATE FUNCTION ghstore_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ghstore_union(internal, internal)
+CREATE FUNCTION ghstore_union(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ghstore_same(internal, internal, internal)
+CREATE FUNCTION ghstore_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ghstore_consistent(internal,internal,int,oid,internal)
+CREATE FUNCTION ghstore_consistent(internal,internal,int,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -501,17 +498,17 @@ AS
-- GIN support
-CREATE OR REPLACE FUNCTION gin_extract_hstore(internal, internal)
+CREATE FUNCTION gin_extract_hstore(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gin_extract_hstore_query(internal, internal, int2, internal, internal)
+CREATE FUNCTION gin_extract_hstore_query(internal, internal, int2, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gin_consistent_hstore(internal, int2, internal, int4, internal, internal)
+CREATE FUNCTION gin_consistent_hstore(internal, int2, internal, int4, internal, internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
diff --git a/contrib/hstore/hstore--unpackaged--1.0.sql b/contrib/hstore/hstore--unpackaged--1.0.sql
new file mode 100644
index 0000000000..0eb300ecf5
--- /dev/null
+++ b/contrib/hstore/hstore--unpackaged--1.0.sql
@@ -0,0 +1,89 @@
+/* contrib/hstore/hstore--unpackaged--1.0.sql */
+
+ALTER EXTENSION hstore ADD type hstore;
+ALTER EXTENSION hstore ADD function hstore_in(cstring);
+ALTER EXTENSION hstore ADD function hstore_out(hstore);
+ALTER EXTENSION hstore ADD function hstore_recv(internal);
+ALTER EXTENSION hstore ADD function hstore_send(hstore);
+ALTER EXTENSION hstore ADD function hstore_version_diag(hstore);
+ALTER EXTENSION hstore ADD function fetchval(hstore,text);
+ALTER EXTENSION hstore ADD operator ->(hstore,text);
+ALTER EXTENSION hstore ADD function slice_array(hstore,text[]);
+ALTER EXTENSION hstore ADD operator ->(hstore,text[]);
+ALTER EXTENSION hstore ADD function slice(hstore,text[]);
+ALTER EXTENSION hstore ADD function isexists(hstore,text);
+ALTER EXTENSION hstore ADD function exist(hstore,text);
+ALTER EXTENSION hstore ADD operator ?(hstore,text);
+ALTER EXTENSION hstore ADD function exists_any(hstore,text[]);
+ALTER EXTENSION hstore ADD operator ?|(hstore,text[]);
+ALTER EXTENSION hstore ADD function exists_all(hstore,text[]);
+ALTER EXTENSION hstore ADD operator ?&(hstore,text[]);
+ALTER EXTENSION hstore ADD function isdefined(hstore,text);
+ALTER EXTENSION hstore ADD function defined(hstore,text);
+ALTER EXTENSION hstore ADD function delete(hstore,text);
+ALTER EXTENSION hstore ADD function delete(hstore,text[]);
+ALTER EXTENSION hstore ADD function delete(hstore,hstore);
+ALTER EXTENSION hstore ADD operator -(hstore,text);
+ALTER EXTENSION hstore ADD operator -(hstore,text[]);
+ALTER EXTENSION hstore ADD operator -(hstore,hstore);
+ALTER EXTENSION hstore ADD function hs_concat(hstore,hstore);
+ALTER EXTENSION hstore ADD operator ||(hstore,hstore);
+ALTER EXTENSION hstore ADD function hs_contains(hstore,hstore);
+ALTER EXTENSION hstore ADD function hs_contained(hstore,hstore);
+ALTER EXTENSION hstore ADD operator <@(hstore,hstore);
+ALTER EXTENSION hstore ADD operator @>(hstore,hstore);
+ALTER EXTENSION hstore ADD operator ~(hstore,hstore);
+ALTER EXTENSION hstore ADD operator @(hstore,hstore);
+ALTER EXTENSION hstore ADD function tconvert(text,text);
+ALTER EXTENSION hstore ADD function hstore(text,text);
+ALTER EXTENSION hstore ADD operator =>(text,text);
+ALTER EXTENSION hstore ADD function hstore(text[],text[]);
+ALTER EXTENSION hstore ADD function hstore(text[]);
+ALTER EXTENSION hstore ADD cast (text[] as hstore);
+ALTER EXTENSION hstore ADD function hstore(record);
+ALTER EXTENSION hstore ADD function hstore_to_array(hstore);
+ALTER EXTENSION hstore ADD operator %%(NONE,hstore);
+ALTER EXTENSION hstore ADD function hstore_to_matrix(hstore);
+ALTER EXTENSION hstore ADD operator %#(NONE,hstore);
+ALTER EXTENSION hstore ADD function akeys(hstore);
+ALTER EXTENSION hstore ADD function avals(hstore);
+ALTER EXTENSION hstore ADD function skeys(hstore);
+ALTER EXTENSION hstore ADD function svals(hstore);
+ALTER EXTENSION hstore ADD function each(hstore);
+ALTER EXTENSION hstore ADD function populate_record(anyelement,hstore);
+ALTER EXTENSION hstore ADD operator #=(anyelement,hstore);
+ALTER EXTENSION hstore ADD function hstore_eq(hstore,hstore);
+ALTER EXTENSION hstore ADD function hstore_ne(hstore,hstore);
+ALTER EXTENSION hstore ADD function hstore_gt(hstore,hstore);
+ALTER EXTENSION hstore ADD function hstore_ge(hstore,hstore);
+ALTER EXTENSION hstore ADD function hstore_lt(hstore,hstore);
+ALTER EXTENSION hstore ADD function hstore_le(hstore,hstore);
+ALTER EXTENSION hstore ADD function hstore_cmp(hstore,hstore);
+ALTER EXTENSION hstore ADD operator <>(hstore,hstore);
+ALTER EXTENSION hstore ADD operator =(hstore,hstore);
+ALTER EXTENSION hstore ADD operator #>#(hstore,hstore);
+ALTER EXTENSION hstore ADD operator #>=#(hstore,hstore);
+ALTER EXTENSION hstore ADD operator #<#(hstore,hstore);
+ALTER EXTENSION hstore ADD operator #<=#(hstore,hstore);
+ALTER EXTENSION hstore ADD operator family btree_hstore_ops using btree;
+ALTER EXTENSION hstore ADD operator class btree_hstore_ops using btree;
+ALTER EXTENSION hstore ADD function hstore_hash(hstore);
+ALTER EXTENSION hstore ADD operator family hash_hstore_ops using hash;
+ALTER EXTENSION hstore ADD operator class hash_hstore_ops using hash;
+ALTER EXTENSION hstore ADD type ghstore;
+ALTER EXTENSION hstore ADD function ghstore_in(cstring);
+ALTER EXTENSION hstore ADD function ghstore_out(ghstore);
+ALTER EXTENSION hstore ADD function ghstore_compress(internal);
+ALTER EXTENSION hstore ADD function ghstore_decompress(internal);
+ALTER EXTENSION hstore ADD function ghstore_penalty(internal,internal,internal);
+ALTER EXTENSION hstore ADD function ghstore_picksplit(internal,internal);
+ALTER EXTENSION hstore ADD function ghstore_union(internal,internal);
+ALTER EXTENSION hstore ADD function ghstore_same(internal,internal,internal);
+ALTER EXTENSION hstore ADD function ghstore_consistent(internal,internal,integer,oid,internal);
+ALTER EXTENSION hstore ADD operator family gist_hstore_ops using gist;
+ALTER EXTENSION hstore ADD operator class gist_hstore_ops using gist;
+ALTER EXTENSION hstore ADD function gin_extract_hstore(internal,internal);
+ALTER EXTENSION hstore ADD function gin_extract_hstore_query(internal,internal,smallint,internal,internal);
+ALTER EXTENSION hstore ADD function gin_consistent_hstore(internal,smallint,internal,integer,internal,internal);
+ALTER EXTENSION hstore ADD operator family gin_hstore_ops using gin;
+ALTER EXTENSION hstore ADD operator class gin_hstore_ops using gin;
diff --git a/contrib/hstore/hstore.control b/contrib/hstore/hstore.control
new file mode 100644
index 0000000000..38a4851ea8
--- /dev/null
+++ b/contrib/hstore/hstore.control
@@ -0,0 +1,5 @@
+# hstore extension
+comment = 'data type for storing sets of (key, value) pairs'
+default_version = '1.0'
+module_pathname = '$libdir/hstore'
+relocatable = true
diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
index 796dce575e..8906397ad2 100644
--- a/contrib/hstore/hstore.h
+++ b/contrib/hstore/hstore.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/hstore.h,v 1.10 2010/02/26 02:00:32 momjian Exp $
+ * contrib/hstore/hstore.h
*/
#ifndef __HSTORE_H__
#define __HSTORE_H__
diff --git a/contrib/hstore/hstore_compat.c b/contrib/hstore/hstore_compat.c
index 033d945f9c..5778f74a80 100644
--- a/contrib/hstore/hstore_compat.c
+++ b/contrib/hstore/hstore_compat.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/hstore_compat.c,v 1.2 2010/02/26 02:00:32 momjian Exp $
+ * contrib/hstore/hstore_compat.c
*
* Notes on old/new hstore format disambiguation.
*
@@ -180,7 +180,8 @@ hstoreValidOldFormat(HStore *hs)
if (hs->size_ & HS_FLAG_NEWVERSION)
return 0;
- Assert(sizeof(HOldEntry) == sizeof(HEntry));
+ /* New format uses an HEntry for key and another for value */
+ Assert(sizeof(HOldEntry) == (2 * sizeof(HEntry)));
if (count == 0)
return 2;
diff --git a/contrib/hstore/hstore_gin.c b/contrib/hstore/hstore_gin.c
index f5056f53ec..2007801cf0 100644
--- a/contrib/hstore/hstore_gin.c
+++ b/contrib/hstore/hstore_gin.c
@@ -1,14 +1,22 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/hstore_gin.c,v 1.8 2010/02/26 02:00:32 momjian Exp $
+ * contrib/hstore/hstore_gin.c
*/
#include "postgres.h"
#include "access/gin.h"
+#include "access/skey.h"
#include "catalog/pg_type.h"
#include "hstore.h"
+/*
+ * When using a GIN index for hstore, we choose to index both keys and values.
+ * The storage format is "text" values, with K, V, or N prepended to the string
+ * to indicate key, value, or null values. (As of 9.1 it might be better to
+ * store null values as nulls, but we'll keep it this way for on-disk
+ * compatibility.)
+ */
#define KEYFLAG 'K'
#define VALFLAG 'V'
#define NULLFLAG 'N'
@@ -16,14 +24,17 @@
PG_FUNCTION_INFO_V1(gin_extract_hstore);
Datum gin_extract_hstore(PG_FUNCTION_ARGS);
+/* Build an indexable text value */
static text *
-makeitem(char *str, int len)
+makeitem(char *str, int len, char flag)
{
text *item;
item = (text *) palloc(VARHDRSZ + len + 1);
SET_VARSIZE(item, VARHDRSZ + len + 1);
+ *VARDATA(item) = flag;
+
if (str && len > 0)
memcpy(VARDATA(item) + 1, str, len);
@@ -49,20 +60,15 @@ gin_extract_hstore(PG_FUNCTION_ARGS)
{
text *item;
- item = makeitem(HS_KEY(hsent, ptr, i), HS_KEYLEN(hsent, i));
- *VARDATA(item) = KEYFLAG;
+ item = makeitem(HS_KEY(hsent, ptr, i), HS_KEYLEN(hsent, i),
+ KEYFLAG);
entries[2 * i] = PointerGetDatum(item);
if (HS_VALISNULL(hsent, i))
- {
- item = makeitem(NULL, 0);
- *VARDATA(item) = NULLFLAG;
- }
+ item = makeitem(NULL, 0, NULLFLAG);
else
- {
- item = makeitem(HS_VAL(hsent, ptr, i), HS_VALLEN(hsent, i));
- *VARDATA(item) = VALFLAG;
- }
+ item = makeitem(HS_VAL(hsent, ptr, i), HS_VALLEN(hsent, i),
+ VALFLAG);
entries[2 * i + 1] = PointerGetDatum(item);
}
@@ -75,30 +81,31 @@ Datum gin_extract_hstore_query(PG_FUNCTION_ARGS);
Datum
gin_extract_hstore_query(PG_FUNCTION_ARGS)
{
+ int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
StrategyNumber strategy = PG_GETARG_UINT16(2);
+ int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
+ Datum *entries;
if (strategy == HStoreContainsStrategyNumber)
{
- PG_RETURN_DATUM(DirectFunctionCall2(gin_extract_hstore,
- PG_GETARG_DATUM(0),
- PG_GETARG_DATUM(1)
- ));
+ /* Query is an hstore, so just apply gin_extract_hstore... */
+ entries = (Datum *)
+ DatumGetPointer(DirectFunctionCall2(gin_extract_hstore,
+ PG_GETARG_DATUM(0),
+ PointerGetDatum(nentries)));
+ /* ... except that "contains {}" requires a full index scan */
+ if (entries == NULL)
+ *searchMode = GIN_SEARCH_MODE_ALL;
}
else if (strategy == HStoreExistsStrategyNumber)
{
- text *item,
- *query = PG_GETARG_TEXT_PP(0);
- int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
- Datum *entries = NULL;
+ text *query = PG_GETARG_TEXT_PP(0);
+ text *item;
*nentries = 1;
entries = (Datum *) palloc(sizeof(Datum));
-
- item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
- *VARDATA(item) = KEYFLAG;
+ item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
entries[0] = PointerGetDatum(item);
-
- PG_RETURN_POINTER(entries);
}
else if (strategy == HStoreExistsAnyStrategyNumber ||
strategy == HStoreExistsAllStrategyNumber)
@@ -109,8 +116,6 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
int key_count;
int i,
j;
- int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
- Datum *entries = NULL;
text *item;
deconstruct_array(query,
@@ -121,21 +126,25 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
for (i = 0, j = 0; i < key_count; ++i)
{
+ /* Nulls in the array are ignored, cf hstoreArrayToPairs */
if (key_nulls[i])
continue;
- item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
- *VARDATA(item) = KEYFLAG;
+ item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG);
entries[j++] = PointerGetDatum(item);
}
- *nentries = j ? j : -1;
-
- PG_RETURN_POINTER(entries);
+ *nentries = j;
+ /* ExistsAll with no keys should match everything */
+ if (j == 0 && strategy == HStoreExistsAllStrategyNumber)
+ *searchMode = GIN_SEARCH_MODE_ALL;
}
else
- elog(ERROR, "Unsupported strategy number: %d", strategy);
+ {
+ elog(ERROR, "unrecognized strategy number: %d", strategy);
+ entries = NULL; /* keep compiler quiet */
+ }
- PG_RETURN_POINTER(NULL);
+ PG_RETURN_POINTER(entries);
}
PG_FUNCTION_INFO_V1(gin_consistent_hstore);
@@ -153,42 +162,52 @@ gin_consistent_hstore(PG_FUNCTION_ARGS)
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
bool *recheck = (bool *) PG_GETARG_POINTER(5);
bool res = true;
-
- *recheck = false;
+ int32 i;
if (strategy == HStoreContainsStrategyNumber)
{
- int i;
-
/*
- * Index lost information about correspondence of keys and values, so
- * we need recheck (pre-8.4 this is handled at SQL level)
+ * Index doesn't have information about correspondence of keys and
+ * values, so we need recheck. However, if not all the keys are
+ * present, we can fail at once.
*/
*recheck = true;
- for (i = 0; res && i < nkeys; i++)
- if (check[i] == false)
+ for (i = 0; i < nkeys; i++)
+ {
+ if (!check[i])
+ {
res = false;
+ break;
+ }
+ }
}
else if (strategy == HStoreExistsStrategyNumber)
{
- /* Existence of key is guaranteed */
+ /* Existence of key is guaranteed in default search mode */
+ *recheck = false;
res = true;
}
else if (strategy == HStoreExistsAnyStrategyNumber)
{
- /* Existence of key is guaranteed */
+ /* Existence of key is guaranteed in default search mode */
+ *recheck = false;
res = true;
}
else if (strategy == HStoreExistsAllStrategyNumber)
{
- int i;
-
- for (i = 0; res && i < nkeys; ++i)
+ /* Testing for all the keys being present gives an exact result */
+ *recheck = false;
+ for (i = 0; i < nkeys; i++)
+ {
if (!check[i])
+ {
res = false;
+ break;
+ }
+ }
}
else
- elog(ERROR, "Unsupported strategy number: %d", strategy);
+ elog(ERROR, "unrecognized strategy number: %d", strategy);
PG_RETURN_BOOL(res);
}
diff --git a/contrib/hstore/hstore_gist.c b/contrib/hstore/hstore_gist.c
index db58fb62dd..88d89ece23 100644
--- a/contrib/hstore/hstore_gist.c
+++ b/contrib/hstore/hstore_gist.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/hstore_gist.c,v 1.12 2010/02/26 02:00:32 momjian Exp $
+ * contrib/hstore/hstore_gist.c
*/
#include "postgres.h"
@@ -168,28 +168,14 @@ ghstore_compress(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(retval);
}
+/*
+ * Since type ghstore isn't toastable (and doesn't need to be),
+ * this function can be a no-op.
+ */
Datum
ghstore_decompress(PG_FUNCTION_ARGS)
{
- GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
- GISTENTRY *retval;
- HStore *key;
-
- key = DatumGetHStoreP(entry->key);
-
- if (key != (HStore *) DatumGetPointer(entry->key))
- {
- /* need to pass back the decompressed item */
- retval = palloc(sizeof(GISTENTRY));
- gistentryinit(*retval, PointerGetDatum(key),
- entry->rel, entry->page, entry->offset, entry->leafkey);
- PG_RETURN_POINTER(retval);
- }
- else
- {
- /* we can return the entry as-is */
- PG_RETURN_POINTER(entry);
- }
+ PG_RETURN_POINTER(PG_GETARG_POINTER(0));
}
Datum
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index fa6da693e9..0d6f0b6b13 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/hstore_io.c,v 1.13 2010/02/26 02:00:32 momjian Exp $
+ * contrib/hstore/hstore_io.c
*/
#include "postgres.h"
@@ -280,9 +280,9 @@ comparePairs(const void *a, const void *b)
{
if (((Pairs *) a)->keylen == ((Pairs *) b)->keylen)
{
- int res = strncmp(((Pairs *) a)->key,
- ((Pairs *) b)->key,
- ((Pairs *) a)->keylen);
+ int res = memcmp(((Pairs *) a)->key,
+ ((Pairs *) b)->key,
+ ((Pairs *) a)->keylen);
if (res)
return res;
@@ -324,7 +324,7 @@ hstoreUniquePairs(Pairs *a, int4 l, int4 *buflen)
while (ptr - a < l)
{
if (ptr->keylen == res->keylen &&
- strncmp(ptr->key, res->key, res->keylen) == 0)
+ memcmp(ptr->key, res->key, res->keylen) == 0)
{
if (ptr->needfree)
{
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index ebee60a1db..5b278c14ff 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/hstore/hstore_op.c,v 1.16 2010/02/26 02:00:32 momjian Exp $
+ * contrib/hstore/hstore_op.c
*/
#include "postgres.h"
@@ -49,7 +49,7 @@ hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen)
stopMiddle = stopLow + (stopHigh - stopLow) / 2;
if (HS_KEYLEN(entries, stopMiddle) == keylen)
- difference = strncmp(HS_KEY(entries, base, stopMiddle), key, keylen);
+ difference = memcmp(HS_KEY(entries, base, stopMiddle), key, keylen);
else
difference = (HS_KEYLEN(entries, stopMiddle) > keylen) ? 1 : -1;
@@ -168,14 +168,16 @@ hstore_exists_any(PG_FUNCTION_ARGS)
* start one entry past the previous "found" entry, or at the lower bound
* of the last search.
*/
-
- for (i = 0; !res && i < nkeys; ++i)
+ for (i = 0; i < nkeys; i++)
{
int idx = hstoreFindKey(hs, &lowbound,
key_pairs[i].key, key_pairs[i].keylen);
if (idx >= 0)
+ {
res = true;
+ break;
+ }
}
PG_RETURN_BOOL(res);
@@ -193,7 +195,7 @@ hstore_exists_all(PG_FUNCTION_ARGS)
Pairs *key_pairs = hstoreArrayToPairs(keys, &nkeys);
int i;
int lowbound = 0;
- bool res = nkeys ? true : false;
+ bool res = true;
/*
* we exploit the fact that the pairs list is already sorted into strictly
@@ -201,14 +203,16 @@ hstore_exists_all(PG_FUNCTION_ARGS)
* start one entry past the previous "found" entry, or at the lower bound
* of the last search.
*/
-
- for (i = 0; res && i < nkeys; ++i)
+ for (i = 0; i < nkeys; i++)
{
int idx = hstoreFindKey(hs, &lowbound,
key_pairs[i].key, key_pairs[i].keylen);
if (idx < 0)
+ {
res = false;
+ break;
+ }
}
PG_RETURN_BOOL(res);
@@ -263,7 +267,7 @@ hstore_delete(PG_FUNCTION_ARGS)
int len = HS_KEYLEN(es, i);
char *ptrs = HS_KEY(es, bufs, i);
- if (!(len == keylen && strncmp(ptrs, keyptr, keylen) == 0))
+ if (!(len == keylen && memcmp(ptrs, keyptr, keylen) == 0))
{
int vallen = HS_VALLEN(es, i);
@@ -331,9 +335,9 @@ hstore_delete_array(PG_FUNCTION_ARGS)
int skeylen = HS_KEYLEN(es, i);
if (skeylen == key_pairs[j].keylen)
- difference = strncmp(HS_KEY(es, ps, i),
- key_pairs[j].key,
- key_pairs[j].keylen);
+ difference = memcmp(HS_KEY(es, ps, i),
+ key_pairs[j].key,
+ key_pairs[j].keylen);
else
difference = (skeylen > key_pairs[j].keylen) ? 1 : -1;
}
@@ -416,9 +420,9 @@ hstore_delete_hstore(PG_FUNCTION_ARGS)
int s2keylen = HS_KEYLEN(es2, j);
if (skeylen == s2keylen)
- difference = strncmp(HS_KEY(es, ps, i),
- HS_KEY(es2, ps2, j),
- skeylen);
+ difference = memcmp(HS_KEY(es, ps, i),
+ HS_KEY(es2, ps2, j),
+ skeylen);
else
difference = (skeylen > s2keylen) ? 1 : -1;
}
@@ -433,7 +437,7 @@ hstore_delete_hstore(PG_FUNCTION_ARGS)
if (snullval != HS_VALISNULL(es2, j)
|| (!snullval
&& (svallen != HS_VALLEN(es2, j)
- || strncmp(HS_VAL(es, ps, i), HS_VAL(es2, ps2, j), svallen) != 0)))
+ || memcmp(HS_VAL(es, ps, i), HS_VAL(es2, ps2, j), svallen) != 0)))
{
HS_COPYITEM(ed, bufd, pd,
HS_KEY(es, ps, i), HS_KEYLEN(es, i),
@@ -526,9 +530,9 @@ hstore_concat(PG_FUNCTION_ARGS)
int s2keylen = HS_KEYLEN(es2, s2idx);
if (s1keylen == s2keylen)
- difference = strncmp(HS_KEY(es1, ps1, s1idx),
- HS_KEY(es2, ps2, s2idx),
- s1keylen);
+ difference = memcmp(HS_KEY(es1, ps1, s1idx),
+ HS_KEY(es2, ps2, s2idx),
+ s1keylen);
else
difference = (s1keylen > s2keylen) ? 1 : -1;
}
@@ -996,7 +1000,7 @@ hstore_contains(PG_FUNCTION_ARGS)
if (nullval != HS_VALISNULL(ve, idx)
|| (!nullval
&& (vallen != HS_VALLEN(ve, idx)
- || strncmp(HS_VAL(te, tstr, i), HS_VAL(ve, vstr, idx), vallen))))
+ || memcmp(HS_VAL(te, tstr, i), HS_VAL(ve, vstr, idx), vallen))))
res = false;
}
else
diff --git a/contrib/hstore/sql/hstore.sql b/contrib/hstore/sql/hstore.sql
index 8fefcbba93..fb6bb59f8a 100644
--- a/contrib/hstore/sql/hstore.sql
+++ b/contrib/hstore/sql/hstore.sql
@@ -1,12 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of hstore.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i hstore.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION hstore;
set escape_string_warning=off;
@@ -48,10 +40,10 @@ select 'aa=>null'::hstore;
select 'aa=>NuLl'::hstore;
select 'aa=>"NuLl"'::hstore;
-select '\\=a=>q=w'::hstore;
-select '"=a"=>q\\=w'::hstore;
-select '"\\"a"=>q>w'::hstore;
-select '\\"a=>q"w'::hstore;
+select e'\\=a=>q=w'::hstore;
+select e'"=a"=>q\\=w'::hstore;
+select e'"\\"a"=>q>w'::hstore;
+select e'\\"a=>q"w'::hstore;
select ''::hstore;
select ' '::hstore;
@@ -97,7 +89,7 @@ select hstore 'a=>NULL, b=>qq' ?& ARRAY['c','a'];
select hstore 'a=>NULL, b=>qq' ?& ARRAY['c','d'];
select hstore 'a=>NULL, b=>qq' ?& '{}'::text[];
--- delete
+-- delete
select delete('a=>1 , b=>2, c=>3'::hstore, 'a');
select delete('a=>null , b=>2, c=>3'::hstore, 'a');
diff --git a/contrib/hstore/uninstall_hstore.sql b/contrib/hstore/uninstall_hstore.sql
deleted file mode 100644
index ca2b05aa83..0000000000
--- a/contrib/hstore/uninstall_hstore.sql
+++ /dev/null
@@ -1,86 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/hstore/uninstall_hstore.sql,v 1.11 2010/07/02 20:36:48 rhaas Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR CLASS gist_hstore_ops USING gist CASCADE;
-DROP OPERATOR CLASS gin_hstore_ops USING gin CASCADE;
-DROP OPERATOR CLASS hash_hstore_ops USING hash CASCADE;
-DROP OPERATOR CLASS btree_hstore_ops USING btree CASCADE;
-
-DROP OPERATOR - ( hstore, text );
-DROP OPERATOR - ( hstore, text[] );
-DROP OPERATOR - ( hstore, hstore );
-DROP OPERATOR ? ( hstore, text );
-DROP OPERATOR ?& ( hstore, text[] );
-DROP OPERATOR ?| ( hstore, text[] );
-DROP OPERATOR -> ( hstore, text );
-DROP OPERATOR -> ( hstore, text[] );
-DROP OPERATOR || ( hstore, hstore );
-DROP OPERATOR @> ( hstore, hstore );
-DROP OPERATOR <@ ( hstore, hstore );
-DROP OPERATOR @ ( hstore, hstore );
-DROP OPERATOR ~ ( hstore, hstore );
-DROP OPERATOR => ( text, text );
-DROP OPERATOR #= ( anyelement, hstore );
-DROP OPERATOR %% ( NONE, hstore );
-DROP OPERATOR %# ( NONE, hstore );
-DROP OPERATOR = ( hstore, hstore );
-DROP OPERATOR <> ( hstore, hstore );
-DROP OPERATOR #<# ( hstore, hstore );
-DROP OPERATOR #<=# ( hstore, hstore );
-DROP OPERATOR #># ( hstore, hstore );
-DROP OPERATOR #>=# ( hstore, hstore );
-
-DROP CAST (text[] AS hstore);
-
-DROP FUNCTION hstore_eq(hstore,hstore);
-DROP FUNCTION hstore_ne(hstore,hstore);
-DROP FUNCTION hstore_gt(hstore,hstore);
-DROP FUNCTION hstore_ge(hstore,hstore);
-DROP FUNCTION hstore_lt(hstore,hstore);
-DROP FUNCTION hstore_le(hstore,hstore);
-DROP FUNCTION hstore_cmp(hstore,hstore);
-DROP FUNCTION hstore_hash(hstore);
-DROP FUNCTION slice_array(hstore,text[]);
-DROP FUNCTION slice(hstore,text[]);
-DROP FUNCTION fetchval(hstore,text);
-DROP FUNCTION isexists(hstore,text);
-DROP FUNCTION exist(hstore,text);
-DROP FUNCTION exists_any(hstore,text[]);
-DROP FUNCTION exists_all(hstore,text[]);
-DROP FUNCTION isdefined(hstore,text);
-DROP FUNCTION defined(hstore,text);
-DROP FUNCTION delete(hstore,text);
-DROP FUNCTION delete(hstore,text[]);
-DROP FUNCTION delete(hstore,hstore);
-DROP FUNCTION hs_concat(hstore,hstore);
-DROP FUNCTION hs_contains(hstore,hstore);
-DROP FUNCTION hs_contained(hstore,hstore);
-DROP FUNCTION tconvert(text,text);
-DROP FUNCTION hstore(text,text);
-DROP FUNCTION hstore(text[],text[]);
-DROP FUNCTION hstore_to_array(hstore);
-DROP FUNCTION hstore_to_matrix(hstore);
-DROP FUNCTION hstore(record);
-DROP FUNCTION hstore(text[]);
-DROP FUNCTION akeys(hstore);
-DROP FUNCTION avals(hstore);
-DROP FUNCTION skeys(hstore);
-DROP FUNCTION svals(hstore);
-DROP FUNCTION each(hstore);
-DROP FUNCTION populate_record(anyelement,hstore);
-DROP FUNCTION ghstore_compress(internal);
-DROP FUNCTION ghstore_decompress(internal);
-DROP FUNCTION ghstore_penalty(internal,internal,internal);
-DROP FUNCTION ghstore_picksplit(internal, internal);
-DROP FUNCTION ghstore_union(internal, internal);
-DROP FUNCTION ghstore_same(internal, internal, internal);
-DROP FUNCTION ghstore_consistent(internal,internal,int,oid,internal);
-DROP FUNCTION gin_consistent_hstore(internal, int2, internal, int4, internal, internal);
-DROP FUNCTION gin_extract_hstore(internal, internal);
-DROP FUNCTION gin_extract_hstore_query(internal, internal, smallint, internal, internal);
-DROP FUNCTION hstore_version_diag(hstore);
-
-DROP TYPE hstore CASCADE;
-DROP TYPE ghstore CASCADE;
diff --git a/contrib/intagg/Makefile b/contrib/intagg/Makefile
index 73ce7e4173..2cfe9978e2 100644
--- a/contrib/intagg/Makefile
+++ b/contrib/intagg/Makefile
@@ -1,6 +1,7 @@
-# $PostgreSQL: pgsql/contrib/intagg/Makefile,v 1.11 2010/02/05 03:06:30 momjian Exp $
+# contrib/intagg/Makefile
-DATA = int_aggregate.sql uninstall_int_aggregate.sql
+EXTENSION = intagg
+DATA = intagg--1.0.sql intagg--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/intagg/int_aggregate.sql b/contrib/intagg/intagg--1.0.sql
index 7ed7c5ddd2..19a57c079b 100644
--- a/contrib/intagg/int_aggregate.sql
+++ b/contrib/intagg/intagg--1.0.sql
@@ -1,18 +1,15 @@
-/* $PostgreSQL: pgsql/contrib/intagg/int_aggregate.sql,v 1.1 2008/11/14 19:58:45 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/intagg/intagg--1.0.sql */
-- Internal function for the aggregate
-- Is called for each item in an aggregation
-CREATE OR REPLACE FUNCTION int_agg_state (internal, int4)
+CREATE FUNCTION int_agg_state (internal, int4)
RETURNS internal
AS 'array_agg_transfn'
LANGUAGE INTERNAL;
-- Internal function for the aggregate
-- Is called at the end of the aggregation, and returns an array.
-CREATE OR REPLACE FUNCTION int_agg_final_array (internal)
+CREATE FUNCTION int_agg_final_array (internal)
RETURNS int4[]
AS 'array_agg_finalfn'
LANGUAGE INTERNAL;
@@ -29,7 +26,7 @@ CREATE AGGREGATE int_array_aggregate (
-- The enumeration function
-- returns each element in a one dimensional integer array
-- as a row.
-CREATE OR REPLACE FUNCTION int_array_enum(int4[])
+CREATE FUNCTION int_array_enum(int4[])
RETURNS setof integer
AS 'array_unnest'
LANGUAGE INTERNAL IMMUTABLE STRICT;
diff --git a/contrib/intagg/intagg--unpackaged--1.0.sql b/contrib/intagg/intagg--unpackaged--1.0.sql
new file mode 100644
index 0000000000..95238d9c67
--- /dev/null
+++ b/contrib/intagg/intagg--unpackaged--1.0.sql
@@ -0,0 +1,6 @@
+/* contrib/intagg/intagg--unpackaged--1.0.sql */
+
+ALTER EXTENSION intagg ADD function int_agg_state(internal,integer);
+ALTER EXTENSION intagg ADD function int_agg_final_array(internal);
+ALTER EXTENSION intagg ADD function int_array_aggregate(integer);
+ALTER EXTENSION intagg ADD function int_array_enum(integer[]);
diff --git a/contrib/intagg/intagg.control b/contrib/intagg/intagg.control
new file mode 100644
index 0000000000..f11fb11940
--- /dev/null
+++ b/contrib/intagg/intagg.control
@@ -0,0 +1,4 @@
+# intagg extension
+comment = 'integer aggregator and enumerator (obsolete)'
+default_version = '1.0'
+relocatable = true
diff --git a/contrib/intagg/uninstall_int_aggregate.sql b/contrib/intagg/uninstall_int_aggregate.sql
deleted file mode 100644
index fe0f4c7df4..0000000000
--- a/contrib/intagg/uninstall_int_aggregate.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/intagg/uninstall_int_aggregate.sql,v 1.4 2008/11/14 19:58:45 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION int_array_enum(int4[]);
-
-DROP AGGREGATE int_array_aggregate (int4);
-
-DROP FUNCTION int_agg_final_array (internal);
-
-DROP FUNCTION int_agg_state (internal, int4);
diff --git a/contrib/intarray/.gitignore b/contrib/intarray/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/intarray/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/intarray/Makefile b/contrib/intarray/Makefile
index 09d7cb0bb5..71f820ec4a 100644
--- a/contrib/intarray/Makefile
+++ b/contrib/intarray/Makefile
@@ -1,9 +1,11 @@
-# $PostgreSQL: pgsql/contrib/intarray/Makefile,v 1.16 2007/11/10 23:59:51 momjian Exp $
+# contrib/intarray/Makefile
MODULE_big = _int
-OBJS = _int_bool.o _int_gist.o _int_op.o _int_tool.o _intbig_gist.o _int_gin.o
-DATA_built = _int.sql
-DATA = uninstall__int.sql
+OBJS = _int_bool.o _int_gist.o _int_op.o _int_tool.o _intbig_gist.o _int_gin.o
+
+EXTENSION = intarray
+DATA = intarray--1.0.sql intarray--unpackaged--1.0.sql
+
REGRESS = _int
ifdef USE_PGXS
diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
index 35dbb54796..11c069890e 100644
--- a/contrib/intarray/_int.h
+++ b/contrib/intarray/_int.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/intarray/_int.h,v 1.17 2009/06/11 14:48:51 momjian Exp $
+ * contrib/intarray/_int.h
*/
#ifndef ___INT_H__
#define ___INT_H__
@@ -9,41 +9,36 @@
/* number ranges for compression */
#define MAXNUMRANGE 100
-/* dimension of array */
-#define NDIM 1
-
/* useful macros for accessing int4 arrays */
#define ARRPTR(x) ( (int4 *) ARR_DATA_PTR(x) )
#define ARRNELEMS(x) ArrayGetNItems(ARR_NDIM(x), ARR_DIMS(x))
-/* reject arrays we can't handle; but allow a NULL or empty array */
+/* reject arrays we can't handle; to wit, those containing nulls */
#define CHECKARRVALID(x) \
do { \
- if (x) { \
- if (ARR_NDIM(x) != NDIM && ARR_NDIM(x) != 0) \
- ereport(ERROR, \
- (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
- errmsg("array must be one-dimensional"))); \
- if (ARR_HASNULL(x)) \
- ereport(ERROR, \
- (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
- errmsg("array must not contain nulls"))); \
- } \
+ if (ARR_HASNULL(x) && array_contains_nulls(x)) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
+ errmsg("array must not contain nulls"))); \
} while(0)
-#define ARRISVOID(x) ((x) == NULL || ARRNELEMS(x) == 0)
+#define ARRISEMPTY(x) (ARRNELEMS(x) == 0)
+/* sort the elements of the array */
#define SORT(x) \
do { \
- if ( ARRNELEMS( x ) > 1 ) \
- isort( ARRPTR( x ), ARRNELEMS( x ) ); \
+ int _nelems_ = ARRNELEMS(x); \
+ if (_nelems_ > 1) \
+ isort(ARRPTR(x), _nelems_); \
} while(0)
+/* sort the elements of the array and remove duplicates */
#define PREPAREARR(x) \
do { \
- if ( ARRNELEMS( x ) > 1 ) \
- if ( isort( ARRPTR( x ), ARRNELEMS( x ) ) ) \
- x = _int_unique( x ); \
+ int _nelems_ = ARRNELEMS(x); \
+ if (_nelems_ > 1) \
+ if (isort(ARRPTR(x), _nelems_)) \
+ (x) = _int_unique(x); \
} while(0)
/* "wish" function */
@@ -90,14 +85,14 @@ typedef struct
#define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) )
/*
-** types for functions
-*/
+ * types for functions
+ */
typedef ArrayType *(*formarray) (ArrayType *, ArrayType *);
typedef void (*formfloat) (ArrayType *, float *);
/*
-** useful function
-*/
+ * useful functions
+ */
bool isort(int4 *a, int len);
ArrayType *new_intArrayType(int num);
ArrayType *copy_intArrayType(ArrayType *a);
@@ -133,17 +128,18 @@ typedef struct ITEM
int4 val;
} ITEM;
-typedef struct
+typedef struct QUERYTYPE
{
int32 vl_len_; /* varlena header (do not touch directly!) */
- int4 size;
- char data[1];
+ int4 size; /* number of ITEMs */
+ ITEM items[1]; /* variable length array */
} QUERYTYPE;
-#define HDRSIZEQT (VARHDRSZ + sizeof(int4))
-#define COMPUTESIZE(size) ( HDRSIZEQT + size * sizeof(ITEM) )
-#define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
+#define HDRSIZEQT offsetof(QUERYTYPE, items)
+#define COMPUTESIZE(size) ( HDRSIZEQT + (size) * sizeof(ITEM) )
+#define GETQUERY(x) ( (x)->items )
+/* "type" codes for ITEM */
#define END 0
#define ERR 1
#define VAL 2
@@ -151,18 +147,28 @@ typedef struct
#define OPEN 4
#define CLOSE 5
+/* fmgr macros for QUERYTYPE objects */
+#define DatumGetQueryTypeP(X) ((QUERYTYPE *) PG_DETOAST_DATUM(X))
+#define DatumGetQueryTypePCopy(X) ((QUERYTYPE *) PG_DETOAST_DATUM_COPY(X))
+#define PG_GETARG_QUERYTYPE_P(n) DatumGetQueryTypeP(PG_GETARG_DATUM(n))
+#define PG_GETARG_QUERYTYPE_P_COPY(n) DatumGetQueryTypePCopy(PG_GETARG_DATUM(n))
+
bool signconsistent(QUERYTYPE *query, BITVEC sign, bool calcnot);
bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot);
-bool ginconsistent(QUERYTYPE *query, bool *check);
-int4 shorterquery(ITEM *q, int4 len);
-int compASC(const void *a, const void *b);
+bool gin_bool_consistent(QUERYTYPE *query, bool *check);
+bool query_has_required_values(QUERYTYPE *query);
+int compASC(const void *a, const void *b);
int compDESC(const void *a, const void *b);
-#define QSORT(a, direction) \
-if (ARRNELEMS(a) > 1) \
- qsort((void*)ARRPTR(a), ARRNELEMS(a),sizeof(int4), \
- (direction) ? compASC : compDESC )
+/* sort, either ascending or descending */
+#define QSORT(a, direction) \
+ do { \
+ int _nelems_ = ARRNELEMS(a); \
+ if (_nelems_ > 1) \
+ qsort((void*) ARRPTR(a), _nelems_, sizeof(int4), \
+ (direction) ? compASC : compDESC ); \
+ } while(0)
#endif /* ___INT_H__ */
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 438db2ca95..4e63f6d66c 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -1,8 +1,9 @@
/*
- * $PostgreSQL: pgsql/contrib/intarray/_int_bool.c,v 1.16 2009/06/11 14:48:51 momjian Exp $
+ * contrib/intarray/_int_bool.c
*/
#include "postgres.h"
+#include "miscadmin.h"
#include "utils/builtins.h"
#include "_int.h"
@@ -22,13 +23,6 @@ PG_FUNCTION_INFO_V1(querytree);
Datum querytree(PG_FUNCTION_ARGS);
-#define END 0
-#define ERR 1
-#define VAL 2
-#define OPR 3
-#define OPEN 4
-#define CLOSE 5
-
/* parser's states */
#define WAITOPERAND 1
#define WAITENDOPERAND 2
@@ -62,24 +56,25 @@ typedef struct
static int4
gettoken(WORKSTATE *state, int4 *val)
{
- char nnn[16],
- *curnnn;
+ char nnn[16];
+ int innn;
*val = 0; /* default result */
- curnnn = nnn;
+ innn = 0;
while (1)
{
+ if (innn >= sizeof(nnn))
+ return ERR; /* buffer overrun => syntax error */
switch (state->state)
{
case WAITOPERAND:
- curnnn = nnn;
+ innn = 0;
if ((*(state->buf) >= '0' && *(state->buf) <= '9') ||
*(state->buf) == '-')
{
state->state = WAITENDOPERAND;
- *curnnn = *(state->buf);
- curnnn++;
+ nnn[innn++] = *(state->buf);
}
else if (*(state->buf) == '!')
{
@@ -99,13 +94,18 @@ gettoken(WORKSTATE *state, int4 *val)
case WAITENDOPERAND:
if (*(state->buf) >= '0' && *(state->buf) <= '9')
{
- *curnnn = *(state->buf);
- curnnn++;
+ nnn[innn++] = *(state->buf);
}
else
{
- *curnnn = '\0';
- *val = (int4) atoi(nnn);
+ long lval;
+
+ nnn[innn] = '\0';
+ errno = 0;
+ lval = strtol(nnn, NULL, 0);
+ *val = (int4) lval;
+ if (errno != 0 || (long) *val != lval)
+ return ERR;
state->state = WAITOPERATOR;
return (state->count && *(state->buf) == '\0')
? ERR : VAL;
@@ -167,6 +167,9 @@ makepol(WORKSTATE *state)
int4 stack[STACKDEPTH];
int4 lenstack = 0;
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
while ((type = gettoken(state, &val)) != END)
{
switch (type)
@@ -196,8 +199,8 @@ makepol(WORKSTATE *state)
case OPEN:
if (makepol(state) == ERR)
return ERR;
- if (lenstack && (stack[lenstack - 1] == (int4) '&' ||
- stack[lenstack - 1] == (int4) '!'))
+ while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
+ stack[lenstack - 1] == (int4) '!'))
{
lenstack--;
pushquery(state, OPR, stack[lenstack]);
@@ -236,7 +239,7 @@ typedef struct
} CHKVAL;
/*
- * is there value 'val' in array or not ?
+ * is there value 'val' in (sorted) array or not ?
*/
static bool
checkcondition_arr(void *checkval, ITEM *item)
@@ -267,11 +270,14 @@ checkcondition_bit(void *checkval, ITEM *item)
}
/*
- * check for boolean condition
+ * evaluate boolean expression, using chkcond() to test the primitive cases
*/
static bool
-execute(ITEM *curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM *item))
+execute(ITEM *curitem, void *checkval, bool calcnot,
+ bool (*chkcond) (void *checkval, ITEM *item))
{
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
if (curitem->type == VAL)
return (*chkcond) (checkval, curitem);
@@ -304,13 +310,12 @@ execute(ITEM *curitem, void *checkval, bool calcnot, bool (*chkcond) (void *chec
bool
signconsistent(QUERYTYPE *query, BITVEC sign, bool calcnot)
{
- return execute(
- GETQUERY(query) + query->size - 1,
+ return execute(GETQUERY(query) + query->size - 1,
(void *) sign, calcnot,
- checkcondition_bit
- );
+ checkcondition_bit);
}
+/* Array must be sorted! */
bool
execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
{
@@ -319,11 +324,9 @@ execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
CHECKARRVALID(array);
chkval.arrb = ARRPTR(array);
chkval.arre = chkval.arrb + ARRNELEMS(array);
- return execute(
- GETQUERY(query) + query->size - 1,
+ return execute(GETQUERY(query) + query->size - 1,
(void *) &chkval, calcnot,
- checkcondition_arr
- );
+ checkcondition_arr);
}
typedef struct
@@ -341,27 +344,75 @@ checkcondition_gin(void *checkval, ITEM *item)
}
bool
-ginconsistent(QUERYTYPE *query, bool *check)
+gin_bool_consistent(QUERYTYPE *query, bool *check)
{
GinChkVal gcv;
ITEM *items = GETQUERY(query);
int i,
j = 0;
- if (query->size < 0)
+ if (query->size <= 0)
return FALSE;
+ /*
+ * Set up data for checkcondition_gin. This must agree with the query
+ * extraction code in ginint4_queryextract.
+ */
gcv.first = items;
gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
for (i = 0; i < query->size; i++)
+ {
if (items[i].type == VAL)
gcv.mapped_check[i] = check[j++];
+ }
- return execute(
- GETQUERY(query) + query->size - 1,
+ return execute(GETQUERY(query) + query->size - 1,
(void *) &gcv, true,
- checkcondition_gin
- );
+ checkcondition_gin);
+}
+
+static bool
+contains_required_value(ITEM *curitem)
+{
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
+ if (curitem->type == VAL)
+ return true;
+ else if (curitem->val == (int4) '!')
+ {
+ /*
+ * Assume anything under a NOT is non-required. For some cases with
+ * nested NOTs, we could prove there's a required value, but it seems
+ * unlikely to be worth the trouble.
+ */
+ return false;
+ }
+ else if (curitem->val == (int4) '&')
+ {
+ /* If either side has a required value, we're good */
+ if (contains_required_value(curitem + curitem->left))
+ return true;
+ else
+ return contains_required_value(curitem - 1);
+ }
+ else
+ { /* |-operator */
+ /* Both sides must have required values */
+ if (contains_required_value(curitem + curitem->left))
+ return contains_required_value(curitem - 1);
+ else
+ return false;
+ }
+ return false;
+}
+
+bool
+query_has_required_values(QUERYTYPE *query)
+{
+ if (query->size <= 0)
+ return false;
+ return contains_required_value(GETQUERY(query) + query->size - 1);
}
/*
@@ -370,37 +421,27 @@ ginconsistent(QUERYTYPE *query, bool *check)
Datum
rboolop(PG_FUNCTION_ARGS)
{
- return DirectFunctionCall2(
- boolop,
+ /* just reverse the operands */
+ return DirectFunctionCall2(boolop,
PG_GETARG_DATUM(1),
- PG_GETARG_DATUM(0)
- );
+ PG_GETARG_DATUM(0));
}
Datum
boolop(PG_FUNCTION_ARGS)
{
- ArrayType *val = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
+ ArrayType *val = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(1);
CHKVAL chkval;
bool result;
CHECKARRVALID(val);
- if (ARRISVOID(val))
- {
- pfree(val);
- PG_FREE_IF_COPY(query, 1);
- PG_RETURN_BOOL(false);
- }
-
PREPAREARR(val);
chkval.arrb = ARRPTR(val);
chkval.arre = chkval.arrb + ARRNELEMS(val);
- result = execute(
- GETQUERY(query) + query->size - 1,
+ result = execute(GETQUERY(query) + query->size - 1,
&chkval, true,
- checkcondition_arr
- );
+ checkcondition_arr);
pfree(val);
PG_FREE_IF_COPY(query, 1);
@@ -599,7 +640,7 @@ infix(INFIX *in, bool first)
Datum
bqarr_out(PG_FUNCTION_ARGS)
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
INFIX nrm;
if (query->size == 0)
@@ -617,173 +658,11 @@ bqarr_out(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(nrm.buf);
}
-static int4
-countdroptree(ITEM *q, int4 pos)
-{
- if (q[pos].type == VAL)
- return 1;
- else if (q[pos].val == (int4) '!')
- return 1 + countdroptree(q, pos - 1);
- else
- return 1 + countdroptree(q, pos - 1) + countdroptree(q, pos + q[pos].left);
-}
-
-/*
- * common algorithm:
- * result of all '!' will be = 'true', so
- * we can modify query tree for clearing
- */
-int4
-shorterquery(ITEM *q, int4 len)
-{
- int4 index,
- posnot,
- poscor;
- bool notisleft = false;
- int4 drop,
- i;
-
- /* out all '!' */
- do
- {
- index = 0;
- drop = 0;
- /* find ! */
- for (posnot = 0; posnot < len; posnot++)
- if (q[posnot].type == OPR && q[posnot].val == (int4) '!')
- {
- index = 1;
- break;
- }
-
- if (posnot == len)
- return len;
-
- /* last operator is ! */
- if (posnot == len - 1)
- return 0;
-
- /* find operator for this operand */
- for (poscor = posnot + 1; poscor < len; poscor++)
- {
- if (q[poscor].type == OPR)
- {
- if (poscor == posnot + 1)
- {
- notisleft = false;
- break;
- }
- else if (q[poscor].left + poscor == posnot)
- {
- notisleft = true;
- break;
- }
- }
- }
- if (q[poscor].val == (int4) '!')
- {
- drop = countdroptree(q, poscor);
- q[poscor - 1].type = VAL;
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i <= poscor)
- q[i].left += drop - 2;
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[poscor - 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- len -= drop - 2;
- }
- else if (q[poscor].val == (int4) '|')
- {
- drop = countdroptree(q, poscor);
- q[poscor - 1].type = VAL;
- q[poscor].val = (int4) '!';
- q[poscor].left = -1;
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i < poscor)
- q[i].left += drop - 2;
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[poscor - 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- len -= drop - 2;
- }
- else
- { /* &-operator */
- if (
- (notisleft && q[poscor - 1].type == OPR &&
- q[poscor - 1].val == (int4) '!') ||
- (!notisleft && q[poscor + q[poscor].left].type == OPR &&
- q[poscor + q[poscor].left].val == (int4) '!')
- )
- { /* drop subtree */
- drop = countdroptree(q, poscor);
- q[poscor - 1].type = VAL;
- q[poscor].val = (int4) '!';
- q[poscor].left = -1;
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i < poscor)
- q[i].left += drop - 2;
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[poscor - 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- len -= drop - 2;
- }
- else
- { /* drop only operator */
- int4 subtreepos = (notisleft) ?
- poscor - 1 : poscor + q[poscor].left;
- int4 subtreelen = countdroptree(q, subtreepos);
-
- drop = countdroptree(q, poscor);
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i < poscor)
- q[i].left += drop - subtreelen;
- memcpy((void *) &q[subtreepos + 1],
- (void *) &q[poscor + 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[subtreepos - subtreelen + 1],
- sizeof(ITEM) * (len - (drop - subtreelen)));
- len -= drop - subtreelen;
- }
- }
- } while (index);
- return len;
-}
-
+/* Useless old "debugging" function for a fundamentally wrong algorithm */
Datum
querytree(PG_FUNCTION_ARGS)
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
- INFIX nrm;
- text *res;
- ITEM *q;
- int4 len;
-
- if (query->size == 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("empty query")));
-
- q = (ITEM *) palloc(sizeof(ITEM) * query->size);
- memcpy((void *) q, GETQUERY(query), sizeof(ITEM) * query->size);
- len = shorterquery(q, query->size);
- PG_FREE_IF_COPY(query, 0);
-
- if (len == 0)
- {
- res = cstring_to_text("T");
- }
- else
- {
- nrm.curpol = q + len - 1;
- nrm.buflen = 32;
- nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
- *(nrm.cur) = '\0';
- infix(&nrm, true);
- res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf);
- }
- pfree(q);
-
- PG_RETURN_TEXT_P(res);
+ elog(ERROR, "querytree is no longer implemented");
+ PG_RETURN_NULL();
}
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c
index 375ff3ae25..9abe54e55f 100644
--- a/contrib/intarray/_int_gin.c
+++ b/contrib/intarray/_int_gin.c
@@ -1,8 +1,9 @@
/*
- * $PostgreSQL: pgsql/contrib/intarray/_int_gin.c,v 1.11 2010/03/25 15:50:10 tgl Exp $
+ * contrib/intarray/_int_gin.c
*/
#include "postgres.h"
+#include "access/gin.h"
#include "access/gist.h"
#include "access/skey.h"
@@ -16,66 +17,90 @@ ginint4_queryextract(PG_FUNCTION_ARGS)
{
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
StrategyNumber strategy = PG_GETARG_UINT16(2);
+ int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
Datum *res = NULL;
*nentries = 0;
if (strategy == BooleanSearchStrategy)
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
ITEM *items = GETQUERY(query);
int i;
- if (query->size == 0)
+ /* empty query must fail */
+ if (query->size <= 0)
PG_RETURN_POINTER(NULL);
- if (shorterquery(items, query->size) == 0)
- elog(ERROR, "Query requires full scan, GIN doesn't support it");
-
- pfree(query);
-
- query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
- items = GETQUERY(query);
-
+ /*
+ * If the query doesn't have any required primitive values (for
+ * instance, it's something like '! 42'), we have to do a full index
+ * scan.
+ */
+ if (query_has_required_values(query))
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else
+ *searchMode = GIN_SEARCH_MODE_ALL;
+
+ /*
+ * Extract all the VAL items as things we want GIN to check for.
+ */
res = (Datum *) palloc(sizeof(Datum) * query->size);
*nentries = 0;
for (i = 0; i < query->size; i++)
+ {
if (items[i].type == VAL)
{
res[*nentries] = Int32GetDatum(items[i].val);
(*nentries)++;
}
+ }
}
else
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
- int4 *arr;
- uint32 i;
CHECKARRVALID(query);
*nentries = ARRNELEMS(query);
if (*nentries > 0)
{
+ int4 *arr;
+ int32 i;
+
res = (Datum *) palloc(sizeof(Datum) * (*nentries));
arr = ARRPTR(query);
for (i = 0; i < *nentries; i++)
res[i] = Int32GetDatum(arr[i]);
}
- }
- if (*nentries == 0)
- {
switch (strategy)
{
- case BooleanSearchStrategy:
case RTOverlapStrategyNumber:
- *nentries = -1; /* nobody can be found */
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ break;
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ /* empty set is contained in everything */
+ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
+ break;
+ case RTSameStrategyNumber:
+ if (*nentries > 0)
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else
+ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
break;
- default: /* require fullscan: GIN can't find void
- * arrays */
+ case RTContainsStrategyNumber:
+ case RTOldContainsStrategyNumber:
+ if (*nentries > 0)
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else /* everything contains the empty set */
+ *searchMode = GIN_SEARCH_MODE_ALL;
break;
+ default:
+ elog(ERROR, "ginint4_queryextract: unknown strategy number: %d",
+ strategy);
}
}
@@ -90,16 +115,12 @@ ginint4_consistent(PG_FUNCTION_ARGS)
{
bool *check = (bool *) PG_GETARG_POINTER(0);
StrategyNumber strategy = PG_GETARG_UINT16(1);
+ int32 nkeys = PG_GETARG_INT32(3);
- /* int32 nkeys = PG_GETARG_INT32(3); */
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
bool *recheck = (bool *) PG_GETARG_POINTER(5);
bool res = FALSE;
-
- /*
- * we need not check array carefully, it's done by previous
- * ginarrayextract call
- */
+ int32 i;
switch (strategy)
{
@@ -117,47 +138,41 @@ ginint4_consistent(PG_FUNCTION_ARGS)
res = TRUE;
break;
case RTSameStrategyNumber:
+ /* we will need recheck */
+ *recheck = true;
+ /* Must have all elements in check[] true */
+ res = TRUE;
+ for (i = 0; i < nkeys; i++)
{
- ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
- int i,
- nentries = ARRNELEMS(query);
-
- /* we will need recheck */
- *recheck = true;
- res = TRUE;
- for (i = 0; i < nentries; i++)
- if (!check[i])
- {
- res = FALSE;
- break;
- }
+ if (!check[i])
+ {
+ res = FALSE;
+ break;
+ }
}
break;
case RTContainsStrategyNumber:
case RTOldContainsStrategyNumber:
+ /* result is not lossy */
+ *recheck = false;
+ /* Must have all elements in check[] true */
+ res = TRUE;
+ for (i = 0; i < nkeys; i++)
{
- ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
- int i,
- nentries = ARRNELEMS(query);
-
- /* result is not lossy */
- *recheck = false;
- res = TRUE;
- for (i = 0; i < nentries; i++)
- if (!check[i])
- {
- res = FALSE;
- break;
- }
+ if (!check[i])
+ {
+ res = FALSE;
+ break;
+ }
}
break;
case BooleanSearchStrategy:
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(2));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(2);
/* result is not lossy */
*recheck = false;
- res = ginconsistent(query, check);
+ res = gin_bool_consistent(query, check);
}
break;
default:
diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c
index 29e08eda66..0a173bfcb6 100644
--- a/contrib/intarray/_int_gist.c
+++ b/contrib/intarray/_int_gist.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/intarray/_int_gist.c,v 1.23 2009/06/11 14:48:51 momjian Exp $
+ * contrib/intarray/_int_gist.c
*/
#include "postgres.h"
@@ -40,7 +40,7 @@ Datum
g_int_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
- ArrayType *query = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(1));
+ ArrayType *query = PG_GETARG_ARRAYTYPE_P_COPY(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
@@ -62,11 +62,6 @@ g_int_consistent(PG_FUNCTION_ARGS)
/* sort query for fast search, key is already sorted */
CHECKARRVALID(query);
- if (ARRISVOID(query))
- {
- pfree(query);
- PG_RETURN_BOOL(false);
- }
PREPAREARR(query);
switch (strategy)
@@ -77,12 +72,10 @@ g_int_consistent(PG_FUNCTION_ARGS)
break;
case RTSameStrategyNumber:
if (GIST_LEAF(entry))
- DirectFunctionCall3(
- g_int_same,
+ DirectFunctionCall3(g_int_same,
entry->key,
PointerGetDatum(query),
- PointerGetDatum(&retval)
- );
+ PointerGetDatum(&retval));
else
retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
query);
@@ -162,7 +155,7 @@ g_int_compress(PG_FUNCTION_ARGS)
if (entry->leafkey)
{
- r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key);
+ r = DatumGetArrayTypePCopy(entry->key);
CHECKARRVALID(r);
PREPAREARR(r);
@@ -182,9 +175,9 @@ g_int_compress(PG_FUNCTION_ARGS)
* ==true, so now we work only with internal keys
*/
- r = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ r = DatumGetArrayTypeP(entry->key);
CHECKARRVALID(r);
- if (ARRISVOID(r))
+ if (ARRISEMPTY(r))
{
if (r != (ArrayType *) DatumGetPointer(entry->key))
pfree(r);
@@ -194,7 +187,7 @@ g_int_compress(PG_FUNCTION_ARGS)
if ((len = ARRNELEMS(r)) >= 2 * MAXNUMRANGE)
{ /* compress */
if (r == (ArrayType *) DatumGetPointer(entry->key))
- r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key);
+ r = DatumGetArrayTypePCopy(entry->key);
r = resize_intArrayType(r, 2 * (len));
dr = ARRPTR(r);
@@ -242,10 +235,10 @@ g_int_decompress(PG_FUNCTION_ARGS)
int i,
j;
- in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ in = DatumGetArrayTypeP(entry->key);
CHECKARRVALID(in);
- if (ARRISVOID(in))
+ if (ARRISEMPTY(in))
{
if (in != (ArrayType *) DatumGetPointer(entry->key))
{
@@ -321,8 +314,8 @@ g_int_penalty(PG_FUNCTION_ARGS)
Datum
g_int_same(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) PointerGetDatum(PG_GETARG_POINTER(0));
- ArrayType *b = (ArrayType *) PointerGetDatum(PG_GETARG_POINTER(1));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
int4 n = ARRNELEMS(a);
int4 *da,
@@ -340,11 +333,13 @@ g_int_same(PG_FUNCTION_ARGS)
da = ARRPTR(a);
db = ARRPTR(b);
while (n--)
+ {
if (*da++ != *db++)
{
*result = FALSE;
break;
}
+ }
PG_RETURN_POINTER(result);
}
diff --git a/contrib/intarray/_int_op.c b/contrib/intarray/_int_op.c
index 54858322a2..392e227cff 100644
--- a/contrib/intarray/_int_op.c
+++ b/contrib/intarray/_int_op.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/intarray/_int_op.c,v 1.9 2009/06/11 14:48:51 momjian Exp $
+ * contrib/intarray/_int_op.c
*/
#include "postgres.h"
@@ -29,27 +29,22 @@ Datum _int_inter(PG_FUNCTION_ARGS);
Datum
_int_contained(PG_FUNCTION_ARGS)
{
- PG_RETURN_BOOL(DatumGetBool(
- DirectFunctionCall2(
- _int_contains,
- PointerGetDatum(PG_GETARG_POINTER(1)),
- PointerGetDatum(PG_GETARG_POINTER(0))
- )
- ));
+ /* just reverse the operands and call _int_contains */
+ return DirectFunctionCall2(_int_contains,
+ PG_GETARG_DATUM(1),
+ PG_GETARG_DATUM(0));
}
Datum
_int_contains(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ /* Force copy so we can modify the arrays in-place */
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
bool res;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) || ARRISVOID(b))
- return FALSE;
-
PREPAREARR(a);
PREPAREARR(b);
res = inner_int_contains(a, b);
@@ -73,24 +68,17 @@ _int_different(PG_FUNCTION_ARGS)
Datum
_int_same(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
int na,
nb;
int n;
int *da,
*db;
bool result;
- bool avoid;
- bool bvoid;
CHECKARRVALID(a);
CHECKARRVALID(b);
- avoid = ARRISVOID(a);
- bvoid = ARRISVOID(b);
- if (avoid || bvoid)
- return (avoid && bvoid) ? TRUE : FALSE;
-
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
@@ -105,11 +93,13 @@ _int_same(PG_FUNCTION_ARGS)
result = TRUE;
for (n = 0; n < na; n++)
+ {
if (da[n] != db[n])
{
result = FALSE;
break;
}
+ }
}
pfree(a);
@@ -123,13 +113,13 @@ _int_same(PG_FUNCTION_ARGS)
Datum
_int_overlap(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
bool result;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) || ARRISVOID(b))
+ if (ARRISEMPTY(a) || ARRISEMPTY(b))
return FALSE;
SORT(a);
@@ -146,24 +136,20 @@ _int_overlap(PG_FUNCTION_ARGS)
Datum
_int_union(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
ArrayType *result;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (!ARRISVOID(a))
- SORT(a);
- if (!ARRISVOID(b))
- SORT(b);
+ SORT(a);
+ SORT(b);
result = inner_int_union(a, b);
- if (a)
- pfree(a);
- if (b)
- pfree(b);
+ pfree(a);
+ pfree(b);
PG_RETURN_POINTER(result);
}
@@ -171,14 +157,12 @@ _int_union(PG_FUNCTION_ARGS)
Datum
_int_inter(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
ArrayType *result;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) || ARRISVOID(b))
- PG_RETURN_POINTER(new_intArrayType(0));
SORT(a);
SORT(b);
@@ -228,7 +212,7 @@ intset(PG_FUNCTION_ARGS)
Datum
icount(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
int32 count = ARRNELEMS(a);
PG_FREE_IF_COPY(a, 0);
@@ -238,14 +222,14 @@ icount(PG_FUNCTION_ARGS)
Datum
sort(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_P(1) : NULL;
int32 dc = (dirstr) ? VARSIZE(dirstr) - VARHDRSZ : 0;
char *d = (dirstr) ? VARDATA(dirstr) : NULL;
int dir = -1;
CHECKARRVALID(a);
- if (ARRISVOID(a) || ARRNELEMS(a) < 2)
+ if (ARRNELEMS(a) < 2)
PG_RETURN_POINTER(a);
if (dirstr == NULL || (dc == 3
@@ -270,11 +254,9 @@ sort(PG_FUNCTION_ARGS)
Datum
sort_asc(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
CHECKARRVALID(a);
- if (ARRISVOID(a))
- PG_RETURN_POINTER(a);
QSORT(a, 1);
PG_RETURN_POINTER(a);
}
@@ -282,11 +264,9 @@ sort_asc(PG_FUNCTION_ARGS)
Datum
sort_desc(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
CHECKARRVALID(a);
- if (ARRISVOID(a))
- PG_RETURN_POINTER(a);
QSORT(a, 0);
PG_RETURN_POINTER(a);
}
@@ -294,10 +274,10 @@ sort_desc(PG_FUNCTION_ARGS)
Datum
uniq(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
CHECKARRVALID(a);
- if (ARRISVOID(a) || ARRNELEMS(a) < 2)
+ if (ARRNELEMS(a) < 2)
PG_RETURN_POINTER(a);
a = _int_unique(a);
PG_RETURN_POINTER(a);
@@ -306,11 +286,11 @@ uniq(PG_FUNCTION_ARGS)
Datum
idx(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
int32 result;
CHECKARRVALID(a);
- result = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ result = ARRNELEMS(a);
if (result)
result = intarray_match_first(a, PG_GETARG_INT32(1));
PG_FREE_IF_COPY(a, 0);
@@ -320,15 +300,17 @@ idx(PG_FUNCTION_ARGS)
Datum
subarray(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
- ArrayType *result;
- int32 start = (PG_GETARG_INT32(1) > 0) ? PG_GETARG_INT32(1) - 1 : PG_GETARG_INT32(1);
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ int32 start = PG_GETARG_INT32(1);
int32 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
int32 end = 0;
int32 c;
+ ArrayType *result;
+
+ start = (start > 0) ? start - 1 : start;
CHECKARRVALID(a);
- if (ARRISVOID(a))
+ if (ARRISEMPTY(a))
{
PG_FREE_IF_COPY(a, 0);
PG_RETURN_POINTER(new_intArrayType(0));
@@ -358,7 +340,6 @@ subarray(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(new_intArrayType(0));
}
-
result = new_intArrayType(end - start);
if (end - start > 0)
memcpy(ARRPTR(result), ARRPTR(a) + start, (end - start) * sizeof(int32));
@@ -369,7 +350,7 @@ subarray(PG_FUNCTION_ARGS)
Datum
intarray_push_elem(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
ArrayType *result;
result = intarray_add_elem(a, PG_GETARG_INT32(1));
@@ -380,8 +361,8 @@ intarray_push_elem(PG_FUNCTION_ARGS)
Datum
intarray_push_array(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
ArrayType *result;
result = intarray_concat_arrays(a, b);
@@ -393,7 +374,7 @@ intarray_push_array(PG_FUNCTION_ARGS)
Datum
intarray_del_elem(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
int32 elem = PG_GETARG_INT32(1);
int32 c;
int32 *aa;
@@ -401,7 +382,7 @@ intarray_del_elem(PG_FUNCTION_ARGS)
i;
CHECKARRVALID(a);
- if (!ARRISVOID(a))
+ if (!ARRISEMPTY(a))
{
c = ARRNELEMS(a);
aa = ARRPTR(a);
@@ -423,7 +404,7 @@ intarray_del_elem(PG_FUNCTION_ARGS)
Datum
intset_union_elem(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
ArrayType *result;
result = intarray_add_elem(a, PG_GETARG_INT32(1));
@@ -435,8 +416,8 @@ intset_union_elem(PG_FUNCTION_ARGS)
Datum
intset_subtract(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
ArrayType *result;
int32 ca;
int32 cb;
diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
index 8c0ec29c31..bfc55501db 100644
--- a/contrib/intarray/_int_tool.c
+++ b/contrib/intarray/_int_tool.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/intarray/_int_tool.c,v 1.12 2009/06/11 14:48:51 momjian Exp $
+ * contrib/intarray/_int_tool.c
*/
#include "postgres.h"
@@ -8,6 +8,7 @@
#include "_int.h"
+/* arguments are assumed sorted & unique-ified */
bool
inner_int_contains(ArrayType *a, ArrayType *b)
{
@@ -19,12 +20,6 @@ inner_int_contains(ArrayType *a, ArrayType *b)
int *da,
*db;
- CHECKARRVALID(a);
- CHECKARRVALID(b);
-
- if (ARRISVOID(a) || ARRISVOID(b))
- return FALSE;
-
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
@@ -32,6 +27,7 @@ inner_int_contains(ArrayType *a, ArrayType *b)
i = j = n = 0;
while (i < na && j < nb)
+ {
if (da[i] < db[j])
i++;
else if (da[i] == db[j])
@@ -41,11 +37,13 @@ inner_int_contains(ArrayType *a, ArrayType *b)
j++;
}
else
- break;
+ break; /* db[j] is not in da */
+ }
return (n == nb) ? TRUE : FALSE;
}
+/* arguments are assumed sorted */
bool
inner_int_overlap(ArrayType *a, ArrayType *b)
{
@@ -56,12 +54,6 @@ inner_int_overlap(ArrayType *a, ArrayType *b)
int *da,
*db;
- CHECKARRVALID(a);
- CHECKARRVALID(b);
-
- if (ARRISVOID(a) || ARRISVOID(b))
- return FALSE;
-
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
@@ -69,12 +61,14 @@ inner_int_overlap(ArrayType *a, ArrayType *b)
i = j = 0;
while (i < na && j < nb)
+ {
if (da[i] < db[j])
i++;
else if (da[i] == db[j])
return TRUE;
else
j++;
+ }
return FALSE;
}
@@ -87,11 +81,11 @@ inner_int_union(ArrayType *a, ArrayType *b)
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) && ARRISVOID(b))
+ if (ARRISEMPTY(a) && ARRISEMPTY(b))
return new_intArrayType(0);
- if (ARRISVOID(a))
+ if (ARRISEMPTY(a))
r = copy_intArrayType(b);
- if (ARRISVOID(b))
+ if (ARRISEMPTY(b))
r = copy_intArrayType(a);
if (!r)
@@ -148,10 +142,7 @@ inner_int_inter(ArrayType *a, ArrayType *b)
int i,
j;
- CHECKARRVALID(a);
- CHECKARRVALID(b);
-
- if (ARRISVOID(a) || ARRISVOID(b))
+ if (ARRISEMPTY(a) || ARRISEMPTY(b))
return new_intArrayType(0);
na = ARRNELEMS(a);
@@ -163,6 +154,7 @@ inner_int_inter(ArrayType *a, ArrayType *b)
i = j = 0;
while (i < na && j < nb)
+ {
if (da[i] < db[j])
i++;
else if (da[i] == db[j])
@@ -174,6 +166,7 @@ inner_int_inter(ArrayType *a, ArrayType *b)
}
else
j++;
+ }
if ((dr - ARRPTR(r)) == 0)
{
@@ -188,57 +181,60 @@ void
rt__int_size(ArrayType *a, float *size)
{
*size = (float) ARRNELEMS(a);
-
- return;
}
-
-/* len >= 2 */
+/* Sort the given data (len >= 2). Return true if any duplicates found */
bool
isort(int4 *a, int len)
{
- int4 tmp,
- index;
- int4 *cur,
+ int4 cur,
+ prev;
+ int4 *pcur,
+ *pprev,
*end;
bool r = FALSE;
+ /*
+ * We use a simple insertion sort. While this is O(N^2) in the worst
+ * case, it's quite fast if the input is already sorted or nearly so.
+ * Also, for not-too-large inputs it's faster than more complex methods
+ * anyhow.
+ */
end = a + len;
- do
+ for (pcur = a + 1; pcur < end; pcur++)
{
- index = 0;
- cur = a + 1;
- while (cur < end)
+ cur = *pcur;
+ for (pprev = pcur - 1; pprev >= a; pprev--)
{
- if (*(cur - 1) > *cur)
+ prev = *pprev;
+ if (prev <= cur)
{
- tmp = *(cur - 1);
- *(cur - 1) = *cur;
- *cur = tmp;
- index = 1;
+ if (prev == cur)
+ r = TRUE;
+ break;
}
- else if (!r && *(cur - 1) == *cur)
- r = TRUE;
- cur++;
+ pprev[1] = prev;
}
- } while (index);
+ pprev[1] = cur;
+ }
return r;
}
+/* Create a new int array with room for "num" elements */
ArrayType *
new_intArrayType(int num)
{
ArrayType *r;
- int nbytes = ARR_OVERHEAD_NONULLS(NDIM) + sizeof(int) * num;
+ int nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num;
r = (ArrayType *) palloc0(nbytes);
SET_VARSIZE(r, nbytes);
- ARR_NDIM(r) = NDIM;
+ ARR_NDIM(r) = 1;
r->dataoffset = 0; /* marker for no null bitmap */
ARR_ELEMTYPE(r) = INT4OID;
- *((int *) ARR_DIMS(r)) = num;
- *((int *) ARR_LBOUND(r)) = 1;
+ ARR_DIMS(r)[0] = num;
+ ARR_LBOUND(r)[0] = 1;
return r;
}
@@ -246,7 +242,8 @@ new_intArrayType(int num)
ArrayType *
resize_intArrayType(ArrayType *a, int num)
{
- int nbytes = ARR_OVERHEAD_NONULLS(NDIM) + sizeof(int) * num;
+ int nbytes = ARR_DATA_OFFSET(a) + sizeof(int) * num;
+ int i;
if (num == ARRNELEMS(a))
return a;
@@ -254,7 +251,12 @@ resize_intArrayType(ArrayType *a, int num)
a = (ArrayType *) repalloc(a, nbytes);
SET_VARSIZE(a, nbytes);
- *((int *) ARR_DIMS(a)) = num;
+ /* usually the array should be 1-D already, but just in case ... */
+ for (i = 0; i < ARR_NDIM(a); i++)
+ {
+ ARR_DIMS(a)[i] = num;
+ num = 1;
+ }
return a;
}
@@ -262,9 +264,10 @@ ArrayType *
copy_intArrayType(ArrayType *a)
{
ArrayType *r;
+ int n = ARRNELEMS(a);
- r = new_intArrayType(ARRNELEMS(a));
- memmove(r, a, VARSIZE(r));
+ r = new_intArrayType(n);
+ memcpy(ARRPTR(r), ARRPTR(a), n * sizeof(int4));
return r;
}
@@ -276,13 +279,15 @@ internal_size(int *a, int len)
size = 0;
for (i = 0; i < len; i += 2)
+ {
if (!i || a[i] != a[i - 1]) /* do not count repeated range */
size += a[i + 1] - a[i] + 1;
+ }
return size;
}
-/* r is sorted and size of r > 1 */
+/* unique-ify elements of r in-place ... r must be sorted already */
ArrayType *
_int_unique(ArrayType *r)
{
@@ -291,17 +296,17 @@ _int_unique(ArrayType *r)
*data;
int num = ARRNELEMS(r);
- CHECKARRVALID(r);
-
if (num < 2)
return r;
data = tmp = dr = ARRPTR(r);
while (tmp - data < num)
+ {
if (*tmp != *dr)
*(++dr) = *tmp++;
else
tmp++;
+ }
return resize_intArrayType(r, dr + 1 - ARRPTR(r));
}
@@ -326,8 +331,6 @@ intarray_match_first(ArrayType *a, int32 elem)
i;
CHECKARRVALID(a);
- if (ARRISVOID(a))
- return 0;
c = ARRNELEMS(a);
aa = ARRPTR(a);
for (i = 0; i < c; i++)
@@ -344,7 +347,7 @@ intarray_add_elem(ArrayType *a, int32 elem)
int32 c;
CHECKARRVALID(a);
- c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ c = ARRNELEMS(a);
result = new_intArrayType(c + 1);
r = ARRPTR(result);
if (c > 0)
@@ -357,8 +360,8 @@ ArrayType *
intarray_concat_arrays(ArrayType *a, ArrayType *b)
{
ArrayType *result;
- int32 ac = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
- int32 bc = (ARRISVOID(b)) ? 0 : ARRNELEMS(b);
+ int32 ac = ARRNELEMS(a);
+ int32 bc = ARRNELEMS(b);
CHECKARRVALID(a);
CHECKARRVALID(b);
diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c
index f9c5986db2..eb8f282634 100644
--- a/contrib/intarray/_intbig_gist.c
+++ b/contrib/intarray/_intbig_gist.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/intarray/_intbig_gist.c,v 1.20 2009/06/11 14:48:51 momjian Exp $
+ * contrib/intarray/_intbig_gist.c
*/
#include "postgres.h"
@@ -153,13 +153,13 @@ g_intbig_compress(PG_FUNCTION_ARGS)
if (entry->leafkey)
{
GISTENTRY *retval;
- ArrayType *in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ ArrayType *in = DatumGetArrayTypeP(entry->key);
int4 *ptr;
int num;
GISTTYPE *res = (GISTTYPE *) palloc0(CALCGTSIZE(0));
CHECKARRVALID(in);
- if (ARRISVOID(in))
+ if (ARRISEMPTY(in))
{
ptr = NULL;
num = 0;
@@ -182,7 +182,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
entry->rel, entry->page,
entry->offset, FALSE);
- if (in != (ArrayType *) PG_DETOAST_DATUM(entry->key))
+ if (in != DatumGetArrayTypeP(entry->key))
pfree(in);
PG_RETURN_POINTER(retval);
@@ -504,7 +504,7 @@ Datum
g_intbig_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
- ArrayType *query = (ArrayType *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
+ ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
@@ -527,11 +527,6 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
}
CHECKARRVALID(query);
- if (ARRISVOID(query))
- {
- PG_FREE_IF_COPY(query, 1);
- PG_RETURN_BOOL(FALSE);
- }
switch (strategy)
{
@@ -548,8 +543,6 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
BITVECP dq,
de;
- CHECKARRVALID(query);
-
memset(qp, 0, sizeof(BITVEC));
while (num--)
@@ -589,8 +582,6 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
BITVECP dq,
de;
- CHECKARRVALID(query);
-
memset(qp, 0, sizeof(BITVEC));
while (num--)
diff --git a/contrib/intarray/bench/bench.pl b/contrib/intarray/bench/bench.pl
index 66df02dfc1..4e18624b9c 100755
--- a/contrib/intarray/bench/bench.pl
+++ b/contrib/intarray/bench/bench.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/perl
use strict;
# make sure we are in a sane environment.
@@ -14,16 +14,16 @@ if ( !( scalar %opt && defined $opt{s} ) ) {
print <<EOT;
Usage:
$0 -d DATABASE -s SECTIONS [-b NUMBER] [-v] [-e] [-o] [-r] [-a] [-u]
--d DATABASE -DATABASE
--b NUMBER -number of repeats
--s SECTIONS -sections, format sid1[,sid2[,sid3[...]]]]
--v -verbose (show SQL)
+-d DATABASE -DATABASE
+-b NUMBER -number of repeats
+-s SECTIONS -sections, format sid1[,sid2[,sid3[...]]]]
+-v -verbose (show SQL)
-e -show explain
-r -use RD-tree index
-a -AND section
-o -show output
-u -unique
--c -count
+-c -count
EOT
exit;
@@ -87,20 +87,19 @@ if ( $opt{o} ) {
foreach ( @a ) {
print "$_->{mid}\t$_->{sections}\n";
}
-}
+}
print sprintf("total: %.02f sec; number: %d; for one: %.03f sec; found %d docs\n", $elapsed, $b, $elapsed/$b, $count+1 );
$dbi -> disconnect;
sub exec_sql {
my ($dbi, $sql, @keys) = @_;
my $sth=$dbi->prepare($sql) || die;
- $sth->execute( @keys ) || die;
- my $r;
+ $sth->execute( @keys ) || die;
+ my $r;
my @row;
while ( defined ( $r=$sth->fetchrow_hashref ) ) {
push @row, $r;
- }
- $sth->finish;
+ }
+ $sth->finish;
return @row;
}
-
diff --git a/contrib/intarray/bench/create_test.pl b/contrib/intarray/bench/create_test.pl
index 01671bf5a2..67394f87b7 100755
--- a/contrib/intarray/bench/create_test.pl
+++ b/contrib/intarray/bench/create_test.pl
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-# $PostgreSQL: pgsql/contrib/intarray/bench/create_test.pl,v 1.4 2006/03/11 04:38:29 momjian Exp $
+# contrib/intarray/bench/create_test.pl
use strict;
print <<EOT;
@@ -9,7 +9,7 @@ create table message (
sections int[]
);
create table message_section_map (
- mid int not null,
+ mid int not null,
sid int not null
);
@@ -66,7 +66,7 @@ unlink 'message.tmp', 'message_section_map.tmp';
sub copytable {
my $t = shift;
-
+
print "COPY $t from stdin;\n";
open( FFF, "$t.tmp") || die;
while(<FFF>) { print; }
diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out
index 596439d314..6ed3cc6ced 100644
--- a/contrib/intarray/expected/_int.out
+++ b/contrib/intarray/expected/_int.out
@@ -1,10 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of _int.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION intarray;
SELECT intset(1234);
intset
--------
diff --git a/contrib/intarray/_int.sql.in b/contrib/intarray/intarray--1.0.sql
index 960d81a638..3b77c516cb 100644
--- a/contrib/intarray/_int.sql.in
+++ b/contrib/intarray/intarray--1.0.sql
@@ -1,19 +1,16 @@
-/* $PostgreSQL: pgsql/contrib/intarray/_int.sql.in,v 1.32 2009/06/11 18:30:03 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/intarray/intarray--1.0.sql */
--
-- Create the user-defined type for the 1-D integer arrays (_int4)
--
-- Query type
-CREATE OR REPLACE FUNCTION bqarr_in(cstring)
+CREATE FUNCTION bqarr_in(cstring)
RETURNS query_int
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION bqarr_out(query_int)
+CREATE FUNCTION bqarr_out(query_int)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -25,20 +22,20 @@ CREATE TYPE query_int (
);
--only for debug
-CREATE OR REPLACE FUNCTION querytree(query_int)
+CREATE FUNCTION querytree(query_int)
RETURNS text
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION boolop(_int4, query_int)
+CREATE FUNCTION boolop(_int4, query_int)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION boolop(_int4, query_int) IS 'boolean operation with array';
-CREATE OR REPLACE FUNCTION rboolop(query_int, _int4)
+CREATE FUNCTION rboolop(query_int, _int4)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -70,35 +67,35 @@ CREATE OPERATOR ~~ (
-- Comparison methods
-CREATE OR REPLACE FUNCTION _int_contains(_int4, _int4)
+CREATE FUNCTION _int_contains(_int4, _int4)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION _int_contains(_int4, _int4) IS 'contains';
-CREATE OR REPLACE FUNCTION _int_contained(_int4, _int4)
+CREATE FUNCTION _int_contained(_int4, _int4)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION _int_contained(_int4, _int4) IS 'contained in';
-CREATE OR REPLACE FUNCTION _int_overlap(_int4, _int4)
+CREATE FUNCTION _int_overlap(_int4, _int4)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION _int_overlap(_int4, _int4) IS 'overlaps';
-CREATE OR REPLACE FUNCTION _int_same(_int4, _int4)
+CREATE FUNCTION _int_same(_int4, _int4)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION _int_same(_int4, _int4) IS 'same as';
-CREATE OR REPLACE FUNCTION _int_different(_int4, _int4)
+CREATE FUNCTION _int_different(_int4, _int4)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -107,12 +104,12 @@ COMMENT ON FUNCTION _int_different(_int4, _int4) IS 'different';
-- support routines for indexing
-CREATE OR REPLACE FUNCTION _int_union(_int4, _int4)
+CREATE FUNCTION _int_union(_int4, _int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _int_inter(_int4, _int4)
+CREATE FUNCTION _int_inter(_int4, _int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -190,12 +187,12 @@ CREATE OPERATOR ~ (
);
--------------
-CREATE OR REPLACE FUNCTION intset(int4)
+CREATE FUNCTION intset(int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION icount(_int4)
+CREATE FUNCTION icount(_int4)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -205,32 +202,32 @@ CREATE OPERATOR # (
PROCEDURE = icount
);
-CREATE OR REPLACE FUNCTION sort(_int4, text)
+CREATE FUNCTION sort(_int4, text)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION sort(_int4)
+CREATE FUNCTION sort(_int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION sort_asc(_int4)
+CREATE FUNCTION sort_asc(_int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION sort_desc(_int4)
+CREATE FUNCTION sort_desc(_int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION uniq(_int4)
+CREATE FUNCTION uniq(_int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION idx(_int4, int4)
+CREATE FUNCTION idx(_int4, int4)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -241,17 +238,17 @@ CREATE OPERATOR # (
PROCEDURE = idx
);
-CREATE OR REPLACE FUNCTION subarray(_int4, int4, int4)
+CREATE FUNCTION subarray(_int4, int4, int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION subarray(_int4, int4)
+CREATE FUNCTION subarray(_int4, int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION intarray_push_elem(_int4, int4)
+CREATE FUNCTION intarray_push_elem(_int4, int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -262,7 +259,7 @@ CREATE OPERATOR + (
PROCEDURE = intarray_push_elem
);
-CREATE OR REPLACE FUNCTION intarray_push_array(_int4, _int4)
+CREATE FUNCTION intarray_push_array(_int4, _int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -274,7 +271,7 @@ CREATE OPERATOR + (
PROCEDURE = intarray_push_array
);
-CREATE OR REPLACE FUNCTION intarray_del_elem(_int4, int4)
+CREATE FUNCTION intarray_del_elem(_int4, int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -285,7 +282,7 @@ CREATE OPERATOR - (
PROCEDURE = intarray_del_elem
);
-CREATE OR REPLACE FUNCTION intset_union_elem(_int4, int4)
+CREATE FUNCTION intset_union_elem(_int4, int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -303,7 +300,7 @@ CREATE OPERATOR | (
PROCEDURE = _int_union
);
-CREATE OR REPLACE FUNCTION intset_subtract(_int4, _int4)
+CREATE FUNCTION intset_subtract(_int4, _int4)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -323,37 +320,37 @@ CREATE OPERATOR & (
--------------
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION g_int_consistent(internal,_int4,int,oid,internal)
+CREATE FUNCTION g_int_consistent(internal,_int4,int,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_int_compress(internal)
+CREATE FUNCTION g_int_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_int_decompress(internal)
+CREATE FUNCTION g_int_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_int_penalty(internal,internal,internal)
+CREATE FUNCTION g_int_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_int_picksplit(internal, internal)
+CREATE FUNCTION g_int_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_int_union(internal, internal)
+CREATE FUNCTION g_int_union(internal, internal)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_int_same(_int4, _int4, internal)
+CREATE FUNCTION g_int_same(_int4, _int4, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -384,12 +381,12 @@ DEFAULT FOR TYPE _int4 USING gist AS
---------------------------------------------
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION _intbig_in(cstring)
+CREATE FUNCTION _intbig_in(cstring)
RETURNS intbig_gkey
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _intbig_out(intbig_gkey)
+CREATE FUNCTION _intbig_out(intbig_gkey)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -400,37 +397,37 @@ CREATE TYPE intbig_gkey (
OUTPUT = _intbig_out
);
-CREATE OR REPLACE FUNCTION g_intbig_consistent(internal,internal,int,oid,internal)
+CREATE FUNCTION g_intbig_consistent(internal,internal,int,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_intbig_compress(internal)
+CREATE FUNCTION g_intbig_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_intbig_decompress(internal)
+CREATE FUNCTION g_intbig_decompress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_intbig_penalty(internal,internal,internal)
+CREATE FUNCTION g_intbig_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_intbig_picksplit(internal, internal)
+CREATE FUNCTION g_intbig_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_intbig_union(internal, internal)
+CREATE FUNCTION g_intbig_union(internal, internal)
RETURNS _int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION g_intbig_same(internal, internal, internal)
+CREATE FUNCTION g_intbig_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -458,12 +455,12 @@ AS
--GIN
-CREATE OR REPLACE FUNCTION ginint4_queryextract(internal, internal, int2, internal, internal)
+CREATE FUNCTION ginint4_queryextract(internal, internal, int2, internal, internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ginint4_consistent(internal, int2, internal, int4, internal, internal)
+CREATE FUNCTION ginint4_consistent(internal, int2, internal, int4, internal, internal, internal, internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -479,7 +476,7 @@ AS
OPERATOR 14 ~,
OPERATOR 20 @@ (_int4, query_int),
FUNCTION 1 btint4cmp (int4, int4),
- FUNCTION 2 ginarrayextract (anyarray, internal),
- FUNCTION 3 ginint4_queryextract (internal, internal, int2, internal, internal),
- FUNCTION 4 ginint4_consistent (internal, int2, internal, int4, internal, internal),
+ FUNCTION 2 ginarrayextract (anyarray, internal, internal),
+ FUNCTION 3 ginint4_queryextract (internal, internal, int2, internal, internal, internal, internal),
+ FUNCTION 4 ginint4_consistent (internal, int2, internal, int4, internal, internal, internal, internal),
STORAGE int4;
diff --git a/contrib/intarray/intarray--unpackaged--1.0.sql b/contrib/intarray/intarray--unpackaged--1.0.sql
new file mode 100644
index 0000000000..5a2829c9f5
--- /dev/null
+++ b/contrib/intarray/intarray--unpackaged--1.0.sql
@@ -0,0 +1,108 @@
+/* contrib/intarray/intarray--unpackaged--1.0.sql */
+
+ALTER EXTENSION intarray ADD type query_int;
+ALTER EXTENSION intarray ADD function bqarr_in(cstring);
+ALTER EXTENSION intarray ADD function bqarr_out(query_int);
+ALTER EXTENSION intarray ADD function querytree(query_int);
+ALTER EXTENSION intarray ADD function boolop(integer[],query_int);
+ALTER EXTENSION intarray ADD function rboolop(query_int,integer[]);
+ALTER EXTENSION intarray ADD operator ~~(query_int,integer[]);
+ALTER EXTENSION intarray ADD operator @@(integer[],query_int);
+ALTER EXTENSION intarray ADD function _int_contains(integer[],integer[]);
+ALTER EXTENSION intarray ADD function _int_contained(integer[],integer[]);
+ALTER EXTENSION intarray ADD function _int_overlap(integer[],integer[]);
+ALTER EXTENSION intarray ADD function _int_same(integer[],integer[]);
+ALTER EXTENSION intarray ADD function _int_different(integer[],integer[]);
+ALTER EXTENSION intarray ADD function _int_union(integer[],integer[]);
+ALTER EXTENSION intarray ADD function _int_inter(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator &&(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator <@(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator @>(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator ~(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator @(integer[],integer[]);
+ALTER EXTENSION intarray ADD function intset(integer);
+ALTER EXTENSION intarray ADD function icount(integer[]);
+ALTER EXTENSION intarray ADD operator #(NONE,integer[]);
+ALTER EXTENSION intarray ADD function sort(integer[],text);
+ALTER EXTENSION intarray ADD function sort(integer[]);
+ALTER EXTENSION intarray ADD function sort_asc(integer[]);
+ALTER EXTENSION intarray ADD function sort_desc(integer[]);
+ALTER EXTENSION intarray ADD function uniq(integer[]);
+ALTER EXTENSION intarray ADD function idx(integer[],integer);
+ALTER EXTENSION intarray ADD operator #(integer[],integer);
+ALTER EXTENSION intarray ADD function subarray(integer[],integer,integer);
+ALTER EXTENSION intarray ADD function subarray(integer[],integer);
+ALTER EXTENSION intarray ADD function intarray_push_elem(integer[],integer);
+ALTER EXTENSION intarray ADD operator +(integer[],integer);
+ALTER EXTENSION intarray ADD function intarray_push_array(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator +(integer[],integer[]);
+ALTER EXTENSION intarray ADD function intarray_del_elem(integer[],integer);
+ALTER EXTENSION intarray ADD operator -(integer[],integer);
+ALTER EXTENSION intarray ADD function intset_union_elem(integer[],integer);
+ALTER EXTENSION intarray ADD operator |(integer[],integer);
+ALTER EXTENSION intarray ADD operator |(integer[],integer[]);
+ALTER EXTENSION intarray ADD function intset_subtract(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator -(integer[],integer[]);
+ALTER EXTENSION intarray ADD operator &(integer[],integer[]);
+ALTER EXTENSION intarray ADD function g_int_consistent(internal,integer[],integer,oid,internal);
+ALTER EXTENSION intarray ADD function g_int_compress(internal);
+ALTER EXTENSION intarray ADD function g_int_decompress(internal);
+ALTER EXTENSION intarray ADD function g_int_penalty(internal,internal,internal);
+ALTER EXTENSION intarray ADD function g_int_picksplit(internal,internal);
+ALTER EXTENSION intarray ADD function g_int_union(internal,internal);
+ALTER EXTENSION intarray ADD function g_int_same(integer[],integer[],internal);
+ALTER EXTENSION intarray ADD operator family gist__int_ops using gist;
+ALTER EXTENSION intarray ADD operator class gist__int_ops using gist;
+ALTER EXTENSION intarray ADD type intbig_gkey;
+ALTER EXTENSION intarray ADD function _intbig_in(cstring);
+ALTER EXTENSION intarray ADD function _intbig_out(intbig_gkey);
+ALTER EXTENSION intarray ADD function g_intbig_consistent(internal,internal,integer,oid,internal);
+ALTER EXTENSION intarray ADD function g_intbig_compress(internal);
+ALTER EXTENSION intarray ADD function g_intbig_decompress(internal);
+ALTER EXTENSION intarray ADD function g_intbig_penalty(internal,internal,internal);
+ALTER EXTENSION intarray ADD function g_intbig_picksplit(internal,internal);
+ALTER EXTENSION intarray ADD function g_intbig_union(internal,internal);
+ALTER EXTENSION intarray ADD function g_intbig_same(internal,internal,internal);
+ALTER EXTENSION intarray ADD operator family gist__intbig_ops using gist;
+ALTER EXTENSION intarray ADD operator class gist__intbig_ops using gist;
+ALTER EXTENSION intarray ADD operator family gin__int_ops using gin;
+ALTER EXTENSION intarray ADD operator class gin__int_ops using gin;
+
+-- These functions had different signatures in 9.0. We can't just
+-- drop and recreate them because they are linked into the GIN opclass,
+-- so we need some ugly hacks.
+
+-- First, absorb them into the extension under their old identities.
+
+ALTER EXTENSION intarray ADD function ginint4_queryextract(internal,internal,smallint,internal,internal);
+ALTER EXTENSION intarray ADD function ginint4_consistent(internal,smallint,internal,integer,internal,internal);
+
+-- Next, fix the parameter lists by means of direct UPDATE on the pg_proc
+-- entries. This is ugly as can be, but there's no other way to do it
+-- while preserving the identities (OIDs) of the functions.
+
+UPDATE pg_catalog.pg_proc
+SET pronargs = 7, proargtypes = '2281 2281 21 2281 2281 2281 2281'
+WHERE oid = 'ginint4_queryextract(internal,internal,smallint,internal,internal)'::pg_catalog.regprocedure;
+
+UPDATE pg_catalog.pg_proc
+SET pronargs = 8, proargtypes = '2281 21 2281 23 2281 2281 2281 2281'
+WHERE oid = 'ginint4_consistent(internal,smallint,internal,integer,internal,internal)'::pg_catalog.regprocedure;
+
+-- intarray also relies on the core function ginarrayextract, which changed
+-- signature in 9.1. To support upgrading, pg_catalog contains entries
+-- for ginarrayextract with both 2 and 3 args, and the former is what would
+-- have been added to our opclass during initial restore of a 9.0 dump script.
+-- Avert your eyes while we hack the pg_amproc entry to make it link to the
+-- 3-arg form ...
+
+UPDATE pg_catalog.pg_amproc
+SET amproc = 'pg_catalog.ginarrayextract(anyarray,internal,internal)'::pg_catalog.regprocedure
+WHERE amprocfamily =
+ (SELECT oid FROM pg_catalog.pg_opfamily WHERE opfname = 'gin__int_ops' AND
+ opfnamespace = (SELECT oid FROM pg_catalog.pg_namespace
+ WHERE nspname = pg_catalog.current_schema()))
+ AND amproclefttype = 'integer[]'::pg_catalog.regtype
+ AND amprocrighttype = 'integer[]'::pg_catalog.regtype
+ AND amprocnum = 2
+ AND amproc = 'pg_catalog.ginarrayextract(anyarray,internal)'::pg_catalog.regprocedure;
diff --git a/contrib/intarray/intarray.control b/contrib/intarray/intarray.control
new file mode 100644
index 0000000000..7b3d4f78f0
--- /dev/null
+++ b/contrib/intarray/intarray.control
@@ -0,0 +1,5 @@
+# intarray extension
+comment = 'functions, operators, and index support for 1-D arrays of integers'
+default_version = '1.0'
+module_pathname = '$libdir/_int'
+relocatable = true
diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql
index 1588e3b514..b60e936dc5 100644
--- a/contrib/intarray/sql/_int.sql
+++ b/contrib/intarray/sql/_int.sql
@@ -1,12 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of _int.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i _int.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION intarray;
SELECT intset(1234);
SELECT icount('{1234234,234234}');
diff --git a/contrib/intarray/uninstall__int.sql b/contrib/intarray/uninstall__int.sql
deleted file mode 100644
index ba962cd0d5..0000000000
--- a/contrib/intarray/uninstall__int.sql
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/intarray/uninstall__int.sql,v 1.12 2009/06/07 20:09:34 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-DROP OPERATOR CLASS gin__int_ops USING gin;
-
-DROP FUNCTION ginint4_queryextract(internal, internal, int2, internal, internal);
-
-DROP FUNCTION ginint4_consistent(internal, int2, internal, int4, internal, internal);
-
-DROP OPERATOR CLASS gist__intbig_ops USING gist;
-
-DROP FUNCTION g_intbig_same(internal, internal, internal);
-
-DROP FUNCTION g_intbig_union(internal, internal);
-
-DROP FUNCTION g_intbig_picksplit(internal, internal);
-
-DROP FUNCTION g_intbig_penalty(internal,internal,internal);
-
-DROP FUNCTION g_intbig_decompress(internal);
-
-DROP FUNCTION g_intbig_compress(internal);
-
-DROP FUNCTION g_intbig_consistent(internal,internal,int,oid,internal);
-
-DROP TYPE intbig_gkey CASCADE;
-
-DROP OPERATOR CLASS gist__int_ops USING gist;
-
-DROP FUNCTION g_int_same(_int4, _int4, internal);
-
-DROP FUNCTION g_int_union(internal, internal);
-
-DROP FUNCTION g_int_picksplit(internal, internal);
-
-DROP FUNCTION g_int_penalty(internal,internal,internal);
-
-DROP FUNCTION g_int_decompress(internal);
-
-DROP FUNCTION g_int_compress(internal);
-
-DROP FUNCTION g_int_consistent(internal,_int4,int,oid,internal);
-
-DROP OPERATOR & (_int4, _int4);
-
-DROP OPERATOR - (_int4, _int4);
-
-DROP FUNCTION intset_subtract(_int4, _int4);
-
-DROP OPERATOR | (_int4, _int4);
-
-DROP OPERATOR | (_int4, int4);
-
-DROP FUNCTION intset_union_elem(_int4, int4);
-
-DROP OPERATOR - (_int4, int4);
-
-DROP FUNCTION intarray_del_elem(_int4, int4);
-
-DROP OPERATOR + (_int4, _int4);
-
-DROP FUNCTION intarray_push_array(_int4, _int4);
-
-DROP OPERATOR + (_int4, int4);
-
-DROP FUNCTION intarray_push_elem(_int4, int4);
-
-DROP FUNCTION subarray(_int4, int4);
-
-DROP FUNCTION subarray(_int4, int4, int4);
-
-DROP OPERATOR # (_int4, int4);
-
-DROP FUNCTION idx(_int4, int4);
-
-DROP FUNCTION uniq(_int4);
-
-DROP FUNCTION sort_desc(_int4);
-
-DROP FUNCTION sort_asc(_int4);
-
-DROP FUNCTION sort(_int4);
-
-DROP FUNCTION sort(_int4, text);
-
-DROP OPERATOR # (NONE, _int4);
-
-DROP FUNCTION icount(_int4);
-
-DROP FUNCTION intset(int4);
-
-DROP OPERATOR <@ (_int4, _int4);
-
-DROP OPERATOR @> (_int4, _int4);
-
-DROP OPERATOR ~ (_int4, _int4);
-
-DROP OPERATOR @ (_int4, _int4);
-
-DROP OPERATOR && (_int4, _int4);
-
-DROP FUNCTION _int_inter(_int4, _int4);
-
-DROP FUNCTION _int_union(_int4, _int4);
-
-DROP FUNCTION _int_different(_int4, _int4);
-
-DROP FUNCTION _int_same(_int4, _int4);
-
-DROP FUNCTION _int_overlap(_int4, _int4);
-
-DROP FUNCTION _int_contained(_int4, _int4);
-
-DROP FUNCTION _int_contains(_int4, _int4);
-
-DROP OPERATOR ~~ (query_int, _int4);
-
-DROP OPERATOR @@ (_int4, query_int);
-
-DROP FUNCTION rboolop(query_int, _int4);
-
-DROP FUNCTION boolop(_int4, query_int);
-
-DROP FUNCTION querytree(query_int);
-
-DROP TYPE query_int CASCADE;
diff --git a/contrib/isn/EAN13.h b/contrib/isn/EAN13.h
index 87b611a542..7023ebdf63 100644
--- a/contrib/isn/EAN13.h
+++ b/contrib/isn/EAN13.h
@@ -6,7 +6,7 @@
* http://www.gs1.org/productssolutions/idkeys/support/prefix_list.html
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/isn/EAN13.h,v 1.2 2006/10/04 00:29:45 momjian Exp $
+ * contrib/isn/EAN13.h
*
*/
diff --git a/contrib/isn/ISBN.h b/contrib/isn/ISBN.h
index 26c84afe80..dbda6fb724 100644
--- a/contrib/isn/ISBN.h
+++ b/contrib/isn/ISBN.h
@@ -7,7 +7,7 @@
* http://www.isbn.org/
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/isn/ISBN.h,v 1.2 2006/10/04 00:29:45 momjian Exp $
+ * contrib/isn/ISBN.h
*
* 0-393-04002-X => 039304002(X) <=> 039304002 <=> (978)039304002 <=> 978039304002(9) <=> 978-0-393-04002-9
*
@@ -28,18 +28,23 @@
*
*/
+/*
+ * For ISBN with prefix 978
+ * Range Table as of 2010-Jul-29
+ */
+
/* where the digit set begins, and how many of them are in the table */
const unsigned ISBN_index[10][2] = {
{0, 6},
{6, 6},
{12, 8},
- {20, 10},
- {30, 6},
- {36, 12},
- {48, 0},
- {48, 5},
- {53, 59},
- {112, 573},
+ {20, 14},
+ {34, 6},
+ {40, 19},
+ {59, 68},
+ {127, 5},
+ {132, 60},
+ {192, 718},
};
const char *ISBN_range[][2] = {
@@ -72,7 +77,11 @@ const char *ISBN_range[][2] = {
{"3-7000", "3-8499"},
{"3-85000", "3-89999"},
{"3-900000", "3-949999"},
- {"3-9500000", "3-9999999"},
+ {"3-9500000", "3-9539999"},
+ {"3-95400", "3-96999"},
+ {"3-9700000", "3-9899999"},
+ {"3-99000", "3-99499"},
+ {"3-99500", "3-99999"},
{"4-00", "4-19"},
{"4-200", "4-699"},
{"4-7000", "4-8499"},
@@ -80,17 +89,92 @@ const char *ISBN_range[][2] = {
{"4-900000", "4-949999"},
{"4-9500000", "4-9999999"},
{"5-00", "5-19"},
- {"5-200", "5-699"},
+ {"5-200", "5-420"},
+ {"5-4210", "5-4299"},
+ {"5-430", "5-430"},
+ {"5-4310", "5-4399"},
+ {"5-440", "5-440"},
+ {"5-4410", "5-4499"},
+ {"5-450", "5-699"},
{"5-7000", "5-8499"},
{"5-85000", "5-89999"},
{"5-900000", "5-909999"},
{"5-91000", "5-91999"},
{"5-9200", "5-9299"},
{"5-93000", "5-94999"},
- {"5-9500", "5-9799"},
+ {"5-9500000", "5-9500999"},
+ {"5-9501", "5-9799"},
{"5-98000", "5-98999"},
{"5-9900000", "5-9909999"},
{"5-9910", "5-9999"},
+ {"600-00", "600-09"},
+ {"600-100", "600-499"},
+ {"600-5000", "600-8999"},
+ {"600-90000", "600-99999"},
+ {"601-00", "601-19"},
+ {"601-200", "601-699"},
+ {"601-7000", "601-7999"},
+ {"601-80000", "601-84999"},
+ {"601-85", "601-99"},
+ {"602-00", "602-19"},
+ {"602-200", "602-799"},
+ {"602-8000", "602-9499"},
+ {"602-95000", "602-99999"},
+ {"603-00", "603-04"},
+ {"603-05", "603-49"},
+ {"603-500", "603-799"},
+ {"603-8000", "603-8999"},
+ {"603-90000", "603-99999"},
+ {"604-0", "604-4"},
+ {"604-50", "604-89"},
+ {"604-900", "604-979"},
+ {"604-9800", "604-9999"},
+ {"605-01", "605-09"},
+ {"605-100", "605-399"},
+ {"605-4000", "605-5999"},
+ {"605-60000", "605-89999"},
+ {"605-90", "605-99"},
+ {"606-0", "606-0"},
+ {"606-10", "606-49"},
+ {"606-500", "606-799"},
+ {"606-8000", "606-9199"},
+ {"606-92000", "606-99999"},
+ {"607-00", "607-39"},
+ {"607-400", "607-749"},
+ {"607-7500", "607-9499"},
+ {"607-95000", "607-99999"},
+ {"608-0", "608-0"},
+ {"608-10", "608-19"},
+ {"608-200", "608-449"},
+ {"608-4500", "608-6499"},
+ {"608-65000", "608-69999"},
+ {"608-7", "608-9"},
+ {"609-00", "609-39"},
+ {"609-400", "609-799"},
+ {"609-8000", "609-9499"},
+ {"609-95000", "609-99999"},
+ {"612-00", "612-29"},
+ {"612-300", "612-399"},
+ {"612-4000", "612-4499"},
+ {"612-45000", "612-49999"},
+ {"612-50", "612-99"},
+ {"613-0", "613-9"},
+ {"614-00", "614-39"},
+ {"614-400", "614-799"},
+ {"614-8000", "614-9499"},
+ {"614-95000", "614-99999"},
+ {"615-00", "615-09"},
+ {"615-100", "615-499"},
+ {"615-5000", "615-7999"},
+ {"615-80000", "615-89999"},
+ {"616-00", "616-19"},
+ {"616-200", "616-699"},
+ {"616-7000", "616-8999"},
+ {"616-90000", "616-99999"},
+ {"617-00", "617-49"},
+ {"617-500", "617-699"},
+ {"617-7000", "617-8999"},
+ {"617-90000", "617-99999"},
{"7-00", "7-09"},
{"7-100", "7-499"},
{"7-5000", "7-7999"},
@@ -117,7 +201,8 @@ const char *ISBN_range[][2] = {
{"83-7000", "83-8499"},
{"83-85000", "83-89999"},
{"83-900000", "83-999999"},
- {"84-00", "84-19"},
+ {"84-00", "84-14"},
+ {"84-15000", "84-19999"},
{"84-200", "84-699"},
{"84-7000", "84-8499"},
{"84-85000", "84-89999"},
@@ -135,8 +220,8 @@ const char *ISBN_range[][2] = {
{"85-900000", "85-979999"},
{"85-98000", "85-99999"},
{"86-00", "86-29"},
- {"86-300", "86-699"},
- {"86-7000", "86-7999"},
+ {"86-300", "86-599"},
+ {"86-6000", "86-7999"},
{"86-80000", "86-89999"},
{"86-900000", "86-999999"},
{"87-00", "87-29"},
@@ -161,8 +246,10 @@ const char *ISBN_range[][2] = {
{"90-70000", "90-79999"},
{"90-800000", "90-849999"},
{"90-8500", "90-8999"},
- {"90-900000", "90-909999"},
- {"90-940000", "90-949999"},
+ {"90-90", "90-90"},
+ {"90-910000", "90-939999"},
+ {"90-94", "90-94"},
+ {"90-950000", "90-999999"},
{"91-0", "91-1"},
{"91-20", "91-49"},
{"91-500", "91-649"},
@@ -175,6 +262,14 @@ const char *ISBN_range[][2] = {
{"92-9000", "92-9499"},
{"92-95000", "92-98999"},
{"92-990000", "92-999999"},
+ {"93-00", "93-09"},
+ {"93-100", "93-499"},
+ {"93-5000", "93-7999"},
+ {"93-80000", "93-94999"},
+ {"93-950000", "93-999999"},
+ {"94-000", "94-599"},
+ {"94-6000", "94-8999"},
+ {"94-90000", "94-99999"},
{"950-00", "950-49"},
{"950-500", "950-899"},
{"950-9000", "950-9899"},
@@ -191,22 +286,24 @@ const char *ISBN_range[][2] = {
{"952-6600", "952-6699"},
{"952-67000", "952-69999"},
{"952-7000", "952-7999"},
- {"952-89", "952-94"},
+ {"952-80", "952-94"},
{"952-9500", "952-9899"},
{"952-99000", "952-99999"},
{"953-0", "953-0"},
{"953-10", "953-14"},
- {"953-150", "953-599"},
+ {"953-150", "953-549"},
+ {"953-55000", "953-59999"},
{"953-6000", "953-9499"},
{"953-95000", "953-99999"},
- {"954-00", "954-29"},
+ {"954-00", "954-28"},
+ {"954-2900", "954-2999"},
{"954-300", "954-799"},
{"954-8000", "954-8999"},
{"954-90000", "954-92999"},
{"954-9300", "954-9999"},
- {"955-0", "955-0"},
- {"955-1000", "955-1999"},
- {"955-20", "955-54"},
+ {"955-0000", "955-1999"},
+ {"955-20", "955-49"},
+ {"955-50000", "955-54999"},
{"955-550", "955-799"},
{"955-8000", "955-9499"},
{"955-95000", "955-99999"},
@@ -223,19 +320,24 @@ const char *ISBN_range[][2] = {
{"957-440", "957-819"},
{"957-8200", "957-9699"},
{"957-97000", "957-99999"},
- {"958-00", "958-59"},
+ {"958-00", "958-56"},
+ {"958-57000", "958-59999"},
{"958-600", "958-799"},
{"958-8000", "958-9499"},
{"958-95000", "958-99999"},
{"959-00", "959-19"},
{"959-200", "959-699"},
{"959-7000", "959-8499"},
+ {"959-85000", "959-99999"},
{"960-00", "960-19"},
{"960-200", "960-659"},
{"960-6600", "960-6899"},
{"960-690", "960-699"},
{"960-7000", "960-8499"},
- {"960-85000", "960-99999"},
+ {"960-85000", "960-92999"},
+ {"960-93", "960-93"},
+ {"960-9400", "960-9799"},
+ {"960-98000", "960-99999"},
{"961-00", "961-19"},
{"961-200", "961-599"},
{"961-6000", "961-8999"},
@@ -263,12 +365,16 @@ const char *ISBN_range[][2] = {
{"965-200", "965-599"},
{"965-7000", "965-7999"},
{"965-90000", "965-99999"},
- {"966-00", "966-28"},
- {"966-2900", "966-2999"},
+ {"966-00", "966-14"},
+ {"966-1500", "966-1699"},
+ {"966-170", "966-199"},
+ {"966-2000", "966-2999"},
{"966-300", "966-699"},
{"966-7000", "966-8999"},
{"966-90000", "966-99999"},
- {"967-0", "967-5"},
+ {"967-00", "967-29"},
+ {"967-300", "967-499"},
+ {"967-5000", "967-5999"},
{"967-60", "967-89"},
{"967-900", "967-989"},
{"967-9900", "967-9989"},
@@ -287,21 +393,24 @@ const char *ISBN_range[][2] = {
{"970-9000", "970-9099"},
{"970-91000", "970-96999"},
{"970-9700", "970-9999"},
- {"971-000", "971-019"},
+ {"971-000", "971-015"},
+ {"971-0160", "971-0199"},
{"971-02", "971-02"},
{"971-0300", "971-0599"},
{"971-06", "971-09"},
{"971-10", "971-49"},
{"971-500", "971-849"},
{"971-8500", "971-9099"},
- {"971-91000", "971-99999"},
+ {"971-91000", "971-98999"},
+ {"971-9900", "971-9999"},
{"972-0", "972-1"},
{"972-20", "972-54"},
{"972-550", "972-799"},
{"972-8000", "972-9499"},
{"972-95000", "972-99999"},
{"973-0", "973-0"},
- {"973-100", "973-199"},
+ {"973-100", "973-169"},
+ {"973-1700", "973-1999"},
{"973-20", "973-54"},
{"973-550", "973-759"},
{"973-7600", "973-8499"},
@@ -315,7 +424,8 @@ const char *ISBN_range[][2] = {
{"974-90000", "974-94999"},
{"974-9500", "974-9999"},
{"975-00000", "975-00999"},
- {"975-01", "975-24"},
+ {"975-01", "975-01"},
+ {"975-02", "975-24"},
{"975-250", "975-599"},
{"975-6000", "975-9199"},
{"975-92000", "975-98999"},
@@ -345,17 +455,20 @@ const char *ISBN_range[][2] = {
{"980-00", "980-19"},
{"980-200", "980-599"},
{"980-6000", "980-9999"},
- {"981-00", "981-19"},
- {"981-200", "981-299"},
- {"981-3000", "981-9999"},
+ {"981-00", "981-11"},
+ {"981-1200", "981-1999"},
+ {"981-200", "981-289"},
+ {"981-2900", "981-9999"},
{"982-00", "982-09"},
{"982-100", "982-699"},
{"982-70", "982-89"},
- {"982-9000", "982-9999"},
+ {"982-9000", "982-9799"},
+ {"982-98000", "982-99999"},
{"983-00", "983-01"},
{"983-020", "983-199"},
{"983-2000", "983-3999"},
- {"983-40000", "983-49999"},
+ {"983-40000", "983-44999"},
+ {"983-45", "983-49"},
{"983-50", "983-79"},
{"983-800", "983-899"},
{"983-9000", "983-9899"},
@@ -379,7 +492,8 @@ const char *ISBN_range[][2] = {
{"987-500", "987-899"},
{"987-9000", "987-9499"},
{"987-95000", "987-99999"},
- {"988-00", "988-19"},
+ {"988-00", "988-16"},
+ {"988-17000", "988-19999"},
{"988-200", "988-799"},
{"988-8000", "988-9699"},
{"988-97000", "988-99999"},
@@ -388,13 +502,79 @@ const char *ISBN_range[][2] = {
{"989-550", "989-799"},
{"989-8000", "989-9499"},
{"989-95000", "989-99999"},
- {"9944-0", "9944-2"},
- {"9944-300", "9944-499"},
+ {"9927-00", "9927-09"},
+ {"9927-100", "9927-399"},
+ {"9927-4000", "9927-4999"},
+ {"9928-00", "9928-09"},
+ {"9928-100", "9928-399"},
+ {"9928-4000", "9928-4999"},
+ {"9929-0", "9929-3"},
+ {"9929-40", "9929-54"},
+ {"9929-550", "9929-799"},
+ {"9929-8000", "9929-9999"},
+ {"9930-00", "9930-49"},
+ {"9930-500", "9930-939"},
+ {"9930-9400", "9930-9999"},
+ {"9931-00", "9931-29"},
+ {"9931-300", "9931-899"},
+ {"9931-9000", "9931-9999"},
+ {"9932-00", "9932-39"},
+ {"9932-400", "9932-849"},
+ {"9932-8500", "9932-9999"},
+ {"9933-0", "9933-0"},
+ {"9933-10", "9933-39"},
+ {"9933-400", "9933-899"},
+ {"9933-9000", "9933-9999"},
+ {"9934-0", "9934-0"},
+ {"9934-10", "9934-49"},
+ {"9934-500", "9934-799"},
+ {"9934-8000", "9934-9999"},
+ {"9935-0", "9935-0"},
+ {"9935-10", "9935-39"},
+ {"9935-400", "9935-899"},
+ {"9935-9000", "9935-9999"},
+ {"9936-0", "9936-1"},
+ {"9936-20", "9936-39"},
+ {"9936-400", "9936-799"},
+ {"9936-8000", "9936-9999"},
+ {"9937-0", "9937-2"},
+ {"9937-30", "9937-49"},
+ {"9937-500", "9937-799"},
+ {"9937-8000", "9937-9999"},
+ {"9938-00", "9938-79"},
+ {"9938-800", "9938-949"},
+ {"9938-9500", "9938-9999"},
+ {"9939-0", "9939-4"},
+ {"9939-50", "9939-79"},
+ {"9939-800", "9939-899"},
+ {"9939-9000", "9939-9999"},
+ {"9940-0", "9940-1"},
+ {"9940-20", "9940-49"},
+ {"9940-500", "9940-899"},
+ {"9940-9000", "9940-9999"},
+ {"9941-0", "9941-0"},
+ {"9941-10", "9941-39"},
+ {"9941-400", "9941-899"},
+ {"9941-9000", "9941-9999"},
+ {"9942-00", "9942-89"},
+ {"9942-900", "9942-994"},
+ {"9942-9950", "9942-9999"},
+ {"9943-00", "9943-29"},
+ {"9943-300", "9943-399"},
+ {"9943-4000", "9943-9999"},
+ {"9944-0000", "9944-0999"},
+ {"9944-100", "9944-499"},
{"9944-5000", "9944-5999"},
- {"9944-60", "9944-89"},
+ {"9944-60", "9944-69"},
+ {"9944-700", "9944-799"},
+ {"9944-80", "9944-89"},
{"9944-900", "9944-999"},
- {"9945-00", "9945-39"},
- {"9945-400", "9945-849"},
+ {"9945-00", "9945-00"},
+ {"9945-010", "9945-079"},
+ {"9945-08", "9945-39"},
+ {"9945-400", "9945-569"},
+ {"9945-57", "9945-57"},
+ {"9945-580", "9945-849"},
{"9945-8500", "9945-9999"},
{"9946-0", "9946-1"},
{"9946-20", "9946-39"},
@@ -437,8 +617,10 @@ const char *ISBN_range[][2] = {
{"9956-400", "9956-899"},
{"9956-9000", "9956-9999"},
{"9957-00", "9957-39"},
- {"9957-400", "9957-849"},
- {"9957-8500", "9957-9999"},
+ {"9957-400", "9957-699"},
+ {"9957-70", "9957-84"},
+ {"9957-8500", "9957-8799"},
+ {"9957-88", "9957-99"},
{"9958-0", "9958-0"},
{"9958-10", "9958-49"},
{"9958-500", "9958-899"},
@@ -461,7 +643,8 @@ const char *ISBN_range[][2] = {
{"9962-8500", "9962-9999"},
{"9963-0", "9963-2"},
{"9963-30", "9963-54"},
- {"9963-550", "9963-749"},
+ {"9963-550", "9963-734"},
+ {"9963-7350", "9963-7499"},
{"9963-7500", "9963-9999"},
{"9964-0", "9964-6"},
{"9964-70", "9964-94"},
@@ -469,7 +652,8 @@ const char *ISBN_range[][2] = {
{"9965-00", "9965-39"},
{"9965-400", "9965-899"},
{"9965-9000", "9965-9999"},
- {"9966-00", "9966-69"},
+ {"9966-000", "9966-199"},
+ {"9966-20", "9966-69"},
{"9966-7000", "9966-7499"},
{"9966-750", "9966-959"},
{"9966-9600", "9966-9999"},
@@ -493,7 +677,9 @@ const char *ISBN_range[][2] = {
{"9972-30", "9972-59"},
{"9972-600", "9972-899"},
{"9972-9000", "9972-9999"},
- {"9973-0", "9973-0"},
+ {"9973-00", "9973-05"},
+ {"9973-060", "9973-089"},
+ {"9973-0900", "9973-0999"},
{"9973-10", "9973-69"},
{"9973-700", "9973-969"},
{"9973-9700", "9973-9999"},
@@ -511,7 +697,7 @@ const char *ISBN_range[][2] = {
{"9976-0", "9976-5"},
{"9976-60", "9976-89"},
{"9976-900", "9976-989"},
- {"9976-9990", "9976-9999"},
+ {"9976-9900", "9976-9999"},
{"9977-00", "9977-89"},
{"9977-900", "9977-989"},
{"9977-9900", "9977-9999"},
@@ -521,7 +707,9 @@ const char *ISBN_range[][2] = {
{"9978-950", "9978-989"},
{"9978-9900", "9978-9999"},
{"9979-0", "9979-4"},
- {"9979-50", "9979-75"},
+ {"9979-50", "9979-64"},
+ {"9979-650", "9979-659"},
+ {"9979-66", "9979-75"},
{"9979-760", "9979-899"},
{"9979-9000", "9979-9999"},
{"9980-0", "9980-3"},
@@ -581,7 +769,8 @@ const char *ISBN_range[][2] = {
{"99906-30", "99906-59"},
{"99906-600", "99906-699"},
{"99906-70", "99906-89"},
- {"99906-9", "99906-9"},
+ {"99906-90", "99906-94"},
+ {"99906-950", "99906-999"},
{"99908-0", "99908-0"},
{"99908-10", "99908-89"},
{"99908-900", "99908-999"},
@@ -602,7 +791,7 @@ const char *ISBN_range[][2] = {
{"99913-600", "99913-604"},
{"99914-0", "99914-4"},
{"99914-50", "99914-89"},
- {"99914-900", "99914-949"},
+ {"99914-900", "99914-999"},
{"99915-0", "99915-4"},
{"99915-50", "99915-79"},
{"99915-800", "99915-999"},
@@ -616,6 +805,7 @@ const char *ISBN_range[][2] = {
{"99918-40", "99918-79"},
{"99918-800", "99918-999"},
{"99919-0", "99919-2"},
+ {"99919-300", "99919-399"},
{"99919-40", "99919-69"},
{"99919-900", "99919-999"},
{"99920-0", "99920-4"},
@@ -632,8 +822,8 @@ const char *ISBN_range[][2] = {
{"99923-0", "99923-1"},
{"99923-20", "99923-79"},
{"99923-800", "99923-999"},
- {"99924-0", "99924-2"},
- {"99924-30", "99924-79"},
+ {"99924-0", "99924-1"},
+ {"99924-20", "99924-79"},
{"99924-800", "99924-999"},
{"99925-0", "99925-3"},
{"99925-40", "99925-79"},
@@ -669,8 +859,8 @@ const char *ISBN_range[][2] = {
{"99934-800", "99934-999"},
{"99935-0", "99935-2"},
{"99935-30", "99935-59"},
- {"99935-600", "99935-799"},
- {"99935-8", "99935-8"},
+ {"99935-600", "99935-699"},
+ {"99935-7", "99935-8"},
{"99935-90", "99935-99"},
{"99936-0", "99936-0"},
{"99936-10", "99936-59"},
@@ -689,8 +879,8 @@ const char *ISBN_range[][2] = {
{"99940-10", "99940-69"},
{"99940-700", "99940-999"},
{"99941-0", "99941-2"},
- {"99941-30", "99941-89"},
- {"99941-900", "99941-999"},
+ {"99941-30", "99941-79"},
+ {"99941-800", "99941-999"},
{"99942-0", "99942-4"},
{"99942-50", "99942-79"},
{"99942-800", "99942-999"},
@@ -718,15 +908,83 @@ const char *ISBN_range[][2] = {
{"99950-0", "99950-4"},
{"99950-50", "99950-79"},
{"99950-800", "99950-999"},
- {"99951-00", "99951-99"},
{"99952-0", "99952-4"},
{"99952-50", "99952-79"},
{"99952-800", "99952-999"},
{"99953-0", "99953-2"},
{"99953-30", "99953-79"},
- {"99953-800", "99953-999"},
+ {"99953-800", "99953-939"},
+ {"99953-94", "99953-99"},
{"99954-0", "99954-2"},
{"99954-30", "99954-69"},
{"99954-700", "99954-999"},
+ {"99955-0", "99955-1"},
+ {"99955-20", "99955-59"},
+ {"99955-600", "99955-799"},
+ {"99955-80", "99955-89"},
+ {"99955-90", "99955-99"},
+ {"99956-00", "99956-59"},
+ {"99956-600", "99956-859"},
+ {"99956-86", "99956-99"},
+ {"99957-0", "99957-1"},
+ {"99957-20", "99957-79"},
+ {"99957-800", "99957-999"},
+ {"99958-0", "99958-4"},
+ {"99958-50", "99958-94"},
+ {"99958-950", "99958-999"},
+ {"99959-0", "99959-2"},
+ {"99959-30", "99959-59"},
+ {"99959-600", "99959-999"},
+ {"99960-0", "99960-0"},
+ {"99960-10", "99960-94"},
+ {"99960-950", "99960-999"},
+ {"99961-0", "99961-3"},
+ {"99961-40", "99961-89"},
+ {"99961-900", "99961-999"},
+ {"99962-0", "99962-4"},
+ {"99962-50", "99962-79"},
+ {"99962-800", "99962-999"},
+ {"99963-00", "99963-49"},
+ {"99963-500", "99963-999"},
+ {"99964-0", "99964-1"},
+ {"99964-20", "99964-79"},
+ {"99964-800", "99964-999"},
+ {"99965-0", "99965-3"},
+ {"99965-40", "99965-79"},
+ {"99965-800", "99965-999"},
+ {"99966-0", "99966-2"},
+ {"99966-30", "99966-69"},
+ {"99966-700", "99966-799"},
+ {"99967-0", "99967-1"},
+ {"99967-20", "99967-59"},
+ {"99967-600", "99967-899"},
+ {NULL, NULL},
+};
+
+/*
+ * For ISBN with prefix 979
+ * Range Table as of 2010-Jul-29
+ */
+
+/* where the digit set begins, and how many of them are in the table */
+const unsigned ISBN_index_new[10][2] = {
+ {0, 0},
+ {0, 5},
+ {5, 0},
+ {5, 0},
+ {5, 0},
+ {5, 0},
+ {5, 0},
+ {5, 0},
+ {5, 0},
+ {5, 0},
+};
+
+const char *ISBN_range_new[][2] = {
+ {"10-00", "10-19"},
+ {"10-200", "10-699"},
+ {"10-7000", "10-8999"},
+ {"10-90000", "10-97599"},
+ {"10-976000", "10-999999"},
{NULL, NULL},
};
diff --git a/contrib/isn/ISMN.h b/contrib/isn/ISMN.h
index 1d7b2af8fd..281f2cdefc 100644
--- a/contrib/isn/ISMN.h
+++ b/contrib/isn/ISMN.h
@@ -6,7 +6,7 @@
* http://www.ismn-international.org
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/isn/ISMN.h,v 1.2 2006/10/04 00:29:45 momjian Exp $
+ * contrib/isn/ISMN.h
*
* M-3452-4680-5 <=> (0)-3452-4680-5 <=> 0345246805 <=> 9790345246805 <=> 979-0-3452-4680-5
*
diff --git a/contrib/isn/ISSN.h b/contrib/isn/ISSN.h
index 063a5d97f1..082efcff7c 100644
--- a/contrib/isn/ISSN.h
+++ b/contrib/isn/ISSN.h
@@ -6,7 +6,7 @@
* http://www.issn.org/
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/isn/ISSN.h,v 1.2 2006/10/04 00:29:45 momjian Exp $
+ * contrib/isn/ISSN.h
*
* 1144-875X <=> 1144875(X) <=> 1144875 <=> (977)1144875 <=> 9771144875(00) <=> 977114487500(7) <=> 977-1144-875-00-7
*
diff --git a/contrib/isn/Makefile b/contrib/isn/Makefile
index 8431921d83..bd8f193e93 100644
--- a/contrib/isn/Makefile
+++ b/contrib/isn/Makefile
@@ -1,8 +1,9 @@
-# $PostgreSQL: pgsql/contrib/isn/Makefile,v 1.3 2007/11/10 23:59:51 momjian Exp $
+# contrib/isn/Makefile
MODULES = isn
-DATA_built = isn.sql
-DATA = uninstall_isn.sql
+
+EXTENSION = isn
+DATA = isn--1.0.sql isn--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/isn/UPC.h b/contrib/isn/UPC.h
index 2b58a6b566..b95473e12d 100644
--- a/contrib/isn/UPC.h
+++ b/contrib/isn/UPC.h
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/isn/UPC.h,v 1.2 2006/10/04 00:29:45 momjian Exp $
+ * contrib/isn/UPC.h
*
*/
diff --git a/contrib/isn/isn.sql.in b/contrib/isn/isn--1.0.sql
index 1963fbbee3..336ad1db3c 100644
--- a/contrib/isn/isn.sql.in
+++ b/contrib/isn/isn--1.0.sql
@@ -1,7 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/isn/isn.sql.in,v 1.9 2008/11/30 19:01:29 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/isn/isn--1.0.sql */
-- Example:
-- create table test ( id isbn );
@@ -15,12 +12,12 @@ SET search_path = public;
-- Input and output functions and data types:
--
---------------------------------------------------
-CREATE OR REPLACE FUNCTION ean13_in(cstring)
+CREATE FUNCTION ean13_in(cstring)
RETURNS ean13
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ean13_out(ean13)
+CREATE FUNCTION ean13_out(ean13)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -33,12 +30,12 @@ CREATE TYPE ean13 (
COMMENT ON TYPE ean13
IS 'International European Article Number (EAN13)';
-CREATE OR REPLACE FUNCTION isbn13_in(cstring)
+CREATE FUNCTION isbn13_in(cstring)
RETURNS isbn13
AS 'MODULE_PATHNAME', 'isbn_in'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ean13_out(isbn13)
+CREATE FUNCTION ean13_out(isbn13)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -51,12 +48,12 @@ CREATE TYPE isbn13 (
COMMENT ON TYPE isbn13
IS 'International Standard Book Number 13 (ISBN13)';
-CREATE OR REPLACE FUNCTION ismn13_in(cstring)
+CREATE FUNCTION ismn13_in(cstring)
RETURNS ismn13
AS 'MODULE_PATHNAME', 'ismn_in'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ean13_out(ismn13)
+CREATE FUNCTION ean13_out(ismn13)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -69,12 +66,12 @@ CREATE TYPE ismn13 (
COMMENT ON TYPE ismn13
IS 'International Standard Music Number 13 (ISMN13)';
-CREATE OR REPLACE FUNCTION issn13_in(cstring)
+CREATE FUNCTION issn13_in(cstring)
RETURNS issn13
AS 'MODULE_PATHNAME', 'issn_in'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ean13_out(issn13)
+CREATE FUNCTION ean13_out(issn13)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -89,12 +86,12 @@ COMMENT ON TYPE issn13
-- Short format:
-CREATE OR REPLACE FUNCTION isbn_in(cstring)
+CREATE FUNCTION isbn_in(cstring)
RETURNS isbn
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isn_out(isbn)
+CREATE FUNCTION isn_out(isbn)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -107,12 +104,12 @@ CREATE TYPE isbn (
COMMENT ON TYPE isbn
IS 'International Standard Book Number (ISBN)';
-CREATE OR REPLACE FUNCTION ismn_in(cstring)
+CREATE FUNCTION ismn_in(cstring)
RETURNS ismn
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isn_out(ismn)
+CREATE FUNCTION isn_out(ismn)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -125,12 +122,12 @@ CREATE TYPE ismn (
COMMENT ON TYPE ismn
IS 'International Standard Music Number (ISMN)';
-CREATE OR REPLACE FUNCTION issn_in(cstring)
+CREATE FUNCTION issn_in(cstring)
RETURNS issn
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isn_out(issn)
+CREATE FUNCTION isn_out(issn)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -143,12 +140,12 @@ CREATE TYPE issn (
COMMENT ON TYPE issn
IS 'International Standard Serial Number (ISSN)';
-CREATE OR REPLACE FUNCTION upc_in(cstring)
+CREATE FUNCTION upc_in(cstring)
RETURNS upc
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isn_out(upc)
+CREATE FUNCTION isn_out(upc)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -166,249 +163,249 @@ COMMENT ON TYPE upc
--
---------------------------------------------------
-- EAN13:
-CREATE OR REPLACE FUNCTION isnlt(ean13, ean13)
+CREATE FUNCTION isnlt(ean13, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, ean13)
+CREATE FUNCTION isnle(ean13, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, ean13)
+CREATE FUNCTION isneq(ean13, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, ean13)
+CREATE FUNCTION isnge(ean13, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, ean13)
+CREATE FUNCTION isngt(ean13, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, ean13)
+CREATE FUNCTION isnne(ean13, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ean13, isbn13)
+CREATE FUNCTION isnlt(ean13, isbn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, isbn13)
+CREATE FUNCTION isnle(ean13, isbn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, isbn13)
+CREATE FUNCTION isneq(ean13, isbn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, isbn13)
+CREATE FUNCTION isnge(ean13, isbn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, isbn13)
+CREATE FUNCTION isngt(ean13, isbn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, isbn13)
+CREATE FUNCTION isnne(ean13, isbn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ean13, ismn13)
+CREATE FUNCTION isnlt(ean13, ismn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, ismn13)
+CREATE FUNCTION isnle(ean13, ismn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, ismn13)
+CREATE FUNCTION isneq(ean13, ismn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, ismn13)
+CREATE FUNCTION isnge(ean13, ismn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, ismn13)
+CREATE FUNCTION isngt(ean13, ismn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, ismn13)
+CREATE FUNCTION isnne(ean13, ismn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ean13, issn13)
+CREATE FUNCTION isnlt(ean13, issn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, issn13)
+CREATE FUNCTION isnle(ean13, issn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, issn13)
+CREATE FUNCTION isneq(ean13, issn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, issn13)
+CREATE FUNCTION isnge(ean13, issn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, issn13)
+CREATE FUNCTION isngt(ean13, issn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, issn13)
+CREATE FUNCTION isnne(ean13, issn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ean13, isbn)
+CREATE FUNCTION isnlt(ean13, isbn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, isbn)
+CREATE FUNCTION isnle(ean13, isbn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, isbn)
+CREATE FUNCTION isneq(ean13, isbn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, isbn)
+CREATE FUNCTION isnge(ean13, isbn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, isbn)
+CREATE FUNCTION isngt(ean13, isbn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, isbn)
+CREATE FUNCTION isnne(ean13, isbn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ean13, ismn)
+CREATE FUNCTION isnlt(ean13, ismn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, ismn)
+CREATE FUNCTION isnle(ean13, ismn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, ismn)
+CREATE FUNCTION isneq(ean13, ismn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, ismn)
+CREATE FUNCTION isnge(ean13, ismn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, ismn)
+CREATE FUNCTION isngt(ean13, ismn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, ismn)
+CREATE FUNCTION isnne(ean13, ismn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ean13, issn)
+CREATE FUNCTION isnlt(ean13, issn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, issn)
+CREATE FUNCTION isnle(ean13, issn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, issn)
+CREATE FUNCTION isneq(ean13, issn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, issn)
+CREATE FUNCTION isnge(ean13, issn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, issn)
+CREATE FUNCTION isngt(ean13, issn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, issn)
+CREATE FUNCTION isnne(ean13, issn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ean13, upc)
+CREATE FUNCTION isnlt(ean13, upc)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ean13, upc)
+CREATE FUNCTION isnle(ean13, upc)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ean13, upc)
+CREATE FUNCTION isneq(ean13, upc)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ean13, upc)
+CREATE FUNCTION isnge(ean13, upc)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ean13, upc)
+CREATE FUNCTION isngt(ean13, upc)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ean13, upc)
+CREATE FUNCTION isnne(ean13, upc)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -416,94 +413,94 @@ CREATE OR REPLACE FUNCTION isnne(ean13, upc)
---------------------------------------------------
-- ISBN13:
-CREATE OR REPLACE FUNCTION isnlt(isbn13, isbn13)
+CREATE FUNCTION isnlt(isbn13, isbn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(isbn13, isbn13)
+CREATE FUNCTION isnle(isbn13, isbn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(isbn13, isbn13)
+CREATE FUNCTION isneq(isbn13, isbn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(isbn13, isbn13)
+CREATE FUNCTION isnge(isbn13, isbn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(isbn13, isbn13)
+CREATE FUNCTION isngt(isbn13, isbn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(isbn13, isbn13)
+CREATE FUNCTION isnne(isbn13, isbn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(isbn13, isbn)
+CREATE FUNCTION isnlt(isbn13, isbn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(isbn13, isbn)
+CREATE FUNCTION isnle(isbn13, isbn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(isbn13, isbn)
+CREATE FUNCTION isneq(isbn13, isbn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(isbn13, isbn)
+CREATE FUNCTION isnge(isbn13, isbn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(isbn13, isbn)
+CREATE FUNCTION isngt(isbn13, isbn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(isbn13, isbn)
+CREATE FUNCTION isnne(isbn13, isbn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(isbn13, ean13)
+CREATE FUNCTION isnlt(isbn13, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(isbn13, ean13)
+CREATE FUNCTION isnle(isbn13, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(isbn13, ean13)
+CREATE FUNCTION isneq(isbn13, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(isbn13, ean13)
+CREATE FUNCTION isnge(isbn13, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(isbn13, ean13)
+CREATE FUNCTION isngt(isbn13, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(isbn13, ean13)
+CREATE FUNCTION isnne(isbn13, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -511,94 +508,94 @@ CREATE OR REPLACE FUNCTION isnne(isbn13, ean13)
---------------------------------------------------
-- ISBN:
-CREATE OR REPLACE FUNCTION isnlt(isbn, isbn)
+CREATE FUNCTION isnlt(isbn, isbn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(isbn, isbn)
+CREATE FUNCTION isnle(isbn, isbn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(isbn, isbn)
+CREATE FUNCTION isneq(isbn, isbn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(isbn, isbn)
+CREATE FUNCTION isnge(isbn, isbn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(isbn, isbn)
+CREATE FUNCTION isngt(isbn, isbn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(isbn, isbn)
+CREATE FUNCTION isnne(isbn, isbn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(isbn, isbn13)
+CREATE FUNCTION isnlt(isbn, isbn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(isbn, isbn13)
+CREATE FUNCTION isnle(isbn, isbn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(isbn, isbn13)
+CREATE FUNCTION isneq(isbn, isbn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(isbn, isbn13)
+CREATE FUNCTION isnge(isbn, isbn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(isbn, isbn13)
+CREATE FUNCTION isngt(isbn, isbn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(isbn, isbn13)
+CREATE FUNCTION isnne(isbn, isbn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(isbn, ean13)
+CREATE FUNCTION isnlt(isbn, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(isbn, ean13)
+CREATE FUNCTION isnle(isbn, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(isbn, ean13)
+CREATE FUNCTION isneq(isbn, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(isbn, ean13)
+CREATE FUNCTION isnge(isbn, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(isbn, ean13)
+CREATE FUNCTION isngt(isbn, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(isbn, ean13)
+CREATE FUNCTION isnne(isbn, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -606,94 +603,94 @@ CREATE OR REPLACE FUNCTION isnne(isbn, ean13)
---------------------------------------------------
-- ISMN13:
-CREATE OR REPLACE FUNCTION isnlt(ismn13, ismn13)
+CREATE FUNCTION isnlt(ismn13, ismn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ismn13, ismn13)
+CREATE FUNCTION isnle(ismn13, ismn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ismn13, ismn13)
+CREATE FUNCTION isneq(ismn13, ismn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ismn13, ismn13)
+CREATE FUNCTION isnge(ismn13, ismn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ismn13, ismn13)
+CREATE FUNCTION isngt(ismn13, ismn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ismn13, ismn13)
+CREATE FUNCTION isnne(ismn13, ismn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ismn13, ismn)
+CREATE FUNCTION isnlt(ismn13, ismn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ismn13, ismn)
+CREATE FUNCTION isnle(ismn13, ismn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ismn13, ismn)
+CREATE FUNCTION isneq(ismn13, ismn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ismn13, ismn)
+CREATE FUNCTION isnge(ismn13, ismn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ismn13, ismn)
+CREATE FUNCTION isngt(ismn13, ismn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ismn13, ismn)
+CREATE FUNCTION isnne(ismn13, ismn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ismn13, ean13)
+CREATE FUNCTION isnlt(ismn13, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ismn13, ean13)
+CREATE FUNCTION isnle(ismn13, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ismn13, ean13)
+CREATE FUNCTION isneq(ismn13, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ismn13, ean13)
+CREATE FUNCTION isnge(ismn13, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ismn13, ean13)
+CREATE FUNCTION isngt(ismn13, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ismn13, ean13)
+CREATE FUNCTION isnne(ismn13, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -701,94 +698,94 @@ CREATE OR REPLACE FUNCTION isnne(ismn13, ean13)
---------------------------------------------------
-- ISMN:
-CREATE OR REPLACE FUNCTION isnlt(ismn, ismn)
+CREATE FUNCTION isnlt(ismn, ismn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ismn, ismn)
+CREATE FUNCTION isnle(ismn, ismn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ismn, ismn)
+CREATE FUNCTION isneq(ismn, ismn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ismn, ismn)
+CREATE FUNCTION isnge(ismn, ismn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ismn, ismn)
+CREATE FUNCTION isngt(ismn, ismn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ismn, ismn)
+CREATE FUNCTION isnne(ismn, ismn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ismn, ismn13)
+CREATE FUNCTION isnlt(ismn, ismn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ismn, ismn13)
+CREATE FUNCTION isnle(ismn, ismn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ismn, ismn13)
+CREATE FUNCTION isneq(ismn, ismn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ismn, ismn13)
+CREATE FUNCTION isnge(ismn, ismn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ismn, ismn13)
+CREATE FUNCTION isngt(ismn, ismn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ismn, ismn13)
+CREATE FUNCTION isnne(ismn, ismn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(ismn, ean13)
+CREATE FUNCTION isnlt(ismn, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(ismn, ean13)
+CREATE FUNCTION isnle(ismn, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(ismn, ean13)
+CREATE FUNCTION isneq(ismn, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(ismn, ean13)
+CREATE FUNCTION isnge(ismn, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(ismn, ean13)
+CREATE FUNCTION isngt(ismn, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(ismn, ean13)
+CREATE FUNCTION isnne(ismn, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -796,94 +793,94 @@ CREATE OR REPLACE FUNCTION isnne(ismn, ean13)
---------------------------------------------------
-- ISSN13:
-CREATE OR REPLACE FUNCTION isnlt(issn13, issn13)
+CREATE FUNCTION isnlt(issn13, issn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(issn13, issn13)
+CREATE FUNCTION isnle(issn13, issn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(issn13, issn13)
+CREATE FUNCTION isneq(issn13, issn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(issn13, issn13)
+CREATE FUNCTION isnge(issn13, issn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(issn13, issn13)
+CREATE FUNCTION isngt(issn13, issn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(issn13, issn13)
+CREATE FUNCTION isnne(issn13, issn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(issn13, issn)
+CREATE FUNCTION isnlt(issn13, issn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(issn13, issn)
+CREATE FUNCTION isnle(issn13, issn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(issn13, issn)
+CREATE FUNCTION isneq(issn13, issn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(issn13, issn)
+CREATE FUNCTION isnge(issn13, issn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(issn13, issn)
+CREATE FUNCTION isngt(issn13, issn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(issn13, issn)
+CREATE FUNCTION isnne(issn13, issn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(issn13, ean13)
+CREATE FUNCTION isnlt(issn13, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(issn13, ean13)
+CREATE FUNCTION isnle(issn13, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(issn13, ean13)
+CREATE FUNCTION isneq(issn13, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(issn13, ean13)
+CREATE FUNCTION isnge(issn13, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(issn13, ean13)
+CREATE FUNCTION isngt(issn13, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(issn13, ean13)
+CREATE FUNCTION isnne(issn13, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -891,94 +888,94 @@ CREATE OR REPLACE FUNCTION isnne(issn13, ean13)
---------------------------------------------------
-- ISSN:
-CREATE OR REPLACE FUNCTION isnlt(issn, issn)
+CREATE FUNCTION isnlt(issn, issn)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(issn, issn)
+CREATE FUNCTION isnle(issn, issn)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(issn, issn)
+CREATE FUNCTION isneq(issn, issn)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(issn, issn)
+CREATE FUNCTION isnge(issn, issn)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(issn, issn)
+CREATE FUNCTION isngt(issn, issn)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(issn, issn)
+CREATE FUNCTION isnne(issn, issn)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(issn, issn13)
+CREATE FUNCTION isnlt(issn, issn13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(issn, issn13)
+CREATE FUNCTION isnle(issn, issn13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(issn, issn13)
+CREATE FUNCTION isneq(issn, issn13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(issn, issn13)
+CREATE FUNCTION isnge(issn, issn13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(issn, issn13)
+CREATE FUNCTION isngt(issn, issn13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(issn, issn13)
+CREATE FUNCTION isnne(issn, issn13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(issn, ean13)
+CREATE FUNCTION isnlt(issn, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(issn, ean13)
+CREATE FUNCTION isnle(issn, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(issn, ean13)
+CREATE FUNCTION isneq(issn, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(issn, ean13)
+CREATE FUNCTION isnge(issn, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(issn, ean13)
+CREATE FUNCTION isngt(issn, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(issn, ean13)
+CREATE FUNCTION isnne(issn, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -986,63 +983,63 @@ CREATE OR REPLACE FUNCTION isnne(issn, ean13)
---------------------------------------------------
-- UPC:
-CREATE OR REPLACE FUNCTION isnlt(upc, upc)
+CREATE FUNCTION isnlt(upc, upc)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(upc, upc)
+CREATE FUNCTION isnle(upc, upc)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(upc, upc)
+CREATE FUNCTION isneq(upc, upc)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(upc, upc)
+CREATE FUNCTION isnge(upc, upc)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(upc, upc)
+CREATE FUNCTION isngt(upc, upc)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(upc, upc)
+CREATE FUNCTION isnne(upc, upc)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnlt(upc, ean13)
+CREATE FUNCTION isnlt(upc, ean13)
RETURNS boolean
AS 'int8lt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnle(upc, ean13)
+CREATE FUNCTION isnle(upc, ean13)
RETURNS boolean
AS 'int8le'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isneq(upc, ean13)
+CREATE FUNCTION isneq(upc, ean13)
RETURNS boolean
AS 'int8eq'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnge(upc, ean13)
+CREATE FUNCTION isnge(upc, ean13)
RETURNS boolean
AS 'int8ge'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isngt(upc, ean13)
+CREATE FUNCTION isngt(upc, ean13)
RETURNS boolean
AS 'int8gt'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isnne(upc, ean13)
+CREATE FUNCTION isnne(upc, ean13)
RETURNS boolean
AS 'int8ne'
LANGUAGE 'internal'
@@ -2525,7 +2522,7 @@ CREATE OPERATOR FAMILY isn_ops USING hash;
--
---------------------------------------------------
-- EAN13:
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, ean13)
+CREATE FUNCTION btean13cmp(ean13, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2540,7 +2537,7 @@ CREATE OPERATOR CLASS ean13_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btean13cmp(ean13, ean13);
-CREATE OR REPLACE FUNCTION hashean13(ean13)
+CREATE FUNCTION hashean13(ean13)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal' IMMUTABLE STRICT;
@@ -2551,37 +2548,37 @@ CREATE OPERATOR CLASS ean13_ops DEFAULT
FUNCTION 1 hashean13(ean13);
-- EAN13 vs other types:
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, isbn13)
+CREATE FUNCTION btean13cmp(ean13, isbn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, ismn13)
+CREATE FUNCTION btean13cmp(ean13, ismn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, issn13)
+CREATE FUNCTION btean13cmp(ean13, issn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, isbn)
+CREATE FUNCTION btean13cmp(ean13, isbn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, ismn)
+CREATE FUNCTION btean13cmp(ean13, ismn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, issn)
+CREATE FUNCTION btean13cmp(ean13, issn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btean13cmp(ean13, upc)
+CREATE FUNCTION btean13cmp(ean13, upc)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2642,7 +2639,7 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
---------------------------------------------------
-- ISBN13:
-CREATE OR REPLACE FUNCTION btisbn13cmp(isbn13, isbn13)
+CREATE FUNCTION btisbn13cmp(isbn13, isbn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2657,7 +2654,7 @@ CREATE OPERATOR CLASS isbn13_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btisbn13cmp(isbn13, isbn13);
-CREATE OR REPLACE FUNCTION hashisbn13(isbn13)
+CREATE FUNCTION hashisbn13(isbn13)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal'
@@ -2669,12 +2666,12 @@ CREATE OPERATOR CLASS isbn13_ops DEFAULT
FUNCTION 1 hashisbn13(isbn13);
-- ISBN13 vs other types:
-CREATE OR REPLACE FUNCTION btisbn13cmp(isbn13, ean13)
+CREATE FUNCTION btisbn13cmp(isbn13, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btisbn13cmp(isbn13, isbn)
+CREATE FUNCTION btisbn13cmp(isbn13, isbn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2700,7 +2697,7 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
---------------------------------------------------
-- ISBN:
-CREATE OR REPLACE FUNCTION btisbncmp(isbn, isbn)
+CREATE FUNCTION btisbncmp(isbn, isbn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2715,7 +2712,7 @@ CREATE OPERATOR CLASS isbn_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btisbncmp(isbn, isbn);
-CREATE OR REPLACE FUNCTION hashisbn(isbn)
+CREATE FUNCTION hashisbn(isbn)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal'
@@ -2727,12 +2724,12 @@ CREATE OPERATOR CLASS isbn_ops DEFAULT
FUNCTION 1 hashisbn(isbn);
-- ISBN vs other types:
-CREATE OR REPLACE FUNCTION btisbncmp(isbn, ean13)
+CREATE FUNCTION btisbncmp(isbn, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btisbncmp(isbn, isbn13)
+CREATE FUNCTION btisbncmp(isbn, isbn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2758,7 +2755,7 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
---------------------------------------------------
-- ISMN13:
-CREATE OR REPLACE FUNCTION btismn13cmp(ismn13, ismn13)
+CREATE FUNCTION btismn13cmp(ismn13, ismn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2773,7 +2770,7 @@ CREATE OPERATOR CLASS ismn13_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btismn13cmp(ismn13, ismn13);
-CREATE OR REPLACE FUNCTION hashismn13(ismn13)
+CREATE FUNCTION hashismn13(ismn13)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal'
@@ -2785,12 +2782,12 @@ CREATE OPERATOR CLASS ismn13_ops DEFAULT
FUNCTION 1 hashismn13(ismn13);
-- ISMN13 vs other types:
-CREATE OR REPLACE FUNCTION btismn13cmp(ismn13, ean13)
+CREATE FUNCTION btismn13cmp(ismn13, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btismn13cmp(ismn13, ismn)
+CREATE FUNCTION btismn13cmp(ismn13, ismn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2816,7 +2813,7 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
---------------------------------------------------
-- ISMN:
-CREATE OR REPLACE FUNCTION btismncmp(ismn, ismn)
+CREATE FUNCTION btismncmp(ismn, ismn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2831,7 +2828,7 @@ CREATE OPERATOR CLASS ismn_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btismncmp(ismn, ismn);
-CREATE OR REPLACE FUNCTION hashismn(ismn)
+CREATE FUNCTION hashismn(ismn)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal'
@@ -2843,12 +2840,12 @@ CREATE OPERATOR CLASS ismn_ops DEFAULT
FUNCTION 1 hashismn(ismn);
-- ISMN vs other types:
-CREATE OR REPLACE FUNCTION btismncmp(ismn, ean13)
+CREATE FUNCTION btismncmp(ismn, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btismncmp(ismn, ismn13)
+CREATE FUNCTION btismncmp(ismn, ismn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2874,7 +2871,7 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
---------------------------------------------------
-- ISSN13:
-CREATE OR REPLACE FUNCTION btissn13cmp(issn13, issn13)
+CREATE FUNCTION btissn13cmp(issn13, issn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2889,7 +2886,7 @@ CREATE OPERATOR CLASS issn13_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btissn13cmp(issn13, issn13);
-CREATE OR REPLACE FUNCTION hashissn13(issn13)
+CREATE FUNCTION hashissn13(issn13)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal'
@@ -2901,12 +2898,12 @@ CREATE OPERATOR CLASS issn13_ops DEFAULT
FUNCTION 1 hashissn13(issn13);
-- ISSN13 vs other types:
-CREATE OR REPLACE FUNCTION btissn13cmp(issn13, ean13)
+CREATE FUNCTION btissn13cmp(issn13, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btissn13cmp(issn13, issn)
+CREATE FUNCTION btissn13cmp(issn13, issn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2932,7 +2929,7 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
---------------------------------------------------
-- ISSN:
-CREATE OR REPLACE FUNCTION btissncmp(issn, issn)
+CREATE FUNCTION btissncmp(issn, issn)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2947,7 +2944,7 @@ CREATE OPERATOR CLASS issn_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btissncmp(issn, issn);
-CREATE OR REPLACE FUNCTION hashissn(issn)
+CREATE FUNCTION hashissn(issn)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal'
@@ -2959,12 +2956,12 @@ CREATE OPERATOR CLASS issn_ops DEFAULT
FUNCTION 1 hashissn(issn);
-- ISSN vs other types:
-CREATE OR REPLACE FUNCTION btissncmp(issn, ean13)
+CREATE FUNCTION btissncmp(issn, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION btissncmp(issn, issn13)
+CREATE FUNCTION btissncmp(issn, issn13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -2990,7 +2987,7 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
---------------------------------------------------
-- UPC:
-CREATE OR REPLACE FUNCTION btupccmp(upc, upc)
+CREATE FUNCTION btupccmp(upc, upc)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -3005,7 +3002,7 @@ CREATE OPERATOR CLASS upc_ops DEFAULT
OPERATOR 5 >,
FUNCTION 1 btupccmp(upc, upc);
-CREATE OR REPLACE FUNCTION hashupc(upc)
+CREATE FUNCTION hashupc(upc)
RETURNS int4
AS 'hashint8'
LANGUAGE 'internal'
@@ -3017,7 +3014,7 @@ CREATE OPERATOR CLASS upc_ops DEFAULT
FUNCTION 1 hashupc(upc);
-- UPC vs other types:
-CREATE OR REPLACE FUNCTION btupccmp(upc, ean13)
+CREATE FUNCTION btupccmp(upc, ean13)
RETURNS int4
AS 'btint8cmp'
LANGUAGE 'internal'
@@ -3038,31 +3035,31 @@ ALTER OPERATOR FAMILY isn_ops USING hash ADD
-- Type casts:
--
---------------------------------------------------
-CREATE OR REPLACE FUNCTION isbn13(ean13)
+CREATE FUNCTION isbn13(ean13)
RETURNS isbn13
AS 'MODULE_PATHNAME', 'isbn_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ismn13(ean13)
+CREATE FUNCTION ismn13(ean13)
RETURNS ismn13
AS 'MODULE_PATHNAME', 'ismn_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION issn13(ean13)
+CREATE FUNCTION issn13(ean13)
RETURNS issn13
AS 'MODULE_PATHNAME', 'issn_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION isbn(ean13)
+CREATE FUNCTION isbn(ean13)
RETURNS isbn
AS 'MODULE_PATHNAME', 'isbn_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ismn(ean13)
+CREATE FUNCTION ismn(ean13)
RETURNS ismn
AS 'MODULE_PATHNAME', 'ismn_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION issn(ean13)
+CREATE FUNCTION issn(ean13)
RETURNS issn
AS 'MODULE_PATHNAME', 'issn_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION upc(ean13)
+CREATE FUNCTION upc(ean13)
RETURNS upc
AS 'MODULE_PATHNAME', 'upc_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
@@ -3094,83 +3091,83 @@ CREATE CAST (issn13 AS issn) WITHOUT FUNCTION AS ASSIGNMENT;
--
-- Validation stuff for lose types:
--
-CREATE OR REPLACE FUNCTION make_valid(ean13)
+CREATE FUNCTION make_valid(ean13)
RETURNS ean13
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION make_valid(isbn13)
+CREATE FUNCTION make_valid(isbn13)
RETURNS isbn13
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION make_valid(ismn13)
+CREATE FUNCTION make_valid(ismn13)
RETURNS ismn13
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION make_valid(issn13)
+CREATE FUNCTION make_valid(issn13)
RETURNS issn13
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION make_valid(isbn)
+CREATE FUNCTION make_valid(isbn)
RETURNS isbn
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION make_valid(ismn)
+CREATE FUNCTION make_valid(ismn)
RETURNS ismn
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION make_valid(issn)
+CREATE FUNCTION make_valid(issn)
RETURNS issn
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION make_valid(upc)
+CREATE FUNCTION make_valid(upc)
RETURNS upc
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(ean13)
+CREATE FUNCTION is_valid(ean13)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(isbn13)
+CREATE FUNCTION is_valid(isbn13)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(ismn13)
+CREATE FUNCTION is_valid(ismn13)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(issn13)
+CREATE FUNCTION is_valid(issn13)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(isbn)
+CREATE FUNCTION is_valid(isbn)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(ismn)
+CREATE FUNCTION is_valid(ismn)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(issn)
+CREATE FUNCTION is_valid(issn)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION is_valid(upc)
+CREATE FUNCTION is_valid(upc)
RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE 'C'
@@ -3180,7 +3177,7 @@ CREATE OR REPLACE FUNCTION is_valid(upc)
-- isn_weak(boolean) - Sets the weak input mode.
-- This function is intended for testing use only!
--
-CREATE OR REPLACE FUNCTION isn_weak(boolean)
+CREATE FUNCTION isn_weak(boolean)
RETURNS boolean
AS 'MODULE_PATHNAME', 'accept_weak_input'
LANGUAGE 'C'
@@ -3189,7 +3186,7 @@ CREATE OR REPLACE FUNCTION isn_weak(boolean)
--
-- isn_weak() - Gets the weak input mode status
--
-CREATE OR REPLACE FUNCTION isn_weak()
+CREATE FUNCTION isn_weak()
RETURNS boolean
AS 'MODULE_PATHNAME', 'weak_input_status'
LANGUAGE 'C'
diff --git a/contrib/isn/isn--unpackaged--1.0.sql b/contrib/isn/isn--unpackaged--1.0.sql
new file mode 100644
index 0000000000..6130a43e51
--- /dev/null
+++ b/contrib/isn/isn--unpackaged--1.0.sql
@@ -0,0 +1,461 @@
+/* contrib/isn/isn--unpackaged--1.0.sql */
+
+ALTER EXTENSION isn ADD type ean13;
+ALTER EXTENSION isn ADD function ean13_in(cstring);
+ALTER EXTENSION isn ADD function ean13_out(ean13);
+ALTER EXTENSION isn ADD type isbn13;
+ALTER EXTENSION isn ADD function isbn13_in(cstring);
+ALTER EXTENSION isn ADD function ean13_out(isbn13);
+ALTER EXTENSION isn ADD type ismn13;
+ALTER EXTENSION isn ADD function ismn13_in(cstring);
+ALTER EXTENSION isn ADD function ean13_out(ismn13);
+ALTER EXTENSION isn ADD type issn13;
+ALTER EXTENSION isn ADD function issn13_in(cstring);
+ALTER EXTENSION isn ADD function ean13_out(issn13);
+ALTER EXTENSION isn ADD type isbn;
+ALTER EXTENSION isn ADD function isbn_in(cstring);
+ALTER EXTENSION isn ADD function isn_out(isbn);
+ALTER EXTENSION isn ADD type ismn;
+ALTER EXTENSION isn ADD function ismn_in(cstring);
+ALTER EXTENSION isn ADD function isn_out(ismn);
+ALTER EXTENSION isn ADD type issn;
+ALTER EXTENSION isn ADD function issn_in(cstring);
+ALTER EXTENSION isn ADD function isn_out(issn);
+ALTER EXTENSION isn ADD type upc;
+ALTER EXTENSION isn ADD function upc_in(cstring);
+ALTER EXTENSION isn ADD function isn_out(upc);
+ALTER EXTENSION isn ADD function isnlt(ean13,ean13);
+ALTER EXTENSION isn ADD function isnle(ean13,ean13);
+ALTER EXTENSION isn ADD function isneq(ean13,ean13);
+ALTER EXTENSION isn ADD function isnge(ean13,ean13);
+ALTER EXTENSION isn ADD function isngt(ean13,ean13);
+ALTER EXTENSION isn ADD function isnne(ean13,ean13);
+ALTER EXTENSION isn ADD function isnlt(ean13,isbn13);
+ALTER EXTENSION isn ADD function isnle(ean13,isbn13);
+ALTER EXTENSION isn ADD function isneq(ean13,isbn13);
+ALTER EXTENSION isn ADD function isnge(ean13,isbn13);
+ALTER EXTENSION isn ADD function isngt(ean13,isbn13);
+ALTER EXTENSION isn ADD function isnne(ean13,isbn13);
+ALTER EXTENSION isn ADD function isnlt(ean13,ismn13);
+ALTER EXTENSION isn ADD function isnle(ean13,ismn13);
+ALTER EXTENSION isn ADD function isneq(ean13,ismn13);
+ALTER EXTENSION isn ADD function isnge(ean13,ismn13);
+ALTER EXTENSION isn ADD function isngt(ean13,ismn13);
+ALTER EXTENSION isn ADD function isnne(ean13,ismn13);
+ALTER EXTENSION isn ADD function isnlt(ean13,issn13);
+ALTER EXTENSION isn ADD function isnle(ean13,issn13);
+ALTER EXTENSION isn ADD function isneq(ean13,issn13);
+ALTER EXTENSION isn ADD function isnge(ean13,issn13);
+ALTER EXTENSION isn ADD function isngt(ean13,issn13);
+ALTER EXTENSION isn ADD function isnne(ean13,issn13);
+ALTER EXTENSION isn ADD function isnlt(ean13,isbn);
+ALTER EXTENSION isn ADD function isnle(ean13,isbn);
+ALTER EXTENSION isn ADD function isneq(ean13,isbn);
+ALTER EXTENSION isn ADD function isnge(ean13,isbn);
+ALTER EXTENSION isn ADD function isngt(ean13,isbn);
+ALTER EXTENSION isn ADD function isnne(ean13,isbn);
+ALTER EXTENSION isn ADD function isnlt(ean13,ismn);
+ALTER EXTENSION isn ADD function isnle(ean13,ismn);
+ALTER EXTENSION isn ADD function isneq(ean13,ismn);
+ALTER EXTENSION isn ADD function isnge(ean13,ismn);
+ALTER EXTENSION isn ADD function isngt(ean13,ismn);
+ALTER EXTENSION isn ADD function isnne(ean13,ismn);
+ALTER EXTENSION isn ADD function isnlt(ean13,issn);
+ALTER EXTENSION isn ADD function isnle(ean13,issn);
+ALTER EXTENSION isn ADD function isneq(ean13,issn);
+ALTER EXTENSION isn ADD function isnge(ean13,issn);
+ALTER EXTENSION isn ADD function isngt(ean13,issn);
+ALTER EXTENSION isn ADD function isnne(ean13,issn);
+ALTER EXTENSION isn ADD function isnlt(ean13,upc);
+ALTER EXTENSION isn ADD function isnle(ean13,upc);
+ALTER EXTENSION isn ADD function isneq(ean13,upc);
+ALTER EXTENSION isn ADD function isnge(ean13,upc);
+ALTER EXTENSION isn ADD function isngt(ean13,upc);
+ALTER EXTENSION isn ADD function isnne(ean13,upc);
+ALTER EXTENSION isn ADD function isnlt(isbn13,isbn13);
+ALTER EXTENSION isn ADD function isnle(isbn13,isbn13);
+ALTER EXTENSION isn ADD function isneq(isbn13,isbn13);
+ALTER EXTENSION isn ADD function isnge(isbn13,isbn13);
+ALTER EXTENSION isn ADD function isngt(isbn13,isbn13);
+ALTER EXTENSION isn ADD function isnne(isbn13,isbn13);
+ALTER EXTENSION isn ADD function isnlt(isbn13,isbn);
+ALTER EXTENSION isn ADD function isnle(isbn13,isbn);
+ALTER EXTENSION isn ADD function isneq(isbn13,isbn);
+ALTER EXTENSION isn ADD function isnge(isbn13,isbn);
+ALTER EXTENSION isn ADD function isngt(isbn13,isbn);
+ALTER EXTENSION isn ADD function isnne(isbn13,isbn);
+ALTER EXTENSION isn ADD function isnlt(isbn13,ean13);
+ALTER EXTENSION isn ADD function isnle(isbn13,ean13);
+ALTER EXTENSION isn ADD function isneq(isbn13,ean13);
+ALTER EXTENSION isn ADD function isnge(isbn13,ean13);
+ALTER EXTENSION isn ADD function isngt(isbn13,ean13);
+ALTER EXTENSION isn ADD function isnne(isbn13,ean13);
+ALTER EXTENSION isn ADD function isnlt(isbn,isbn);
+ALTER EXTENSION isn ADD function isnle(isbn,isbn);
+ALTER EXTENSION isn ADD function isneq(isbn,isbn);
+ALTER EXTENSION isn ADD function isnge(isbn,isbn);
+ALTER EXTENSION isn ADD function isngt(isbn,isbn);
+ALTER EXTENSION isn ADD function isnne(isbn,isbn);
+ALTER EXTENSION isn ADD function isnlt(isbn,isbn13);
+ALTER EXTENSION isn ADD function isnle(isbn,isbn13);
+ALTER EXTENSION isn ADD function isneq(isbn,isbn13);
+ALTER EXTENSION isn ADD function isnge(isbn,isbn13);
+ALTER EXTENSION isn ADD function isngt(isbn,isbn13);
+ALTER EXTENSION isn ADD function isnne(isbn,isbn13);
+ALTER EXTENSION isn ADD function isnlt(isbn,ean13);
+ALTER EXTENSION isn ADD function isnle(isbn,ean13);
+ALTER EXTENSION isn ADD function isneq(isbn,ean13);
+ALTER EXTENSION isn ADD function isnge(isbn,ean13);
+ALTER EXTENSION isn ADD function isngt(isbn,ean13);
+ALTER EXTENSION isn ADD function isnne(isbn,ean13);
+ALTER EXTENSION isn ADD function isnlt(ismn13,ismn13);
+ALTER EXTENSION isn ADD function isnle(ismn13,ismn13);
+ALTER EXTENSION isn ADD function isneq(ismn13,ismn13);
+ALTER EXTENSION isn ADD function isnge(ismn13,ismn13);
+ALTER EXTENSION isn ADD function isngt(ismn13,ismn13);
+ALTER EXTENSION isn ADD function isnne(ismn13,ismn13);
+ALTER EXTENSION isn ADD function isnlt(ismn13,ismn);
+ALTER EXTENSION isn ADD function isnle(ismn13,ismn);
+ALTER EXTENSION isn ADD function isneq(ismn13,ismn);
+ALTER EXTENSION isn ADD function isnge(ismn13,ismn);
+ALTER EXTENSION isn ADD function isngt(ismn13,ismn);
+ALTER EXTENSION isn ADD function isnne(ismn13,ismn);
+ALTER EXTENSION isn ADD function isnlt(ismn13,ean13);
+ALTER EXTENSION isn ADD function isnle(ismn13,ean13);
+ALTER EXTENSION isn ADD function isneq(ismn13,ean13);
+ALTER EXTENSION isn ADD function isnge(ismn13,ean13);
+ALTER EXTENSION isn ADD function isngt(ismn13,ean13);
+ALTER EXTENSION isn ADD function isnne(ismn13,ean13);
+ALTER EXTENSION isn ADD function isnlt(ismn,ismn);
+ALTER EXTENSION isn ADD function isnle(ismn,ismn);
+ALTER EXTENSION isn ADD function isneq(ismn,ismn);
+ALTER EXTENSION isn ADD function isnge(ismn,ismn);
+ALTER EXTENSION isn ADD function isngt(ismn,ismn);
+ALTER EXTENSION isn ADD function isnne(ismn,ismn);
+ALTER EXTENSION isn ADD function isnlt(ismn,ismn13);
+ALTER EXTENSION isn ADD function isnle(ismn,ismn13);
+ALTER EXTENSION isn ADD function isneq(ismn,ismn13);
+ALTER EXTENSION isn ADD function isnge(ismn,ismn13);
+ALTER EXTENSION isn ADD function isngt(ismn,ismn13);
+ALTER EXTENSION isn ADD function isnne(ismn,ismn13);
+ALTER EXTENSION isn ADD function isnlt(ismn,ean13);
+ALTER EXTENSION isn ADD function isnle(ismn,ean13);
+ALTER EXTENSION isn ADD function isneq(ismn,ean13);
+ALTER EXTENSION isn ADD function isnge(ismn,ean13);
+ALTER EXTENSION isn ADD function isngt(ismn,ean13);
+ALTER EXTENSION isn ADD function isnne(ismn,ean13);
+ALTER EXTENSION isn ADD function isnlt(issn13,issn13);
+ALTER EXTENSION isn ADD function isnle(issn13,issn13);
+ALTER EXTENSION isn ADD function isneq(issn13,issn13);
+ALTER EXTENSION isn ADD function isnge(issn13,issn13);
+ALTER EXTENSION isn ADD function isngt(issn13,issn13);
+ALTER EXTENSION isn ADD function isnne(issn13,issn13);
+ALTER EXTENSION isn ADD function isnlt(issn13,issn);
+ALTER EXTENSION isn ADD function isnle(issn13,issn);
+ALTER EXTENSION isn ADD function isneq(issn13,issn);
+ALTER EXTENSION isn ADD function isnge(issn13,issn);
+ALTER EXTENSION isn ADD function isngt(issn13,issn);
+ALTER EXTENSION isn ADD function isnne(issn13,issn);
+ALTER EXTENSION isn ADD function isnlt(issn13,ean13);
+ALTER EXTENSION isn ADD function isnle(issn13,ean13);
+ALTER EXTENSION isn ADD function isneq(issn13,ean13);
+ALTER EXTENSION isn ADD function isnge(issn13,ean13);
+ALTER EXTENSION isn ADD function isngt(issn13,ean13);
+ALTER EXTENSION isn ADD function isnne(issn13,ean13);
+ALTER EXTENSION isn ADD function isnlt(issn,issn);
+ALTER EXTENSION isn ADD function isnle(issn,issn);
+ALTER EXTENSION isn ADD function isneq(issn,issn);
+ALTER EXTENSION isn ADD function isnge(issn,issn);
+ALTER EXTENSION isn ADD function isngt(issn,issn);
+ALTER EXTENSION isn ADD function isnne(issn,issn);
+ALTER EXTENSION isn ADD function isnlt(issn,issn13);
+ALTER EXTENSION isn ADD function isnle(issn,issn13);
+ALTER EXTENSION isn ADD function isneq(issn,issn13);
+ALTER EXTENSION isn ADD function isnge(issn,issn13);
+ALTER EXTENSION isn ADD function isngt(issn,issn13);
+ALTER EXTENSION isn ADD function isnne(issn,issn13);
+ALTER EXTENSION isn ADD function isnlt(issn,ean13);
+ALTER EXTENSION isn ADD function isnle(issn,ean13);
+ALTER EXTENSION isn ADD function isneq(issn,ean13);
+ALTER EXTENSION isn ADD function isnge(issn,ean13);
+ALTER EXTENSION isn ADD function isngt(issn,ean13);
+ALTER EXTENSION isn ADD function isnne(issn,ean13);
+ALTER EXTENSION isn ADD function isnlt(upc,upc);
+ALTER EXTENSION isn ADD function isnle(upc,upc);
+ALTER EXTENSION isn ADD function isneq(upc,upc);
+ALTER EXTENSION isn ADD function isnge(upc,upc);
+ALTER EXTENSION isn ADD function isngt(upc,upc);
+ALTER EXTENSION isn ADD function isnne(upc,upc);
+ALTER EXTENSION isn ADD function isnlt(upc,ean13);
+ALTER EXTENSION isn ADD function isnle(upc,ean13);
+ALTER EXTENSION isn ADD function isneq(upc,ean13);
+ALTER EXTENSION isn ADD function isnge(upc,ean13);
+ALTER EXTENSION isn ADD function isngt(upc,ean13);
+ALTER EXTENSION isn ADD function isnne(upc,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,ean13);
+ALTER EXTENSION isn ADD operator <(ean13,ean13);
+ALTER EXTENSION isn ADD operator <=(ean13,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,ean13);
+ALTER EXTENSION isn ADD operator =(ean13,ean13);
+ALTER EXTENSION isn ADD operator >(isbn13,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,isbn13);
+ALTER EXTENSION isn ADD operator <(ean13,isbn13);
+ALTER EXTENSION isn ADD operator >=(isbn13,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,isbn13);
+ALTER EXTENSION isn ADD operator <=(ean13,isbn13);
+ALTER EXTENSION isn ADD operator =(isbn13,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,isbn13);
+ALTER EXTENSION isn ADD operator =(ean13,isbn13);
+ALTER EXTENSION isn ADD operator <=(isbn13,ean13);
+ALTER EXTENSION isn ADD operator <(isbn13,ean13);
+ALTER EXTENSION isn ADD operator <>(isbn13,ean13);
+ALTER EXTENSION isn ADD operator >(ismn13,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,ismn13);
+ALTER EXTENSION isn ADD operator <(ean13,ismn13);
+ALTER EXTENSION isn ADD operator >=(ismn13,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,ismn13);
+ALTER EXTENSION isn ADD operator <=(ean13,ismn13);
+ALTER EXTENSION isn ADD operator =(ismn13,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,ismn13);
+ALTER EXTENSION isn ADD operator =(ean13,ismn13);
+ALTER EXTENSION isn ADD operator <=(ismn13,ean13);
+ALTER EXTENSION isn ADD operator <(ismn13,ean13);
+ALTER EXTENSION isn ADD operator <>(ismn13,ean13);
+ALTER EXTENSION isn ADD operator >(issn13,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,issn13);
+ALTER EXTENSION isn ADD operator <(ean13,issn13);
+ALTER EXTENSION isn ADD operator >=(issn13,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,issn13);
+ALTER EXTENSION isn ADD operator <=(ean13,issn13);
+ALTER EXTENSION isn ADD operator =(issn13,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,issn13);
+ALTER EXTENSION isn ADD operator =(ean13,issn13);
+ALTER EXTENSION isn ADD operator <=(issn13,ean13);
+ALTER EXTENSION isn ADD operator <(issn13,ean13);
+ALTER EXTENSION isn ADD operator <>(issn13,ean13);
+ALTER EXTENSION isn ADD operator >(isbn,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,isbn);
+ALTER EXTENSION isn ADD operator <(ean13,isbn);
+ALTER EXTENSION isn ADD operator >=(isbn,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,isbn);
+ALTER EXTENSION isn ADD operator <=(ean13,isbn);
+ALTER EXTENSION isn ADD operator =(isbn,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,isbn);
+ALTER EXTENSION isn ADD operator =(ean13,isbn);
+ALTER EXTENSION isn ADD operator <=(isbn,ean13);
+ALTER EXTENSION isn ADD operator <(isbn,ean13);
+ALTER EXTENSION isn ADD operator <>(isbn,ean13);
+ALTER EXTENSION isn ADD operator >(ismn,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,ismn);
+ALTER EXTENSION isn ADD operator <(ean13,ismn);
+ALTER EXTENSION isn ADD operator >=(ismn,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,ismn);
+ALTER EXTENSION isn ADD operator <=(ean13,ismn);
+ALTER EXTENSION isn ADD operator =(ismn,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,ismn);
+ALTER EXTENSION isn ADD operator =(ean13,ismn);
+ALTER EXTENSION isn ADD operator <=(ismn,ean13);
+ALTER EXTENSION isn ADD operator <(ismn,ean13);
+ALTER EXTENSION isn ADD operator <>(ismn,ean13);
+ALTER EXTENSION isn ADD operator >(issn,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,issn);
+ALTER EXTENSION isn ADD operator <(ean13,issn);
+ALTER EXTENSION isn ADD operator >=(issn,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,issn);
+ALTER EXTENSION isn ADD operator <=(ean13,issn);
+ALTER EXTENSION isn ADD operator =(issn,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,issn);
+ALTER EXTENSION isn ADD operator =(ean13,issn);
+ALTER EXTENSION isn ADD operator <=(issn,ean13);
+ALTER EXTENSION isn ADD operator <(issn,ean13);
+ALTER EXTENSION isn ADD operator <>(issn,ean13);
+ALTER EXTENSION isn ADD operator >(upc,ean13);
+ALTER EXTENSION isn ADD operator >=(ean13,upc);
+ALTER EXTENSION isn ADD operator <(ean13,upc);
+ALTER EXTENSION isn ADD operator >=(upc,ean13);
+ALTER EXTENSION isn ADD operator >(ean13,upc);
+ALTER EXTENSION isn ADD operator <=(ean13,upc);
+ALTER EXTENSION isn ADD operator =(upc,ean13);
+ALTER EXTENSION isn ADD operator <>(ean13,upc);
+ALTER EXTENSION isn ADD operator =(ean13,upc);
+ALTER EXTENSION isn ADD operator <=(upc,ean13);
+ALTER EXTENSION isn ADD operator <(upc,ean13);
+ALTER EXTENSION isn ADD operator <>(upc,ean13);
+ALTER EXTENSION isn ADD operator >(isbn13,isbn13);
+ALTER EXTENSION isn ADD operator >=(isbn13,isbn13);
+ALTER EXTENSION isn ADD operator <(isbn13,isbn13);
+ALTER EXTENSION isn ADD operator <=(isbn13,isbn13);
+ALTER EXTENSION isn ADD operator <>(isbn13,isbn13);
+ALTER EXTENSION isn ADD operator =(isbn13,isbn13);
+ALTER EXTENSION isn ADD operator >(isbn,isbn13);
+ALTER EXTENSION isn ADD operator >=(isbn13,isbn);
+ALTER EXTENSION isn ADD operator <(isbn13,isbn);
+ALTER EXTENSION isn ADD operator >=(isbn,isbn13);
+ALTER EXTENSION isn ADD operator >(isbn13,isbn);
+ALTER EXTENSION isn ADD operator <=(isbn13,isbn);
+ALTER EXTENSION isn ADD operator =(isbn,isbn13);
+ALTER EXTENSION isn ADD operator <>(isbn13,isbn);
+ALTER EXTENSION isn ADD operator =(isbn13,isbn);
+ALTER EXTENSION isn ADD operator <=(isbn,isbn13);
+ALTER EXTENSION isn ADD operator <(isbn,isbn13);
+ALTER EXTENSION isn ADD operator <>(isbn,isbn13);
+ALTER EXTENSION isn ADD operator >(isbn,isbn);
+ALTER EXTENSION isn ADD operator >=(isbn,isbn);
+ALTER EXTENSION isn ADD operator <(isbn,isbn);
+ALTER EXTENSION isn ADD operator <=(isbn,isbn);
+ALTER EXTENSION isn ADD operator <>(isbn,isbn);
+ALTER EXTENSION isn ADD operator =(isbn,isbn);
+ALTER EXTENSION isn ADD operator >(ismn13,ismn13);
+ALTER EXTENSION isn ADD operator >=(ismn13,ismn13);
+ALTER EXTENSION isn ADD operator <(ismn13,ismn13);
+ALTER EXTENSION isn ADD operator <=(ismn13,ismn13);
+ALTER EXTENSION isn ADD operator <>(ismn13,ismn13);
+ALTER EXTENSION isn ADD operator =(ismn13,ismn13);
+ALTER EXTENSION isn ADD operator >(ismn,ismn13);
+ALTER EXTENSION isn ADD operator >=(ismn13,ismn);
+ALTER EXTENSION isn ADD operator <(ismn13,ismn);
+ALTER EXTENSION isn ADD operator >=(ismn,ismn13);
+ALTER EXTENSION isn ADD operator >(ismn13,ismn);
+ALTER EXTENSION isn ADD operator <=(ismn13,ismn);
+ALTER EXTENSION isn ADD operator =(ismn,ismn13);
+ALTER EXTENSION isn ADD operator <>(ismn13,ismn);
+ALTER EXTENSION isn ADD operator =(ismn13,ismn);
+ALTER EXTENSION isn ADD operator <=(ismn,ismn13);
+ALTER EXTENSION isn ADD operator <(ismn,ismn13);
+ALTER EXTENSION isn ADD operator <>(ismn,ismn13);
+ALTER EXTENSION isn ADD operator >(ismn,ismn);
+ALTER EXTENSION isn ADD operator >=(ismn,ismn);
+ALTER EXTENSION isn ADD operator <(ismn,ismn);
+ALTER EXTENSION isn ADD operator <=(ismn,ismn);
+ALTER EXTENSION isn ADD operator <>(ismn,ismn);
+ALTER EXTENSION isn ADD operator =(ismn,ismn);
+ALTER EXTENSION isn ADD operator >(issn13,issn13);
+ALTER EXTENSION isn ADD operator >=(issn13,issn13);
+ALTER EXTENSION isn ADD operator <(issn13,issn13);
+ALTER EXTENSION isn ADD operator <=(issn13,issn13);
+ALTER EXTENSION isn ADD operator <>(issn13,issn13);
+ALTER EXTENSION isn ADD operator =(issn13,issn13);
+ALTER EXTENSION isn ADD operator >(issn,issn13);
+ALTER EXTENSION isn ADD operator >=(issn13,issn);
+ALTER EXTENSION isn ADD operator <(issn13,issn);
+ALTER EXTENSION isn ADD operator >=(issn,issn13);
+ALTER EXTENSION isn ADD operator >(issn13,issn);
+ALTER EXTENSION isn ADD operator <=(issn13,issn);
+ALTER EXTENSION isn ADD operator =(issn,issn13);
+ALTER EXTENSION isn ADD operator <>(issn13,issn);
+ALTER EXTENSION isn ADD operator =(issn13,issn);
+ALTER EXTENSION isn ADD operator <=(issn,issn13);
+ALTER EXTENSION isn ADD operator <(issn,issn13);
+ALTER EXTENSION isn ADD operator <>(issn,issn13);
+ALTER EXTENSION isn ADD operator >(issn,issn);
+ALTER EXTENSION isn ADD operator >=(issn,issn);
+ALTER EXTENSION isn ADD operator <(issn,issn);
+ALTER EXTENSION isn ADD operator <=(issn,issn);
+ALTER EXTENSION isn ADD operator <>(issn,issn);
+ALTER EXTENSION isn ADD operator =(issn,issn);
+ALTER EXTENSION isn ADD operator >(upc,upc);
+ALTER EXTENSION isn ADD operator >=(upc,upc);
+ALTER EXTENSION isn ADD operator <(upc,upc);
+ALTER EXTENSION isn ADD operator <=(upc,upc);
+ALTER EXTENSION isn ADD operator <>(upc,upc);
+ALTER EXTENSION isn ADD operator =(upc,upc);
+ALTER EXTENSION isn ADD operator family isn_ops using btree;
+ALTER EXTENSION isn ADD operator family isn_ops using hash;
+ALTER EXTENSION isn ADD function btean13cmp(ean13,ean13);
+ALTER EXTENSION isn ADD operator class ean13_ops using btree;
+ALTER EXTENSION isn ADD function hashean13(ean13);
+ALTER EXTENSION isn ADD operator class ean13_ops using hash;
+ALTER EXTENSION isn ADD function btean13cmp(ean13,isbn13);
+ALTER EXTENSION isn ADD function btean13cmp(ean13,ismn13);
+ALTER EXTENSION isn ADD function btean13cmp(ean13,issn13);
+ALTER EXTENSION isn ADD function btean13cmp(ean13,isbn);
+ALTER EXTENSION isn ADD function btean13cmp(ean13,ismn);
+ALTER EXTENSION isn ADD function btean13cmp(ean13,issn);
+ALTER EXTENSION isn ADD function btean13cmp(ean13,upc);
+ALTER EXTENSION isn ADD function btisbn13cmp(isbn13,isbn13);
+ALTER EXTENSION isn ADD operator class isbn13_ops using btree;
+ALTER EXTENSION isn ADD function hashisbn13(isbn13);
+ALTER EXTENSION isn ADD operator class isbn13_ops using hash;
+ALTER EXTENSION isn ADD function btisbn13cmp(isbn13,ean13);
+ALTER EXTENSION isn ADD function btisbn13cmp(isbn13,isbn);
+ALTER EXTENSION isn ADD function btisbncmp(isbn,isbn);
+ALTER EXTENSION isn ADD operator class isbn_ops using btree;
+ALTER EXTENSION isn ADD function hashisbn(isbn);
+ALTER EXTENSION isn ADD operator class isbn_ops using hash;
+ALTER EXTENSION isn ADD function btisbncmp(isbn,ean13);
+ALTER EXTENSION isn ADD function btisbncmp(isbn,isbn13);
+ALTER EXTENSION isn ADD function btismn13cmp(ismn13,ismn13);
+ALTER EXTENSION isn ADD operator class ismn13_ops using btree;
+ALTER EXTENSION isn ADD function hashismn13(ismn13);
+ALTER EXTENSION isn ADD operator class ismn13_ops using hash;
+ALTER EXTENSION isn ADD function btismn13cmp(ismn13,ean13);
+ALTER EXTENSION isn ADD function btismn13cmp(ismn13,ismn);
+ALTER EXTENSION isn ADD function btismncmp(ismn,ismn);
+ALTER EXTENSION isn ADD operator class ismn_ops using btree;
+ALTER EXTENSION isn ADD function hashismn(ismn);
+ALTER EXTENSION isn ADD operator class ismn_ops using hash;
+ALTER EXTENSION isn ADD function btismncmp(ismn,ean13);
+ALTER EXTENSION isn ADD function btismncmp(ismn,ismn13);
+ALTER EXTENSION isn ADD function btissn13cmp(issn13,issn13);
+ALTER EXTENSION isn ADD operator class issn13_ops using btree;
+ALTER EXTENSION isn ADD function hashissn13(issn13);
+ALTER EXTENSION isn ADD operator class issn13_ops using hash;
+ALTER EXTENSION isn ADD function btissn13cmp(issn13,ean13);
+ALTER EXTENSION isn ADD function btissn13cmp(issn13,issn);
+ALTER EXTENSION isn ADD function btissncmp(issn,issn);
+ALTER EXTENSION isn ADD operator class issn_ops using btree;
+ALTER EXTENSION isn ADD function hashissn(issn);
+ALTER EXTENSION isn ADD operator class issn_ops using hash;
+ALTER EXTENSION isn ADD function btissncmp(issn,ean13);
+ALTER EXTENSION isn ADD function btissncmp(issn,issn13);
+ALTER EXTENSION isn ADD function btupccmp(upc,upc);
+ALTER EXTENSION isn ADD operator class upc_ops using btree;
+ALTER EXTENSION isn ADD function hashupc(upc);
+ALTER EXTENSION isn ADD operator class upc_ops using hash;
+ALTER EXTENSION isn ADD function btupccmp(upc,ean13);
+ALTER EXTENSION isn ADD function isbn13(ean13);
+ALTER EXTENSION isn ADD function ismn13(ean13);
+ALTER EXTENSION isn ADD function issn13(ean13);
+ALTER EXTENSION isn ADD function isbn(ean13);
+ALTER EXTENSION isn ADD function ismn(ean13);
+ALTER EXTENSION isn ADD function issn(ean13);
+ALTER EXTENSION isn ADD function upc(ean13);
+ALTER EXTENSION isn ADD cast (ean13 as isbn13);
+ALTER EXTENSION isn ADD cast (ean13 as isbn);
+ALTER EXTENSION isn ADD cast (ean13 as ismn13);
+ALTER EXTENSION isn ADD cast (ean13 as ismn);
+ALTER EXTENSION isn ADD cast (ean13 as issn13);
+ALTER EXTENSION isn ADD cast (ean13 as issn);
+ALTER EXTENSION isn ADD cast (ean13 as upc);
+ALTER EXTENSION isn ADD cast (isbn13 as ean13);
+ALTER EXTENSION isn ADD cast (isbn as ean13);
+ALTER EXTENSION isn ADD cast (ismn13 as ean13);
+ALTER EXTENSION isn ADD cast (ismn as ean13);
+ALTER EXTENSION isn ADD cast (issn13 as ean13);
+ALTER EXTENSION isn ADD cast (issn as ean13);
+ALTER EXTENSION isn ADD cast (upc as ean13);
+ALTER EXTENSION isn ADD cast (isbn as isbn13);
+ALTER EXTENSION isn ADD cast (isbn13 as isbn);
+ALTER EXTENSION isn ADD cast (ismn as ismn13);
+ALTER EXTENSION isn ADD cast (ismn13 as ismn);
+ALTER EXTENSION isn ADD cast (issn as issn13);
+ALTER EXTENSION isn ADD cast (issn13 as issn);
+ALTER EXTENSION isn ADD function make_valid(ean13);
+ALTER EXTENSION isn ADD function make_valid(isbn13);
+ALTER EXTENSION isn ADD function make_valid(ismn13);
+ALTER EXTENSION isn ADD function make_valid(issn13);
+ALTER EXTENSION isn ADD function make_valid(isbn);
+ALTER EXTENSION isn ADD function make_valid(ismn);
+ALTER EXTENSION isn ADD function make_valid(issn);
+ALTER EXTENSION isn ADD function make_valid(upc);
+ALTER EXTENSION isn ADD function is_valid(ean13);
+ALTER EXTENSION isn ADD function is_valid(isbn13);
+ALTER EXTENSION isn ADD function is_valid(ismn13);
+ALTER EXTENSION isn ADD function is_valid(issn13);
+ALTER EXTENSION isn ADD function is_valid(isbn);
+ALTER EXTENSION isn ADD function is_valid(ismn);
+ALTER EXTENSION isn ADD function is_valid(issn);
+ALTER EXTENSION isn ADD function is_valid(upc);
+ALTER EXTENSION isn ADD function isn_weak(boolean);
+ALTER EXTENSION isn ADD function isn_weak();
diff --git a/contrib/isn/isn.c b/contrib/isn/isn.c
index dac760b111..b698cb00ff 100644
--- a/contrib/isn/isn.c
+++ b/contrib/isn/isn.c
@@ -4,10 +4,10 @@
* PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
*
* Author: German Mendez Bravo (Kronuz)
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/isn/isn.c,v 1.14 2010/02/26 02:00:32 momjian Exp $
+ * contrib/isn/isn.c
*
*-------------------------------------------------------------------------
*/
@@ -341,8 +341,7 @@ ean2isn(ean13 ean, bool errorOK, ean13 *result, enum isn_type accept)
enum isn_type type = INVALID;
char buf[MAXEAN13LEN + 1];
- char *firstdig,
- *aux;
+ char *aux;
unsigned digval;
unsigned search;
ean13 ret = ean;
@@ -354,7 +353,7 @@ ean2isn(ean13 ean, bool errorOK, ean13 *result, enum isn_type accept)
/* convert the number */
search = 0;
- firstdig = aux = buf + 13;
+ aux = buf + 13;
*aux = '\0'; /* terminate string; aux points to last digit */
do
{
@@ -528,8 +527,7 @@ ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
const unsigned (*TABLE_index)[2];
enum isn_type type = INVALID;
- char *firstdig,
- *aux;
+ char *aux;
unsigned digval;
unsigned search;
char valid = '\0'; /* was the number initially written with a
@@ -546,7 +544,7 @@ ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
/* convert the number */
search = 0;
- firstdig = aux = result + MAXEAN13LEN;
+ aux = result + MAXEAN13LEN;
*aux = '\0'; /* terminate string; aux points to last digit */
*--aux = valid; /* append '!' for numbers with invalid but
* corrected check digit */
@@ -573,7 +571,7 @@ ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
/* find out what type of hyphenation is needed: */
if (!strncmp("978-", result, search))
- { /* ISBN */
+ { /* ISBN -13 978-range */
/* The string should be in this form: 978-??000000000-0" */
type = ISBN;
TABLE = ISBN_range;
@@ -593,6 +591,13 @@ ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
TABLE = ISMN_range;
TABLE_index = ISMN_index;
}
+ else if (!strncmp("979-", result, search))
+ { /* ISBN-13 979-range */
+ /* The string should be in this form: 979-??000000000-0" */
+ type = ISBN;
+ TABLE = ISBN_range_new;
+ TABLE_index = ISBN_index_new;
+ }
else if (*result == '0')
{ /* UPC */
/* The string should be in this form: 000-00000000000-0" */
diff --git a/contrib/isn/isn.control b/contrib/isn/isn.control
new file mode 100644
index 0000000000..cf0b2ebe38
--- /dev/null
+++ b/contrib/isn/isn.control
@@ -0,0 +1,5 @@
+# isn extension
+comment = 'data types for international product numbering standards'
+default_version = '1.0'
+module_pathname = '$libdir/isn'
+relocatable = true
diff --git a/contrib/isn/isn.h b/contrib/isn/isn.h
index fdc72d9b53..3f478b5f4b 100644
--- a/contrib/isn/isn.h
+++ b/contrib/isn/isn.h
@@ -4,10 +4,10 @@
* PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
*
* Author: German Mendez Bravo (Kronuz)
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/isn/isn.h,v 1.10 2010/02/26 02:00:32 momjian Exp $
+ * contrib/isn/isn.h
*
*-------------------------------------------------------------------------
*/
diff --git a/contrib/isn/uninstall_isn.sql b/contrib/isn/uninstall_isn.sql
deleted file mode 100644
index cc7b573b04..0000000000
--- a/contrib/isn/uninstall_isn.sql
+++ /dev/null
@@ -1,24 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/isn/uninstall_isn.sql,v 1.4 2008/11/28 21:19:13 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
--- Drop the operator families (which don't depend on the types)
-DROP OPERATOR FAMILY isn_ops USING btree CASCADE;
-DROP OPERATOR FAMILY isn_ops USING hash CASCADE;
-
---
--- Drop the actual types (in cascade):
---
-DROP TYPE ean13 CASCADE;
-DROP TYPE isbn13 CASCADE;
-DROP TYPE ismn13 CASCADE;
-DROP TYPE issn13 CASCADE;
-DROP TYPE isbn CASCADE;
-DROP TYPE ismn CASCADE;
-DROP TYPE issn CASCADE;
-DROP TYPE upc CASCADE;
-
--- and clean up a couple miscellaneous functions
-DROP FUNCTION isn_weak();
-DROP FUNCTION isn_weak(boolean);
diff --git a/contrib/lo/Makefile b/contrib/lo/Makefile
index 336cb5685e..66b337c17a 100644
--- a/contrib/lo/Makefile
+++ b/contrib/lo/Makefile
@@ -1,8 +1,9 @@
-# $PostgreSQL: pgsql/contrib/lo/Makefile,v 1.17 2007/11/10 23:59:51 momjian Exp $
+# contrib/lo/Makefile
MODULES = lo
-DATA_built = lo.sql
-DATA = uninstall_lo.sql
+
+EXTENSION = lo
+DATA = lo--1.0.sql lo--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/lo/lo.sql.in b/contrib/lo/lo--1.0.sql
index 6dcf6659c5..4b9a7dee32 100644
--- a/contrib/lo/lo.sql.in
+++ b/contrib/lo/lo--1.0.sql
@@ -1,7 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/lo/lo.sql.in,v 1.15 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/lo/lo--1.0.sql */
--
-- Create the data type ... now just a domain over OID
@@ -15,11 +12,11 @@ CREATE DOMAIN lo AS pg_catalog.oid;
-- The other functions that formerly existed are not needed because
-- the implicit casts between a domain and its underlying type handle them.
--
-CREATE OR REPLACE FUNCTION lo_oid(lo) RETURNS pg_catalog.oid AS
+CREATE FUNCTION lo_oid(lo) RETURNS pg_catalog.oid AS
'SELECT $1::pg_catalog.oid' LANGUAGE SQL STRICT IMMUTABLE;
-- This is used in triggers
-CREATE OR REPLACE FUNCTION lo_manage()
+CREATE FUNCTION lo_manage()
RETURNS pg_catalog.trigger
AS 'MODULE_PATHNAME'
LANGUAGE C;
diff --git a/contrib/lo/lo--unpackaged--1.0.sql b/contrib/lo/lo--unpackaged--1.0.sql
new file mode 100644
index 0000000000..54de61686e
--- /dev/null
+++ b/contrib/lo/lo--unpackaged--1.0.sql
@@ -0,0 +1,5 @@
+/* contrib/lo/lo--unpackaged--1.0.sql */
+
+ALTER EXTENSION lo ADD domain lo;
+ALTER EXTENSION lo ADD function lo_oid(lo);
+ALTER EXTENSION lo ADD function lo_manage();
diff --git a/contrib/lo/lo.c b/contrib/lo/lo.c
index 2e37a28591..0e3559c020 100644
--- a/contrib/lo/lo.c
+++ b/contrib/lo/lo.c
@@ -1,7 +1,7 @@
/*
* PostgreSQL definitions for managed Large Objects.
*
- * $PostgreSQL: pgsql/contrib/lo/lo.c,v 1.17 2006/07/11 17:04:12 momjian Exp $
+ * contrib/lo/lo.c
*
*/
diff --git a/contrib/lo/lo.control b/contrib/lo/lo.control
new file mode 100644
index 0000000000..849dfb5803
--- /dev/null
+++ b/contrib/lo/lo.control
@@ -0,0 +1,5 @@
+# lo extension
+comment = 'Large Object maintenance'
+default_version = '1.0'
+module_pathname = '$libdir/lo'
+relocatable = true
diff --git a/contrib/lo/lo_test.sql b/contrib/lo/lo_test.sql
index 73022b2535..7e52362f81 100644
--- a/contrib/lo/lo_test.sql
+++ b/contrib/lo/lo_test.sql
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/lo/lo_test.sql,v 1.6 2009/12/14 00:39:10 itagaki Exp $ */
+/* contrib/lo/lo_test.sql */
-- Adjust this setting to control where the objects get created.
SET search_path = public;
diff --git a/contrib/lo/uninstall_lo.sql b/contrib/lo/uninstall_lo.sql
deleted file mode 100644
index 7cbc796a3d..0000000000
--- a/contrib/lo/uninstall_lo.sql
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/lo/uninstall_lo.sql,v 1.3 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
---
--- This removes the LO type
--- It's used just for development
---
-
--- drop the type and associated functions
-DROP TYPE lo CASCADE;
-
--- the trigger function has no dependency on the type, so drop separately
-DROP FUNCTION lo_manage();
-
--- the lo stuff is now removed from the system
diff --git a/contrib/ltree/.gitignore b/contrib/ltree/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/ltree/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/ltree/Makefile b/contrib/ltree/Makefile
index 130658a2a7..65d42f875f 100644
--- a/contrib/ltree/Makefile
+++ b/contrib/ltree/Makefile
@@ -1,11 +1,13 @@
-# $PostgreSQL: pgsql/contrib/ltree/Makefile,v 1.8 2007/11/10 23:59:51 momjian Exp $
+# contrib/ltree/Makefile
-PG_CPPFLAGS = -DLOWER_NODE
MODULE_big = ltree
OBJS = ltree_io.o ltree_op.o lquery_op.o _ltree_op.o crc32.o \
ltxtquery_io.o ltxtquery_op.o ltree_gist.o _ltree_gist.o
-DATA_built = ltree.sql
-DATA = uninstall_ltree.sql
+PG_CPPFLAGS = -DLOWER_NODE
+
+EXTENSION = ltree
+DATA = ltree--1.0.sql ltree--unpackaged--1.0.sql
+
REGRESS = ltree
ifdef USE_PGXS
diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c
index 4c0e7c25c0..c1f509ed8b 100644
--- a/contrib/ltree/_ltree_gist.c
+++ b/contrib/ltree/_ltree_gist.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/ltree/_ltree_gist.c,v 1.27 2010/02/24 18:02:24 tgl Exp $
+ * contrib/ltree/_ltree_gist.c
*
*
* GiST support for ltree[]
@@ -92,7 +92,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("array must be one-dimensional")));
- if (ARR_HASNULL(val))
+ if (array_contains_nulls(val))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("array must not contain nulls")));
@@ -538,7 +538,7 @@ _arrq_cons(ltree_gist *key, ArrayType *_query)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("array must be one-dimensional")));
- if (ARR_HASNULL(_query))
+ if (array_contains_nulls(_query))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("array must not contain nulls")));
diff --git a/contrib/ltree/_ltree_op.c b/contrib/ltree/_ltree_op.c
index 02c96c05d4..f4f0451fd8 100644
--- a/contrib/ltree/_ltree_op.c
+++ b/contrib/ltree/_ltree_op.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/ltree/_ltree_op.c,v 1.14 2010/02/24 18:02:24 tgl Exp $
+ * contrib/ltree/_ltree_op.c
*
*
* op function for ltree[]
@@ -52,7 +52,7 @@ array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("array must be one-dimensional")));
- if (ARR_HASNULL(la))
+ if (array_contains_nulls(la))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("array must not contain nulls")));
@@ -152,7 +152,7 @@ _lt_q_regex(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("array must be one-dimensional")));
- if (ARR_HASNULL(_query))
+ if (array_contains_nulls(_query))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("array must not contain nulls")));
@@ -310,7 +310,7 @@ _lca(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("array must be one-dimensional")));
- if (ARR_HASNULL(la))
+ if (array_contains_nulls(la))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("array must not contain nulls")));
diff --git a/contrib/ltree/crc32.c b/contrib/ltree/crc32.c
index f0078d6e42..c736defc73 100644
--- a/contrib/ltree/crc32.c
+++ b/contrib/ltree/crc32.c
@@ -1,6 +1,6 @@
/* Both POSIX and CRC32 checksums */
-/* $PostgreSQL: pgsql/contrib/ltree/crc32.c,v 1.8 2007/07/15 22:40:28 tgl Exp $ */
+/* contrib/ltree/crc32.c */
#include <sys/types.h>
#include <stdio.h>
diff --git a/contrib/ltree/crc32.h b/contrib/ltree/crc32.h
index 69d9eee3e1..269d05d0c1 100644
--- a/contrib/ltree/crc32.h
+++ b/contrib/ltree/crc32.h
@@ -1,7 +1,7 @@
#ifndef _CRC32_H
#define _CRC32_H
-/* $PostgreSQL: pgsql/contrib/ltree/crc32.h,v 1.3 2006/03/11 04:38:29 momjian Exp $ */
+/* contrib/ltree/crc32.h */
/* Returns crc32 of data block */
extern unsigned int ltree_crc32_sz(char *buf, int size);
diff --git a/contrib/ltree/expected/ltree.out b/contrib/ltree/expected/ltree.out
index 7f61e569cf..da6e39a785 100644
--- a/contrib/ltree/expected/ltree.out
+++ b/contrib/ltree/expected/ltree.out
@@ -1,10 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of ltree.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION ltree;
SELECT ''::ltree;
ltree
-------
diff --git a/contrib/ltree/lquery_op.c b/contrib/ltree/lquery_op.c
index 1059417e77..da1086a8eb 100644
--- a/contrib/ltree/lquery_op.c
+++ b/contrib/ltree/lquery_op.c
@@ -1,12 +1,13 @@
/*
* op function for ltree and lquery
* Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/lquery_op.c,v 1.15 2010/02/24 18:02:24 tgl Exp $
+ * contrib/ltree/lquery_op.c
*/
#include "postgres.h"
#include <ctype.h>
+#include "catalog/pg_collation.h"
#include "utils/array.h"
#include "utils/formatting.h"
#include "ltree.h"
@@ -90,8 +91,8 @@ bool
int
ltree_strncasecmp(const char *a, const char *b, size_t s)
{
- char *al = str_tolower(a, s);
- char *bl = str_tolower(b, s);
+ char *al = str_tolower(a, s, DEFAULT_COLLATION_OID);
+ char *bl = str_tolower(b, s, DEFAULT_COLLATION_OID);
int res;
res = strncmp(al, bl, s);
@@ -348,7 +349,7 @@ lt_q_regex(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("array must be one-dimensional")));
- if (ARR_HASNULL(_query))
+ if (array_contains_nulls(_query))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("array must not contain nulls")));
diff --git a/contrib/ltree/ltree.sql.in b/contrib/ltree/ltree--1.0.sql
index 364c44db1b..32969538a0 100644
--- a/contrib/ltree/ltree.sql.in
+++ b/contrib/ltree/ltree--1.0.sql
@@ -1,14 +1,11 @@
-/* $PostgreSQL: pgsql/contrib/ltree/ltree.sql.in,v 1.18 2009/06/11 18:30:03 tgl Exp $ */
+/* contrib/ltree/ltree--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION ltree_in(cstring)
+CREATE FUNCTION ltree_in(cstring)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION ltree_out(ltree)
+CREATE FUNCTION ltree_out(ltree)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
@@ -22,37 +19,37 @@ CREATE TYPE ltree (
--Compare function for ltree
-CREATE OR REPLACE FUNCTION ltree_cmp(ltree,ltree)
+CREATE FUNCTION ltree_cmp(ltree,ltree)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_lt(ltree,ltree)
+CREATE FUNCTION ltree_lt(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_le(ltree,ltree)
+CREATE FUNCTION ltree_le(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_eq(ltree,ltree)
+CREATE FUNCTION ltree_eq(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_ge(ltree,ltree)
+CREATE FUNCTION ltree_ge(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_gt(ltree,ltree)
+CREATE FUNCTION ltree_gt(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_ne(ltree,ltree)
+CREATE FUNCTION ltree_ne(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -122,112 +119,112 @@ CREATE OPERATOR <> (
--util functions
-CREATE OR REPLACE FUNCTION subltree(ltree,int4,int4)
+CREATE FUNCTION subltree(ltree,int4,int4)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION subpath(ltree,int4,int4)
+CREATE FUNCTION subpath(ltree,int4,int4)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION subpath(ltree,int4)
+CREATE FUNCTION subpath(ltree,int4)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION index(ltree,ltree)
+CREATE FUNCTION index(ltree,ltree)
RETURNS int4
AS 'MODULE_PATHNAME', 'ltree_index'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION index(ltree,ltree,int4)
+CREATE FUNCTION index(ltree,ltree,int4)
RETURNS int4
AS 'MODULE_PATHNAME', 'ltree_index'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION nlevel(ltree)
+CREATE FUNCTION nlevel(ltree)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree2text(ltree)
+CREATE FUNCTION ltree2text(ltree)
RETURNS text
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION text2ltree(text)
+CREATE FUNCTION text2ltree(text)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(_ltree)
+CREATE FUNCTION lca(_ltree)
RETURNS ltree
AS 'MODULE_PATHNAME','_lca'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(ltree,ltree)
+CREATE FUNCTION lca(ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(ltree,ltree,ltree)
+CREATE FUNCTION lca(ltree,ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(ltree,ltree,ltree,ltree)
+CREATE FUNCTION lca(ltree,ltree,ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(ltree,ltree,ltree,ltree,ltree)
+CREATE FUNCTION lca(ltree,ltree,ltree,ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree)
+CREATE FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree)
+CREATE FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree,ltree)
+CREATE FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_isparent(ltree,ltree)
+CREATE FUNCTION ltree_isparent(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_risparent(ltree,ltree)
+CREATE FUNCTION ltree_risparent(ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_addltree(ltree,ltree)
+CREATE FUNCTION ltree_addltree(ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_addtext(ltree,text)
+CREATE FUNCTION ltree_addtext(ltree,text)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltree_textadd(text,ltree)
+CREATE FUNCTION ltree_textadd(text,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltreeparentsel(internal, oid, internal, integer)
+CREATE FUNCTION ltreeparentsel(internal, oid, internal, integer)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -300,12 +297,12 @@ CREATE OPERATOR CLASS ltree_ops
--lquery type
-CREATE OR REPLACE FUNCTION lquery_in(cstring)
+CREATE FUNCTION lquery_in(cstring)
RETURNS lquery
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION lquery_out(lquery)
+CREATE FUNCTION lquery_out(lquery)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
@@ -317,12 +314,12 @@ CREATE TYPE lquery (
STORAGE = extended
);
-CREATE OR REPLACE FUNCTION ltq_regex(ltree,lquery)
+CREATE FUNCTION ltq_regex(ltree,lquery)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltq_rregex(lquery,ltree)
+CREATE FUNCTION ltq_rregex(lquery,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -364,12 +361,12 @@ CREATE OPERATOR ^~ (
JOIN = contjoinsel
);
-CREATE OR REPLACE FUNCTION lt_q_regex(ltree,_lquery)
+CREATE FUNCTION lt_q_regex(ltree,_lquery)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION lt_q_rregex(_lquery,ltree)
+CREATE FUNCTION lt_q_rregex(_lquery,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -411,12 +408,12 @@ CREATE OPERATOR ^? (
JOIN = contjoinsel
);
-CREATE OR REPLACE FUNCTION ltxtq_in(cstring)
+CREATE FUNCTION ltxtq_in(cstring)
RETURNS ltxtquery
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION ltxtq_out(ltxtquery)
+CREATE FUNCTION ltxtq_out(ltxtquery)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
@@ -430,12 +427,12 @@ CREATE TYPE ltxtquery (
-- operations WITH ltxtquery
-CREATE OR REPLACE FUNCTION ltxtq_exec(ltree, ltxtquery)
+CREATE FUNCTION ltxtq_exec(ltree, ltxtquery)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION ltxtq_rexec(ltxtquery, ltree)
+CREATE FUNCTION ltxtq_rexec(ltxtquery, ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -478,43 +475,43 @@ CREATE OPERATOR ^@ (
);
--GiST support for ltree
-CREATE OR REPLACE FUNCTION ltree_gist_in(cstring)
+CREATE FUNCTION ltree_gist_in(cstring)
RETURNS ltree_gist
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION ltree_gist_out(ltree_gist)
+
+CREATE FUNCTION ltree_gist_out(ltree_gist)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-
+
CREATE TYPE ltree_gist (
internallength = -1,
input = ltree_gist_in,
output = ltree_gist_out,
storage = plain
-);
+);
-CREATE OR REPLACE FUNCTION ltree_consistent(internal,internal,int2,oid,internal)
+CREATE FUNCTION ltree_consistent(internal,internal,int2,oid,internal)
RETURNS bool as 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ltree_compress(internal)
+CREATE FUNCTION ltree_compress(internal)
RETURNS internal as 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ltree_decompress(internal)
+CREATE FUNCTION ltree_decompress(internal)
RETURNS internal as 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ltree_penalty(internal,internal,internal)
+CREATE FUNCTION ltree_penalty(internal,internal,internal)
RETURNS internal as 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ltree_picksplit(internal, internal)
+CREATE FUNCTION ltree_picksplit(internal, internal)
RETURNS internal as 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ltree_union(internal, internal)
+CREATE FUNCTION ltree_union(internal, internal)
RETURNS int4 as 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION ltree_same(internal, internal, internal)
+CREATE FUNCTION ltree_same(internal, internal, internal)
RETURNS internal as 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR CLASS gist_ltree_ops
@@ -544,52 +541,52 @@ CREATE OPERATOR CLASS gist_ltree_ops
-- arrays of ltree
-CREATE OR REPLACE FUNCTION _ltree_isparent(_ltree,ltree)
+CREATE FUNCTION _ltree_isparent(_ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _ltree_r_isparent(ltree,_ltree)
+CREATE FUNCTION _ltree_r_isparent(ltree,_ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _ltree_risparent(_ltree,ltree)
+CREATE FUNCTION _ltree_risparent(_ltree,ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _ltree_r_risparent(ltree,_ltree)
+CREATE FUNCTION _ltree_r_risparent(ltree,_ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _ltq_regex(_ltree,lquery)
+CREATE FUNCTION _ltq_regex(_ltree,lquery)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _ltq_rregex(lquery,_ltree)
+CREATE FUNCTION _ltq_rregex(lquery,_ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _lt_q_regex(_ltree,_lquery)
+CREATE FUNCTION _lt_q_regex(_ltree,_lquery)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _lt_q_rregex(_lquery,_ltree)
+CREATE FUNCTION _lt_q_rregex(_lquery,_ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _ltxtq_exec(_ltree, ltxtquery)
+CREATE FUNCTION _ltxtq_exec(_ltree, ltxtquery)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION _ltxtq_rexec(ltxtquery, _ltree)
+CREATE FUNCTION _ltxtq_rexec(ltxtquery, _ltree)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -777,7 +774,7 @@ CREATE OPERATOR ^@ (
);
--extractors
-CREATE OR REPLACE FUNCTION _ltree_extract_isparent(_ltree,ltree)
+CREATE FUNCTION _ltree_extract_isparent(_ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -788,7 +785,7 @@ CREATE OPERATOR ?@> (
PROCEDURE = _ltree_extract_isparent
);
-CREATE OR REPLACE FUNCTION _ltree_extract_risparent(_ltree,ltree)
+CREATE FUNCTION _ltree_extract_risparent(_ltree,ltree)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -799,7 +796,7 @@ CREATE OPERATOR ?<@ (
PROCEDURE = _ltree_extract_risparent
);
-CREATE OR REPLACE FUNCTION _ltq_extract_regex(_ltree,lquery)
+CREATE FUNCTION _ltq_extract_regex(_ltree,lquery)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -810,7 +807,7 @@ CREATE OPERATOR ?~ (
PROCEDURE = _ltq_extract_regex
);
-CREATE OR REPLACE FUNCTION _ltxtq_extract_exec(_ltree,ltxtquery)
+CREATE FUNCTION _ltxtq_extract_exec(_ltree,ltxtquery)
RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -822,32 +819,32 @@ CREATE OPERATOR ?@ (
);
--GiST support for ltree[]
-CREATE OR REPLACE FUNCTION _ltree_consistent(internal,internal,int2,oid,internal)
+CREATE FUNCTION _ltree_consistent(internal,internal,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION _ltree_compress(internal)
+CREATE FUNCTION _ltree_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION _ltree_penalty(internal,internal,internal)
+CREATE FUNCTION _ltree_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION _ltree_picksplit(internal, internal)
+CREATE FUNCTION _ltree_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION _ltree_union(internal, internal)
+CREATE FUNCTION _ltree_union(internal, internal)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION _ltree_same(internal, internal, internal)
+CREATE FUNCTION _ltree_same(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
diff --git a/contrib/ltree/ltree--unpackaged--1.0.sql b/contrib/ltree/ltree--unpackaged--1.0.sql
new file mode 100644
index 0000000000..f483725b4a
--- /dev/null
+++ b/contrib/ltree/ltree--unpackaged--1.0.sql
@@ -0,0 +1,131 @@
+/* contrib/ltree/ltree--unpackaged--1.0.sql */
+
+ALTER EXTENSION ltree ADD type ltree;
+ALTER EXTENSION ltree ADD function ltree_in(cstring);
+ALTER EXTENSION ltree ADD function ltree_out(ltree);
+ALTER EXTENSION ltree ADD function ltree_cmp(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_lt(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_le(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_eq(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_ge(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_gt(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_ne(ltree,ltree);
+ALTER EXTENSION ltree ADD operator >(ltree,ltree);
+ALTER EXTENSION ltree ADD operator >=(ltree,ltree);
+ALTER EXTENSION ltree ADD operator <(ltree,ltree);
+ALTER EXTENSION ltree ADD operator <=(ltree,ltree);
+ALTER EXTENSION ltree ADD operator <>(ltree,ltree);
+ALTER EXTENSION ltree ADD operator =(ltree,ltree);
+ALTER EXTENSION ltree ADD function subltree(ltree,integer,integer);
+ALTER EXTENSION ltree ADD function subpath(ltree,integer,integer);
+ALTER EXTENSION ltree ADD function subpath(ltree,integer);
+ALTER EXTENSION ltree ADD function index(ltree,ltree);
+ALTER EXTENSION ltree ADD function index(ltree,ltree,integer);
+ALTER EXTENSION ltree ADD function nlevel(ltree);
+ALTER EXTENSION ltree ADD function ltree2text(ltree);
+ALTER EXTENSION ltree ADD function text2ltree(text);
+ALTER EXTENSION ltree ADD function lca(ltree[]);
+ALTER EXTENSION ltree ADD function lca(ltree,ltree);
+ALTER EXTENSION ltree ADD function lca(ltree,ltree,ltree);
+ALTER EXTENSION ltree ADD function lca(ltree,ltree,ltree,ltree);
+ALTER EXTENSION ltree ADD function lca(ltree,ltree,ltree,ltree,ltree);
+ALTER EXTENSION ltree ADD function lca(ltree,ltree,ltree,ltree,ltree,ltree);
+ALTER EXTENSION ltree ADD function lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree);
+ALTER EXTENSION ltree ADD function lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_isparent(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_risparent(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_addltree(ltree,ltree);
+ALTER EXTENSION ltree ADD function ltree_addtext(ltree,text);
+ALTER EXTENSION ltree ADD function ltree_textadd(text,ltree);
+ALTER EXTENSION ltree ADD function ltreeparentsel(internal,oid,internal,integer);
+ALTER EXTENSION ltree ADD operator <@(ltree,ltree);
+ALTER EXTENSION ltree ADD operator @>(ltree,ltree);
+ALTER EXTENSION ltree ADD operator ^<@(ltree,ltree);
+ALTER EXTENSION ltree ADD operator ^@>(ltree,ltree);
+ALTER EXTENSION ltree ADD operator ||(ltree,ltree);
+ALTER EXTENSION ltree ADD operator ||(ltree,text);
+ALTER EXTENSION ltree ADD operator ||(text,ltree);
+ALTER EXTENSION ltree ADD operator family ltree_ops using btree;
+ALTER EXTENSION ltree ADD operator class ltree_ops using btree;
+ALTER EXTENSION ltree ADD type lquery;
+ALTER EXTENSION ltree ADD function lquery_in(cstring);
+ALTER EXTENSION ltree ADD function lquery_out(lquery);
+ALTER EXTENSION ltree ADD function ltq_regex(ltree,lquery);
+ALTER EXTENSION ltree ADD function ltq_rregex(lquery,ltree);
+ALTER EXTENSION ltree ADD operator ~(lquery,ltree);
+ALTER EXTENSION ltree ADD operator ~(ltree,lquery);
+ALTER EXTENSION ltree ADD operator ^~(lquery,ltree);
+ALTER EXTENSION ltree ADD operator ^~(ltree,lquery);
+ALTER EXTENSION ltree ADD function lt_q_regex(ltree,lquery[]);
+ALTER EXTENSION ltree ADD function lt_q_rregex(lquery[],ltree);
+ALTER EXTENSION ltree ADD operator ?(lquery[],ltree);
+ALTER EXTENSION ltree ADD operator ?(ltree,lquery[]);
+ALTER EXTENSION ltree ADD operator ^?(lquery[],ltree);
+ALTER EXTENSION ltree ADD operator ^?(ltree,lquery[]);
+ALTER EXTENSION ltree ADD type ltxtquery;
+ALTER EXTENSION ltree ADD function ltxtq_in(cstring);
+ALTER EXTENSION ltree ADD function ltxtq_out(ltxtquery);
+ALTER EXTENSION ltree ADD function ltxtq_exec(ltree,ltxtquery);
+ALTER EXTENSION ltree ADD function ltxtq_rexec(ltxtquery,ltree);
+ALTER EXTENSION ltree ADD operator @(ltxtquery,ltree);
+ALTER EXTENSION ltree ADD operator @(ltree,ltxtquery);
+ALTER EXTENSION ltree ADD operator ^@(ltxtquery,ltree);
+ALTER EXTENSION ltree ADD operator ^@(ltree,ltxtquery);
+ALTER EXTENSION ltree ADD type ltree_gist;
+ALTER EXTENSION ltree ADD function ltree_gist_in(cstring);
+ALTER EXTENSION ltree ADD function ltree_gist_out(ltree_gist);
+ALTER EXTENSION ltree ADD function ltree_consistent(internal,internal,smallint,oid,internal);
+ALTER EXTENSION ltree ADD function ltree_compress(internal);
+ALTER EXTENSION ltree ADD function ltree_decompress(internal);
+ALTER EXTENSION ltree ADD function ltree_penalty(internal,internal,internal);
+ALTER EXTENSION ltree ADD function ltree_picksplit(internal,internal);
+ALTER EXTENSION ltree ADD function ltree_union(internal,internal);
+ALTER EXTENSION ltree ADD function ltree_same(internal,internal,internal);
+ALTER EXTENSION ltree ADD operator family gist_ltree_ops using gist;
+ALTER EXTENSION ltree ADD operator class gist_ltree_ops using gist;
+ALTER EXTENSION ltree ADD function _ltree_isparent(ltree[],ltree);
+ALTER EXTENSION ltree ADD function _ltree_r_isparent(ltree,ltree[]);
+ALTER EXTENSION ltree ADD function _ltree_risparent(ltree[],ltree);
+ALTER EXTENSION ltree ADD function _ltree_r_risparent(ltree,ltree[]);
+ALTER EXTENSION ltree ADD function _ltq_regex(ltree[],lquery);
+ALTER EXTENSION ltree ADD function _ltq_rregex(lquery,ltree[]);
+ALTER EXTENSION ltree ADD function _lt_q_regex(ltree[],lquery[]);
+ALTER EXTENSION ltree ADD function _lt_q_rregex(lquery[],ltree[]);
+ALTER EXTENSION ltree ADD function _ltxtq_exec(ltree[],ltxtquery);
+ALTER EXTENSION ltree ADD function _ltxtq_rexec(ltxtquery,ltree[]);
+ALTER EXTENSION ltree ADD operator <@(ltree,ltree[]);
+ALTER EXTENSION ltree ADD operator @>(ltree[],ltree);
+ALTER EXTENSION ltree ADD operator @>(ltree,ltree[]);
+ALTER EXTENSION ltree ADD operator <@(ltree[],ltree);
+ALTER EXTENSION ltree ADD operator ~(lquery,ltree[]);
+ALTER EXTENSION ltree ADD operator ~(ltree[],lquery);
+ALTER EXTENSION ltree ADD operator ?(lquery[],ltree[]);
+ALTER EXTENSION ltree ADD operator ?(ltree[],lquery[]);
+ALTER EXTENSION ltree ADD operator @(ltxtquery,ltree[]);
+ALTER EXTENSION ltree ADD operator @(ltree[],ltxtquery);
+ALTER EXTENSION ltree ADD operator ^<@(ltree,ltree[]);
+ALTER EXTENSION ltree ADD operator ^@>(ltree[],ltree);
+ALTER EXTENSION ltree ADD operator ^@>(ltree,ltree[]);
+ALTER EXTENSION ltree ADD operator ^<@(ltree[],ltree);
+ALTER EXTENSION ltree ADD operator ^~(lquery,ltree[]);
+ALTER EXTENSION ltree ADD operator ^~(ltree[],lquery);
+ALTER EXTENSION ltree ADD operator ^?(lquery[],ltree[]);
+ALTER EXTENSION ltree ADD operator ^?(ltree[],lquery[]);
+ALTER EXTENSION ltree ADD operator ^@(ltxtquery,ltree[]);
+ALTER EXTENSION ltree ADD operator ^@(ltree[],ltxtquery);
+ALTER EXTENSION ltree ADD function _ltree_extract_isparent(ltree[],ltree);
+ALTER EXTENSION ltree ADD operator ?@>(ltree[],ltree);
+ALTER EXTENSION ltree ADD function _ltree_extract_risparent(ltree[],ltree);
+ALTER EXTENSION ltree ADD operator ?<@(ltree[],ltree);
+ALTER EXTENSION ltree ADD function _ltq_extract_regex(ltree[],lquery);
+ALTER EXTENSION ltree ADD operator ?~(ltree[],lquery);
+ALTER EXTENSION ltree ADD function _ltxtq_extract_exec(ltree[],ltxtquery);
+ALTER EXTENSION ltree ADD operator ?@(ltree[],ltxtquery);
+ALTER EXTENSION ltree ADD function _ltree_consistent(internal,internal,smallint,oid,internal);
+ALTER EXTENSION ltree ADD function _ltree_compress(internal);
+ALTER EXTENSION ltree ADD function _ltree_penalty(internal,internal,internal);
+ALTER EXTENSION ltree ADD function _ltree_picksplit(internal,internal);
+ALTER EXTENSION ltree ADD function _ltree_union(internal,internal);
+ALTER EXTENSION ltree ADD function _ltree_same(internal,internal,internal);
+ALTER EXTENSION ltree ADD operator family gist__ltree_ops using gist;
+ALTER EXTENSION ltree ADD operator class gist__ltree_ops using gist;
diff --git a/contrib/ltree/ltree.control b/contrib/ltree/ltree.control
new file mode 100644
index 0000000000..d879fd618c
--- /dev/null
+++ b/contrib/ltree/ltree.control
@@ -0,0 +1,5 @@
+# ltree extension
+comment = 'data type for hierarchical tree-like structures'
+default_version = '1.0'
+module_pathname = '$libdir/ltree'
+relocatable = true
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index f16c6f9a32..8e4ea4c151 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/ltree/ltree.h,v 1.22 2009/06/11 14:48:51 momjian Exp $ */
+/* contrib/ltree/ltree.h */
#ifndef __LTREE_H__
#define __LTREE_H__
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index 46fccb1ee1..26c34753dc 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -1,7 +1,7 @@
/*
* GiST support for ltree
* Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/ltree_gist.c,v 1.26 2010/02/24 18:02:24 tgl Exp $
+ * contrib/ltree/ltree_gist.c
*/
#include "postgres.h"
@@ -546,7 +546,7 @@ gist_tqcmp(ltree *t, lquery *q)
while (an > 0 && bn > 0)
{
bl = LQL_FIRST(ql);
- if ((res = strncmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
+ if ((res = memcmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
{
if (al->len != bl->len)
return al->len - bl->len;
@@ -606,7 +606,7 @@ arrq_cons(ltree_gist *key, ArrayType *_query)
ereport(ERROR,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("array must be one-dimensional")));
- if (ARR_HASNULL(_query))
+ if (array_contains_nulls(_query))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("array must not contain nulls")));
diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c
index a88eb16cb9..3e88b81c16 100644
--- a/contrib/ltree/ltree_io.c
+++ b/contrib/ltree/ltree_io.c
@@ -1,7 +1,7 @@
/*
* in/out function for ltree and lquery
* Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/ltree_io.c,v 1.18 2009/06/11 14:48:51 momjian Exp $
+ * contrib/ltree/ltree_io.c
*/
#include "postgres.h"
diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c
index 2e6d5367d8..2b048d4b7c 100644
--- a/contrib/ltree/ltree_op.c
+++ b/contrib/ltree/ltree_op.c
@@ -1,7 +1,7 @@
/*
* op function for ltree
* Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/ltree_op.c,v 1.20 2009/06/11 14:48:51 momjian Exp $
+ * contrib/ltree/ltree_op.c
*/
#include "postgres.h"
@@ -68,7 +68,7 @@ ltree_compare(const ltree *a, const ltree *b)
while (an > 0 && bn > 0)
{
- if ((res = strncmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
+ if ((res = memcmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
{
if (al->len != bl->len)
return (al->len - bl->len) * 10 * (an + 1);
@@ -165,7 +165,7 @@ inner_isparent(const ltree *c, const ltree *p)
{
if (cl->len != pl->len)
return false;
- if (strncmp(cl->name, pl->name, cl->len))
+ if (memcmp(cl->name, pl->name, cl->len))
return false;
pn--;
@@ -373,7 +373,7 @@ ltree_index(PG_FUNCTION_ARGS)
bptr = LTREE_FIRST(b);
for (j = 0; j < b->numlevel; j++)
{
- if (!(aptr->len == bptr->len && strncmp(aptr->name, bptr->name, aptr->len) == 0))
+ if (!(aptr->len == bptr->len && memcmp(aptr->name, bptr->name, aptr->len) == 0))
break;
aptr = LEVEL_NEXT(aptr);
bptr = LEVEL_NEXT(bptr);
@@ -451,7 +451,7 @@ lca_inner(ltree **a, int len)
num = 0;
for (i = 0; i < Min(tmp, (*ptr)->numlevel - 1); i++)
{
- if (l1->len == l2->len && strncmp(l1->name, l2->name, l1->len) == 0)
+ if (l1->len == l2->len && memcmp(l1->name, l2->name, l1->len) == 0)
num = i + 1;
else
break;
diff --git a/contrib/ltree/ltreetest.sql b/contrib/ltree/ltreetest.sql
index 8621188b7f..d6996caf3c 100644
--- a/contrib/ltree/ltreetest.sql
+++ b/contrib/ltree/ltreetest.sql
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/ltree/ltreetest.sql,v 1.4 2007/11/13 04:24:28 momjian Exp $ */
+/* contrib/ltree/ltreetest.sql */
-- Adjust this setting to control where the objects get created.
SET search_path = public;
diff --git a/contrib/ltree/ltxtquery_io.c b/contrib/ltree/ltxtquery_io.c
index b158c4b441..826f4e1c9d 100644
--- a/contrib/ltree/ltxtquery_io.c
+++ b/contrib/ltree/ltxtquery_io.c
@@ -1,7 +1,7 @@
/*
* txtquery io
* Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/ltxtquery_io.c,v 1.17 2009/06/11 14:48:51 momjian Exp $
+ * contrib/ltree/ltxtquery_io.c
*/
#include "postgres.h"
@@ -241,8 +241,8 @@ makepol(QPRS_STATE *state)
case OPEN:
if (makepol(state) == ERR)
return ERR;
- if (lenstack && (stack[lenstack - 1] == (int4) '&' ||
- stack[lenstack - 1] == (int4) '!'))
+ while (lenstack && (stack[lenstack - 1] == (int4) '&' ||
+ stack[lenstack - 1] == (int4) '!'))
{
lenstack--;
pushquery(state, OPR, stack[lenstack], 0, 0, 0);
diff --git a/contrib/ltree/ltxtquery_op.c b/contrib/ltree/ltxtquery_op.c
index 559c05e2bf..1c13888605 100644
--- a/contrib/ltree/ltxtquery_op.c
+++ b/contrib/ltree/ltxtquery_op.c
@@ -1,7 +1,7 @@
/*
* txtquery operations with ltree
* Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/ltxtquery_op.c,v 1.10 2009/06/11 14:48:51 momjian Exp $
+ * contrib/ltree/ltxtquery_op.c
*/
#include "postgres.h"
diff --git a/contrib/ltree/sql/ltree.sql b/contrib/ltree/sql/ltree.sql
index 9241c2a0cb..46cfa41a41 100644
--- a/contrib/ltree/sql/ltree.sql
+++ b/contrib/ltree/sql/ltree.sql
@@ -1,12 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of ltree.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i ltree.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION ltree;
SELECT ''::ltree;
SELECT '1'::ltree;
@@ -291,4 +283,3 @@ SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
-
diff --git a/contrib/ltree/uninstall_ltree.sql b/contrib/ltree/uninstall_ltree.sql
deleted file mode 100644
index acd07df1e8..0000000000
--- a/contrib/ltree/uninstall_ltree.sql
+++ /dev/null
@@ -1,240 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/ltree/uninstall_ltree.sql,v 1.6 2008/04/14 17:05:32 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR CLASS gist__ltree_ops USING gist;
-
-DROP FUNCTION _ltree_same(internal, internal, internal);
-
-DROP FUNCTION _ltree_union(internal, internal);
-
-DROP FUNCTION _ltree_picksplit(internal, internal);
-
-DROP FUNCTION _ltree_penalty(internal,internal,internal);
-
-DROP FUNCTION _ltree_compress(internal);
-
-DROP FUNCTION _ltree_consistent(internal,internal,int2,oid,internal);
-
-DROP OPERATOR ?@ (_ltree, ltxtquery);
-
-DROP FUNCTION _ltxtq_extract_exec(_ltree,ltxtquery);
-
-DROP OPERATOR ?~ (_ltree, lquery);
-
-DROP FUNCTION _ltq_extract_regex(_ltree,lquery);
-
-DROP OPERATOR ?<@ (_ltree, ltree);
-
-DROP FUNCTION _ltree_extract_risparent(_ltree,ltree);
-
-DROP OPERATOR ?@> (_ltree, ltree);
-
-DROP FUNCTION _ltree_extract_isparent(_ltree,ltree);
-
-DROP OPERATOR ^@ (ltxtquery, _ltree);
-
-DROP OPERATOR ^@ (_ltree, ltxtquery);
-
-DROP OPERATOR ^? (_lquery, _ltree);
-
-DROP OPERATOR ^? (_ltree, _lquery);
-
-DROP OPERATOR ^~ (lquery, _ltree);
-
-DROP OPERATOR ^~ (_ltree, lquery);
-
-DROP OPERATOR ^@> (ltree, _ltree);
-
-DROP OPERATOR ^<@ (_ltree, ltree);
-
-DROP OPERATOR ^<@ (ltree, _ltree);
-
-DROP OPERATOR ^@> (_ltree, ltree);
-
-DROP OPERATOR @ (ltxtquery, _ltree);
-
-DROP OPERATOR @ (_ltree, ltxtquery);
-
-DROP OPERATOR ? (_lquery, _ltree);
-
-DROP OPERATOR ? (_ltree, _lquery);
-
-DROP OPERATOR ~ (lquery, _ltree);
-
-DROP OPERATOR ~ (_ltree, lquery);
-
-DROP OPERATOR @> (ltree, _ltree);
-
-DROP OPERATOR <@ (_ltree, ltree);
-
-DROP OPERATOR <@ (ltree, _ltree);
-
-DROP OPERATOR @> (_ltree, ltree);
-
-DROP FUNCTION _ltxtq_rexec(ltxtquery, _ltree);
-
-DROP FUNCTION _ltxtq_exec(_ltree, ltxtquery);
-
-DROP FUNCTION _lt_q_rregex(_lquery,_ltree);
-
-DROP FUNCTION _lt_q_regex(_ltree,_lquery);
-
-DROP FUNCTION _ltq_rregex(lquery,_ltree);
-
-DROP FUNCTION _ltq_regex(_ltree,lquery);
-
-DROP FUNCTION _ltree_r_risparent(ltree,_ltree);
-
-DROP FUNCTION _ltree_risparent(_ltree,ltree);
-
-DROP FUNCTION _ltree_r_isparent(ltree,_ltree);
-
-DROP FUNCTION _ltree_isparent(_ltree,ltree);
-
-DROP OPERATOR CLASS gist_ltree_ops USING gist;
-
-DROP FUNCTION ltree_same(internal, internal, internal);
-
-DROP FUNCTION ltree_union(internal, internal);
-
-DROP FUNCTION ltree_picksplit(internal, internal);
-
-DROP FUNCTION ltree_penalty(internal,internal,internal);
-
-DROP FUNCTION ltree_decompress(internal);
-
-DROP FUNCTION ltree_compress(internal);
-
-DROP FUNCTION ltree_consistent(internal,internal,int2,oid,internal);
-
-DROP TYPE ltree_gist CASCADE;
-
-DROP OPERATOR ^@ (ltxtquery, ltree);
-
-DROP OPERATOR ^@ (ltree, ltxtquery);
-
-DROP OPERATOR @ (ltxtquery, ltree);
-
-DROP OPERATOR @ (ltree, ltxtquery);
-
-DROP FUNCTION ltxtq_rexec(ltxtquery, ltree);
-
-DROP FUNCTION ltxtq_exec(ltree, ltxtquery);
-
-DROP TYPE ltxtquery CASCADE;
-
-DROP OPERATOR ^? (_lquery, ltree);
-
-DROP OPERATOR ^? (ltree, _lquery);
-
-DROP OPERATOR ? (_lquery, ltree);
-
-DROP OPERATOR ? (ltree, _lquery);
-
-DROP FUNCTION lt_q_rregex(_lquery,ltree);
-
-DROP FUNCTION lt_q_regex(ltree,_lquery);
-
-DROP OPERATOR ^~ (lquery, ltree);
-
-DROP OPERATOR ^~ (ltree, lquery);
-
-DROP OPERATOR ~ (lquery, ltree);
-
-DROP OPERATOR ~ (ltree, lquery);
-
-DROP FUNCTION ltq_rregex(lquery,ltree);
-
-DROP FUNCTION ltq_regex(ltree,lquery);
-
-DROP TYPE lquery CASCADE;
-
-DROP OPERATOR CLASS ltree_ops USING btree;
-
-DROP OPERATOR || (text, ltree);
-
-DROP OPERATOR || (ltree, text);
-
-DROP OPERATOR || (ltree, ltree);
-
-DROP OPERATOR ^<@ (ltree, ltree);
-
-DROP OPERATOR <@ (ltree, ltree);
-
-DROP OPERATOR ^@> (ltree, ltree);
-
-DROP OPERATOR @> (ltree, ltree);
-
-DROP FUNCTION ltreeparentsel(internal, oid, internal, integer);
-
-DROP FUNCTION ltree_textadd(text,ltree);
-
-DROP FUNCTION ltree_addtext(ltree,text);
-
-DROP FUNCTION ltree_addltree(ltree,ltree);
-
-DROP FUNCTION ltree_risparent(ltree,ltree);
-
-DROP FUNCTION ltree_isparent(ltree,ltree);
-
-DROP FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree,ltree);
-
-DROP FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree,ltree);
-
-DROP FUNCTION lca(ltree,ltree,ltree,ltree,ltree,ltree);
-
-DROP FUNCTION lca(ltree,ltree,ltree,ltree,ltree);
-
-DROP FUNCTION lca(ltree,ltree,ltree,ltree);
-
-DROP FUNCTION lca(ltree,ltree,ltree);
-
-DROP FUNCTION lca(ltree,ltree);
-
-DROP FUNCTION lca(_ltree);
-
-DROP FUNCTION text2ltree(text);
-
-DROP FUNCTION ltree2text(ltree);
-
-DROP FUNCTION nlevel(ltree);
-
-DROP FUNCTION index(ltree,ltree,int4);
-
-DROP FUNCTION index(ltree,ltree);
-
-DROP FUNCTION subpath(ltree,int4);
-
-DROP FUNCTION subpath(ltree,int4,int4);
-
-DROP FUNCTION subltree(ltree,int4,int4);
-
-DROP OPERATOR <> (ltree, ltree);
-
-DROP OPERATOR = (ltree, ltree);
-
-DROP OPERATOR > (ltree, ltree);
-
-DROP OPERATOR >= (ltree, ltree);
-
-DROP OPERATOR <= (ltree, ltree);
-
-DROP OPERATOR < (ltree, ltree);
-
-DROP FUNCTION ltree_ne(ltree,ltree);
-
-DROP FUNCTION ltree_gt(ltree,ltree);
-
-DROP FUNCTION ltree_ge(ltree,ltree);
-
-DROP FUNCTION ltree_eq(ltree,ltree);
-
-DROP FUNCTION ltree_le(ltree,ltree);
-
-DROP FUNCTION ltree_lt(ltree,ltree);
-
-DROP FUNCTION ltree_cmp(ltree,ltree);
-
-DROP TYPE ltree CASCADE;
diff --git a/contrib/oid2name/.gitignore b/contrib/oid2name/.gitignore
new file mode 100644
index 0000000000..fdefde108d
--- /dev/null
+++ b/contrib/oid2name/.gitignore
@@ -0,0 +1 @@
+/oid2name
diff --git a/contrib/oid2name/Makefile b/contrib/oid2name/Makefile
index ce043550af..f695b4a84e 100644
--- a/contrib/oid2name/Makefile
+++ b/contrib/oid2name/Makefile
@@ -1,7 +1,7 @@
-# $PostgreSQL: pgsql/contrib/oid2name/Makefile,v 1.11 2010/05/12 11:33:07 momjian Exp $
+# contrib/oid2name/Makefile
PGFILEDESC = "oid2name - examine the file structure"
-PGAPPICON=win32
+PGAPPICON = win32
PROGRAM = oid2name
OBJS = oid2name.o
diff --git a/contrib/oid2name/oid2name.c b/contrib/oid2name/oid2name.c
index ff824278aa..05c06ccc68 100644
--- a/contrib/oid2name/oid2name.c
+++ b/contrib/oid2name/oid2name.c
@@ -5,7 +5,7 @@
* Originally by
* B. Palmer, bpalmer@crimelabs.net 1-17-2001
*
- * $PostgreSQL: pgsql/contrib/oid2name/oid2name.c,v 1.38 2010/02/26 02:00:32 momjian Exp $
+ * contrib/oid2name/oid2name.c
*/
#include "postgres_fe.h"
diff --git a/contrib/pageinspect/Makefile b/contrib/pageinspect/Makefile
index 3a6b729c17..13ba6d3911 100644
--- a/contrib/pageinspect/Makefile
+++ b/contrib/pageinspect/Makefile
@@ -1,15 +1,10 @@
-#-------------------------------------------------------------------------
-#
-# pageinspect Makefile
-#
-# $PostgreSQL: pgsql/contrib/pageinspect/Makefile,v 1.4 2008/09/30 10:52:09 heikki Exp $
-#
-#-------------------------------------------------------------------------
+# contrib/pageinspect/Makefile
MODULE_big = pageinspect
OBJS = rawpage.o heapfuncs.o btreefuncs.o fsmfuncs.o
-DATA_built = pageinspect.sql
-DATA = uninstall_pageinspect.sql
+
+EXTENSION = pageinspect
+DATA = pageinspect--1.0.sql pageinspect--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
@@ -21,4 +16,3 @@ top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif
-
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
index 4f56864d2e..ef27cd4080 100644
--- a/contrib/pageinspect/btreefuncs.c
+++ b/contrib/pageinspect/btreefuncs.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pageinspect/btreefuncs.c,v 1.10 2009/06/11 14:48:51 momjian Exp $
+ * contrib/pageinspect/btreefuncs.c
*
*
* btreefuncs.c
diff --git a/contrib/pageinspect/fsmfuncs.c b/contrib/pageinspect/fsmfuncs.c
index 5fbf93ba2f..38c4e23fc2 100644
--- a/contrib/pageinspect/fsmfuncs.c
+++ b/contrib/pageinspect/fsmfuncs.c
@@ -9,10 +9,10 @@
* there's hardly any use case for using these without superuser-rights
* anyway.
*
- * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2007-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/pageinspect/fsmfuncs.c,v 1.4 2010/01/02 16:57:32 momjian Exp $
+ * contrib/pageinspect/fsmfuncs.c
*
*-------------------------------------------------------------------------
*/
@@ -35,7 +35,6 @@ Datum
fsm_page_contents(PG_FUNCTION_ARGS)
{
bytea *raw_page = PG_GETARG_BYTEA_P(0);
- int raw_page_size;
StringInfoData sinfo;
FSMPage fsmpage;
int i;
@@ -45,7 +44,6 @@ fsm_page_contents(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use raw page functions"))));
- raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
fsmpage = (FSMPage) PageGetContents(VARDATA(raw_page));
initStringInfo(&sinfo);
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 143a47cb80..20bca0dc53 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -15,10 +15,10 @@
* there's hardly any use case for using these without superuser-rights
* anyway.
*
- * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2007-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/pageinspect/heapfuncs.c,v 1.9 2010/04/02 15:19:22 mha Exp $
+ * contrib/pageinspect/heapfuncs.c
*
*-------------------------------------------------------------------------
*/
@@ -170,8 +170,8 @@ heap_page_items(PG_FUNCTION_ARGS)
values[5] = UInt32GetDatum(HeapTupleHeaderGetXmax(tuphdr));
values[6] = UInt32GetDatum(HeapTupleHeaderGetRawCommandId(tuphdr)); /* shared with xvac */
values[7] = PointerGetDatum(&tuphdr->t_ctid);
- values[8] = UInt16GetDatum(tuphdr->t_infomask2);
- values[9] = UInt16GetDatum(tuphdr->t_infomask);
+ values[8] = UInt32GetDatum(tuphdr->t_infomask2);
+ values[9] = UInt32GetDatum(tuphdr->t_infomask);
values[10] = UInt8GetDatum(tuphdr->t_hoff);
/*
diff --git a/contrib/pageinspect/pageinspect.sql.in b/contrib/pageinspect/pageinspect--1.0.sql
index abf1ddc57c..a711f581e2 100644
--- a/contrib/pageinspect/pageinspect.sql.in
+++ b/contrib/pageinspect/pageinspect--1.0.sql
@@ -1,17 +1,14 @@
-/* $PostgreSQL: pgsql/contrib/pageinspect/pageinspect.sql.in,v 1.7 2009/06/08 16:22:44 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/pageinspect/pageinspect--1.0.sql */
--
-- get_raw_page()
--
-CREATE OR REPLACE FUNCTION get_raw_page(text, int4)
+CREATE FUNCTION get_raw_page(text, int4)
RETURNS bytea
AS 'MODULE_PATHNAME', 'get_raw_page'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION get_raw_page(text, text, int4)
+CREATE FUNCTION get_raw_page(text, text, int4)
RETURNS bytea
AS 'MODULE_PATHNAME', 'get_raw_page_fork'
LANGUAGE C STRICT;
@@ -19,7 +16,7 @@ LANGUAGE C STRICT;
--
-- page_header()
--
-CREATE OR REPLACE FUNCTION page_header(IN page bytea,
+CREATE FUNCTION page_header(IN page bytea,
OUT lsn text,
OUT tli smallint,
OUT flags smallint,
@@ -35,7 +32,7 @@ LANGUAGE C STRICT;
--
-- heap_page_items()
--
-CREATE OR REPLACE FUNCTION heap_page_items(IN page bytea,
+CREATE FUNCTION heap_page_items(IN page bytea,
OUT lp smallint,
OUT lp_off smallint,
OUT lp_flags smallint,
@@ -44,8 +41,8 @@ CREATE OR REPLACE FUNCTION heap_page_items(IN page bytea,
OUT t_xmax xid,
OUT t_field3 int4,
OUT t_ctid tid,
- OUT t_infomask2 smallint,
- OUT t_infomask smallint,
+ OUT t_infomask2 integer,
+ OUT t_infomask integer,
OUT t_hoff smallint,
OUT t_bits text,
OUT t_oid oid)
@@ -56,7 +53,7 @@ LANGUAGE C STRICT;
--
-- bt_metap()
--
-CREATE OR REPLACE FUNCTION bt_metap(IN relname text,
+CREATE FUNCTION bt_metap(IN relname text,
OUT magic int4,
OUT version int4,
OUT root int4,
@@ -69,7 +66,7 @@ LANGUAGE C STRICT;
--
-- bt_page_stats()
--
-CREATE OR REPLACE FUNCTION bt_page_stats(IN relname text, IN blkno int4,
+CREATE FUNCTION bt_page_stats(IN relname text, IN blkno int4,
OUT blkno int4,
OUT type "char",
OUT live_items int4,
@@ -87,7 +84,7 @@ LANGUAGE C STRICT;
--
-- bt_page_items()
--
-CREATE OR REPLACE FUNCTION bt_page_items(IN relname text, IN blkno int4,
+CREATE FUNCTION bt_page_items(IN relname text, IN blkno int4,
OUT itemoffset smallint,
OUT ctid tid,
OUT itemlen smallint,
@@ -101,7 +98,7 @@ LANGUAGE C STRICT;
--
-- fsm_page_contents()
--
-CREATE OR REPLACE FUNCTION fsm_page_contents(IN page bytea)
+CREATE FUNCTION fsm_page_contents(IN page bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'fsm_page_contents'
LANGUAGE C STRICT;
diff --git a/contrib/pageinspect/pageinspect--unpackaged--1.0.sql b/contrib/pageinspect/pageinspect--unpackaged--1.0.sql
new file mode 100644
index 0000000000..7d4feaf034
--- /dev/null
+++ b/contrib/pageinspect/pageinspect--unpackaged--1.0.sql
@@ -0,0 +1,28 @@
+/* contrib/pageinspect/pageinspect--unpackaged--1.0.sql */
+
+DROP FUNCTION heap_page_items(bytea);
+CREATE FUNCTION heap_page_items(IN page bytea,
+ OUT lp smallint,
+ OUT lp_off smallint,
+ OUT lp_flags smallint,
+ OUT lp_len smallint,
+ OUT t_xmin xid,
+ OUT t_xmax xid,
+ OUT t_field3 int4,
+ OUT t_ctid tid,
+ OUT t_infomask2 integer,
+ OUT t_infomask integer,
+ OUT t_hoff smallint,
+ OUT t_bits text,
+ OUT t_oid oid)
+RETURNS SETOF record
+AS 'MODULE_PATHNAME', 'heap_page_items'
+LANGUAGE C STRICT;
+
+ALTER EXTENSION pageinspect ADD function get_raw_page(text,integer);
+ALTER EXTENSION pageinspect ADD function get_raw_page(text,text,integer);
+ALTER EXTENSION pageinspect ADD function page_header(bytea);
+ALTER EXTENSION pageinspect ADD function bt_metap(text);
+ALTER EXTENSION pageinspect ADD function bt_page_stats(text,integer);
+ALTER EXTENSION pageinspect ADD function bt_page_items(text,integer);
+ALTER EXTENSION pageinspect ADD function fsm_page_contents(bytea);
diff --git a/contrib/pageinspect/pageinspect.control b/contrib/pageinspect/pageinspect.control
new file mode 100644
index 0000000000..f9da0e86ed
--- /dev/null
+++ b/contrib/pageinspect/pageinspect.control
@@ -0,0 +1,5 @@
+# pageinspect extension
+comment = 'inspect the contents of database pages at a low level'
+default_version = '1.0'
+module_pathname = '$libdir/pageinspect'
+relocatable = true
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
index 9043fa37bd..2607576c37 100644
--- a/contrib/pageinspect/rawpage.c
+++ b/contrib/pageinspect/rawpage.c
@@ -5,10 +5,10 @@
*
* Access-method specific inspection functions are in separate files.
*
- * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2007-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.14 2010/01/02 16:57:32 momjian Exp $
+ * contrib/pageinspect/rawpage.c
*
*-------------------------------------------------------------------------
*/
@@ -119,6 +119,11 @@ get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot get raw page from composite type \"%s\"",
RelationGetRelationName(rel))));
+ if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot get raw page from foreign table \"%s\"",
+ RelationGetRelationName(rel))));
/*
* Reject attempts to read non-local temporary relations; we would be
diff --git a/contrib/pageinspect/uninstall_pageinspect.sql b/contrib/pageinspect/uninstall_pageinspect.sql
deleted file mode 100644
index 8c0a7f7f37..0000000000
--- a/contrib/pageinspect/uninstall_pageinspect.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pageinspect/uninstall_pageinspect.sql,v 1.5 2009/06/08 16:22:44 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION get_raw_page(text, int4);
-DROP FUNCTION get_raw_page(text, text, int4);
-DROP FUNCTION page_header(bytea);
-DROP FUNCTION heap_page_items(bytea);
-DROP FUNCTION bt_metap(text);
-DROP FUNCTION bt_page_stats(text, int4);
-DROP FUNCTION bt_page_items(text, int4);
-DROP FUNCTION fsm_page_contents(bytea);
diff --git a/contrib/passwordcheck/Makefile b/contrib/passwordcheck/Makefile
index 1d2c8b1c34..4829bfd1f3 100644
--- a/contrib/passwordcheck/Makefile
+++ b/contrib/passwordcheck/Makefile
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/contrib/passwordcheck/Makefile,v 1.1 2009/11/18 21:57:56 tgl Exp $
+# contrib/passwordcheck/Makefile
MODULE_big = passwordcheck
OBJS = passwordcheck.o
diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c
index adf417769e..711ec9fc36 100644
--- a/contrib/passwordcheck/passwordcheck.c
+++ b/contrib/passwordcheck/passwordcheck.c
@@ -3,12 +3,12 @@
* passwordcheck.c
*
*
- * Copyright (c) 2009-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2009-2011, PostgreSQL Global Development Group
*
* Author: Laurenz Albe <laurenz.albe@wien.gv.at>
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/passwordcheck/passwordcheck.c,v 1.3 2010/02/26 02:00:32 momjian Exp $
+ * contrib/passwordcheck/passwordcheck.c
*
*-------------------------------------------------------------------------
*/
diff --git a/contrib/pg_archivecleanup/.gitignore b/contrib/pg_archivecleanup/.gitignore
new file mode 100644
index 0000000000..804089070d
--- /dev/null
+++ b/contrib/pg_archivecleanup/.gitignore
@@ -0,0 +1 @@
+/pg_archivecleanup
diff --git a/contrib/pg_archivecleanup/Makefile b/contrib/pg_archivecleanup/Makefile
index d858b5bcd3..39c55d8713 100644
--- a/contrib/pg_archivecleanup/Makefile
+++ b/contrib/pg_archivecleanup/Makefile
@@ -1,7 +1,7 @@
-# $PostgreSQL: pgsql/contrib/pg_archivecleanup/Makefile,v 1.1 2010/06/14 16:19:24 sriggs Exp $
+# contrib/pg_archivecleanup/Makefile
PGFILEDESC = "pg_archivecleanup - cleans archive when used with streaming replication"
-PGAPPICON=win32
+PGAPPICON = win32
PROGRAM = pg_archivecleanup
OBJS = pg_archivecleanup.o
diff --git a/contrib/pg_archivecleanup/pg_archivecleanup.c b/contrib/pg_archivecleanup/pg_archivecleanup.c
index 0f53b4d439..dd8a45133c 100644
--- a/contrib/pg_archivecleanup/pg_archivecleanup.c
+++ b/contrib/pg_archivecleanup/pg_archivecleanup.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pg_archivecleanup/pg_archivecleanup.c,v 1.3 2010/07/06 19:18:55 momjian Exp $
+ * contrib/pg_archivecleanup/pg_archivecleanup.c
*
* pg_archivecleanup.c
*
@@ -18,15 +18,15 @@
#include <fcntl.h>
#include <signal.h>
-#ifdef WIN32
-int getopt(int argc, char *const argv[], const char *optstring);
-#else
+#ifndef WIN32
#include <sys/time.h>
#include <unistd.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
+#else /* WIN32 */
+extern int getopt(int argc, char *const argv[], const char *optstring);
#endif /* ! WIN32 */
extern char *optarg;
@@ -117,12 +117,8 @@ CleanupPriorWALFiles(void)
strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_DATA_FNAME_LEN &&
strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
{
-#ifdef WIN32
- snprintf(WALFilePath, MAXPGPATH, "%s\\%s", archiveLocation, xlde->d_name);
-#else
- snprintf(WALFilePath, MAXPGPATH, "%s/%s", archiveLocation, xlde->d_name);
-#endif
-
+ snprintf(WALFilePath, MAXPGPATH, "%s/%s",
+ archiveLocation, xlde->d_name);
if (debug)
fprintf(stderr, "%s: removing file \"%s\"\n",
progname, WALFilePath);
@@ -207,19 +203,19 @@ usage(void)
printf("%s removes older WAL files from PostgreSQL archives.\n\n", progname);
printf("Usage:\n");
printf(" %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n", progname);
+ printf("\nOptions:\n");
+ printf(" -d generates debug output (verbose mode)\n");
+ printf(" --help show this help, then exit\n");
+ printf(" --version output version information, then exit\n");
printf("\n"
- "for use as an archive_cleanup_command in the recovery.conf when standby_mode = on:\n"
+ "For use as archive_cleanup_command in recovery.conf when standby_mode = on:\n"
" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
"e.g.\n"
" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n");
printf("\n"
- "or for use as a standalone archive cleaner:\n"
+ "Or for use as a standalone archive cleaner:\n"
"e.g.\n"
" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n");
- printf("\nOptions:\n");
- printf(" -d generates debug output (verbose mode)\n");
- printf(" --help show this help, then exit\n");
- printf(" --version output version information, then exit\n");
printf("\nReport bugs to <pgsql-bugs@postgresql.org>.\n");
}
@@ -308,8 +304,12 @@ main(int argc, char **argv)
SetWALFileNameForCleanup();
if (debug)
+ {
+ snprintf(WALFilePath, MAXPGPATH, "%s/%s",
+ archiveLocation, exclusiveCleanupFileName);
fprintf(stderr, "%s: keep WAL file \"%s\" and later\n",
- progname, exclusiveCleanupFileName);
+ progname, WALFilePath);
+ }
/*
* Remove WAL files older than cut-off
diff --git a/contrib/pg_buffercache/Makefile b/contrib/pg_buffercache/Makefile
index 83aee70de1..323c0ac8ed 100644
--- a/contrib/pg_buffercache/Makefile
+++ b/contrib/pg_buffercache/Makefile
@@ -1,10 +1,10 @@
-# $PostgreSQL: pgsql/contrib/pg_buffercache/Makefile,v 1.5 2007/11/10 23:59:51 momjian Exp $
+# contrib/pg_buffercache/Makefile
MODULE_big = pg_buffercache
-OBJS = pg_buffercache_pages.o
+OBJS = pg_buffercache_pages.o
-DATA_built = pg_buffercache.sql
-DATA = uninstall_pg_buffercache.sql
+EXTENSION = pg_buffercache
+DATA = pg_buffercache--1.0.sql pg_buffercache--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/pg_buffercache/pg_buffercache.sql.in b/contrib/pg_buffercache/pg_buffercache--1.0.sql
index 59ada02e4c..9407d21410 100644
--- a/contrib/pg_buffercache/pg_buffercache.sql.in
+++ b/contrib/pg_buffercache/pg_buffercache--1.0.sql
@@ -1,10 +1,7 @@
-/* $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache.sql.in,v 1.8 2008/08/14 12:56:41 heikki Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/pg_buffercache/pg_buffercache--1.0.sql */
-- Register the function.
-CREATE OR REPLACE FUNCTION pg_buffercache_pages()
+CREATE FUNCTION pg_buffercache_pages()
RETURNS SETOF RECORD
AS 'MODULE_PATHNAME', 'pg_buffercache_pages'
LANGUAGE C;
@@ -12,9 +9,9 @@ LANGUAGE C;
-- Create a view for convenient access.
CREATE VIEW pg_buffercache AS
SELECT P.* FROM pg_buffercache_pages() AS P
- (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
+ (bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid,
relforknumber int2, relblocknumber int8, isdirty bool, usagecount int2);
-
--- Don't want these to be available at public.
+
+-- Don't want these to be available to public.
REVOKE ALL ON FUNCTION pg_buffercache_pages() FROM PUBLIC;
REVOKE ALL ON pg_buffercache FROM PUBLIC;
diff --git a/contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql b/contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql
new file mode 100644
index 0000000000..f00a954d86
--- /dev/null
+++ b/contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql
@@ -0,0 +1,4 @@
+/* contrib/pg_buffercache/pg_buffercache--unpackaged--1.0.sql */
+
+ALTER EXTENSION pg_buffercache ADD function pg_buffercache_pages();
+ALTER EXTENSION pg_buffercache ADD view pg_buffercache;
diff --git a/contrib/pg_buffercache/pg_buffercache.control b/contrib/pg_buffercache/pg_buffercache.control
new file mode 100644
index 0000000000..709513c334
--- /dev/null
+++ b/contrib/pg_buffercache/pg_buffercache.control
@@ -0,0 +1,5 @@
+# pg_buffercache extension
+comment = 'examine the shared buffer cache'
+default_version = '1.0'
+module_pathname = '$libdir/pg_buffercache'
+relocatable = true
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index 5939f52a04..ed882881ab 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -3,7 +3,7 @@
* pg_buffercache_pages.c
* display some contents of the buffer cache
*
- * $PostgreSQL: pgsql/contrib/pg_buffercache/pg_buffercache_pages.c,v 1.16 2009/06/11 14:48:51 momjian Exp $
+ * contrib/pg_buffercache/pg_buffercache_pages.c
*-------------------------------------------------------------------------
*/
#include "postgres.h"
diff --git a/contrib/pg_buffercache/uninstall_pg_buffercache.sql b/contrib/pg_buffercache/uninstall_pg_buffercache.sql
deleted file mode 100644
index 19dc9301ca..0000000000
--- a/contrib/pg_buffercache/uninstall_pg_buffercache.sql
+++ /dev/null
@@ -1,8 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pg_buffercache/uninstall_pg_buffercache.sql,v 1.3 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP VIEW pg_buffercache;
-
-DROP FUNCTION pg_buffercache_pages();
diff --git a/contrib/pg_freespacemap/Makefile b/contrib/pg_freespacemap/Makefile
index daeab59d46..b2e3ba3aa3 100644
--- a/contrib/pg_freespacemap/Makefile
+++ b/contrib/pg_freespacemap/Makefile
@@ -1,10 +1,10 @@
-# $PostgreSQL: pgsql/contrib/pg_freespacemap/Makefile,v 1.5 2008/09/30 11:17:07 heikki Exp $
+# contrib/pg_freespacemap/Makefile
MODULE_big = pg_freespacemap
-OBJS = pg_freespacemap.o
+OBJS = pg_freespacemap.o
-DATA_built = pg_freespacemap.sql
-DATA = uninstall_pg_freespacemap.sql
+EXTENSION = pg_freespacemap
+DATA = pg_freespacemap--1.0.sql pg_freespacemap--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/pg_freespacemap/pg_freespacemap.sql.in b/contrib/pg_freespacemap/pg_freespacemap--1.0.sql
index 7054380386..d63420e33a 100644
--- a/contrib/pg_freespacemap/pg_freespacemap.sql.in
+++ b/contrib/pg_freespacemap/pg_freespacemap--1.0.sql
@@ -1,17 +1,13 @@
-/* $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.sql.in,v 1.12 2009/06/10 22:12:28 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
+/* contrib/pg_freespacemap/pg_freespacemap--1.0.sql */
-- Register the C function.
-CREATE OR REPLACE FUNCTION pg_freespace(regclass, bigint)
+CREATE FUNCTION pg_freespace(regclass, bigint)
RETURNS int2
AS 'MODULE_PATHNAME', 'pg_freespace'
LANGUAGE C STRICT;
-- pg_freespace shows the recorded space avail at each block in a relation
-CREATE OR REPLACE FUNCTION
+CREATE FUNCTION
pg_freespace(rel regclass, blkno OUT bigint, avail OUT int2)
RETURNS SETOF RECORD
AS $$
diff --git a/contrib/pg_freespacemap/pg_freespacemap--unpackaged--1.0.sql b/contrib/pg_freespacemap/pg_freespacemap--unpackaged--1.0.sql
new file mode 100644
index 0000000000..4c7487fa4e
--- /dev/null
+++ b/contrib/pg_freespacemap/pg_freespacemap--unpackaged--1.0.sql
@@ -0,0 +1,4 @@
+/* contrib/pg_freespacemap/pg_freespacemap--unpackaged--1.0.sql */
+
+ALTER EXTENSION pg_freespacemap ADD function pg_freespace(regclass,bigint);
+ALTER EXTENSION pg_freespacemap ADD function pg_freespace(regclass);
diff --git a/contrib/pg_freespacemap/pg_freespacemap.c b/contrib/pg_freespacemap/pg_freespacemap.c
index 4b1dece12a..bf6b0df8f9 100644
--- a/contrib/pg_freespacemap/pg_freespacemap.c
+++ b/contrib/pg_freespacemap/pg_freespacemap.c
@@ -3,7 +3,7 @@
* pg_freespacemap.c
* display contents of a free space map
*
- * $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.c,v 1.14 2009/06/11 14:48:51 momjian Exp $
+ * contrib/pg_freespacemap/pg_freespacemap.c
*-------------------------------------------------------------------------
*/
#include "postgres.h"
diff --git a/contrib/pg_freespacemap/pg_freespacemap.control b/contrib/pg_freespacemap/pg_freespacemap.control
new file mode 100644
index 0000000000..34b695ff75
--- /dev/null
+++ b/contrib/pg_freespacemap/pg_freespacemap.control
@@ -0,0 +1,5 @@
+# pg_freespacemap extension
+comment = 'examine the free space map (FSM)'
+default_version = '1.0'
+module_pathname = '$libdir/pg_freespacemap'
+relocatable = true
diff --git a/contrib/pg_freespacemap/uninstall_pg_freespacemap.sql b/contrib/pg_freespacemap/uninstall_pg_freespacemap.sql
deleted file mode 100644
index e9bf0ad7d1..0000000000
--- a/contrib/pg_freespacemap/uninstall_pg_freespacemap.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pg_freespacemap/uninstall_pg_freespacemap.sql,v 1.5 2009/06/10 22:12:28 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION pg_freespace(regclass, bigint);
-DROP FUNCTION pg_freespace(regclass);
diff --git a/contrib/pg_standby/.gitignore b/contrib/pg_standby/.gitignore
new file mode 100644
index 0000000000..a401b085a8
--- /dev/null
+++ b/contrib/pg_standby/.gitignore
@@ -0,0 +1 @@
+/pg_standby
diff --git a/contrib/pg_standby/Makefile b/contrib/pg_standby/Makefile
index 5e6bbd9145..b7c6ae95e7 100644
--- a/contrib/pg_standby/Makefile
+++ b/contrib/pg_standby/Makefile
@@ -1,7 +1,7 @@
-# $PostgreSQL: pgsql/contrib/pg_standby/Makefile,v 1.6 2010/05/12 11:33:07 momjian Exp $
+# contrib/pg_standby/Makefile
PGFILEDESC = "pg_standby - supports creation of a warm standby"
-PGAPPICON=win32
+PGAPPICON = win32
PROGRAM = pg_standby
OBJS = pg_standby.o
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
index 70680e762d..d2e0d582f2 100644
--- a/contrib/pg_standby/pg_standby.c
+++ b/contrib/pg_standby/pg_standby.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pg_standby/pg_standby.c,v 1.29 2010/05/15 09:31:57 heikki Exp $
+ * contrib/pg_standby/pg_standby.c
*
*
* pg_standby.c
@@ -119,7 +119,7 @@ struct stat stat_buf;
* accessible directory. If you want to make other assumptions,
* such as using a vendor-specific archive and access API, these
* routines are the ones you'll need to change. You're
- * enouraged to submit any changes to pgsql-hackers@postgresql.org
+ * encouraged to submit any changes to pgsql-hackers@postgresql.org
* or personally to the current maintainer. Those changes may be
* folded in to later versions of this program.
*/
@@ -252,7 +252,7 @@ CustomizableCleanupPriorWALFiles(void)
/*
* Assume it's OK to keep failing. The failure situation may change
* over time, so we'd rather keep going on the main processing than
- * fail because we couldnt clean up yet.
+ * fail because we couldn't clean up yet.
*/
if ((xldir = opendir(archiveLocation)) != NULL)
{
@@ -515,11 +515,6 @@ usage(void)
printf("%s allows PostgreSQL warm standby servers to be configured.\n\n", progname);
printf("Usage:\n");
printf(" %s [OPTION]... ARCHIVELOCATION NEXTWALFILE XLOGFILEPATH [RESTARTWALFILE]\n", progname);
- printf("\n"
- "with main intended use as a restore_command in the recovery.conf:\n"
- " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
- "e.g.\n"
- " restore_command = 'pg_standby -l /mnt/server/archiverdir %%f %%p %%r'\n");
printf("\nOptions:\n");
printf(" -c copies file from archive (default)\n");
printf(" -d generate lots of debugging output (testing only)\n");
@@ -534,6 +529,11 @@ usage(void)
printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
printf(" --help show this help, then exit\n");
printf(" --version output version information, then exit\n");
+ printf("\n"
+ "Main intended use as restore_command in recovery.conf:\n"
+ " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
+ "e.g.\n"
+ " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
printf("\nReport bugs to <pgsql-bugs@postgresql.org>.\n");
}
@@ -722,20 +722,20 @@ main(int argc, char **argv)
if (debug)
{
- fprintf(stderr, "Trigger file : %s\n", triggerPath ? triggerPath : "<not set>");
- fprintf(stderr, "Waiting for WAL file : %s\n", nextWALFileName);
- fprintf(stderr, "WAL file path : %s\n", WALFilePath);
- fprintf(stderr, "Restoring to : %s\n", xlogFilePath);
- fprintf(stderr, "Sleep interval : %d second%s\n",
+ fprintf(stderr, "Trigger file: %s\n", triggerPath ? triggerPath : "<not set>");
+ fprintf(stderr, "Waiting for WAL file: %s\n", nextWALFileName);
+ fprintf(stderr, "WAL file path: %s\n", WALFilePath);
+ fprintf(stderr, "Restoring to: %s\n", xlogFilePath);
+ fprintf(stderr, "Sleep interval: %d second%s\n",
sleeptime, (sleeptime > 1 ? "s" : " "));
- fprintf(stderr, "Max wait interval : %d %s\n",
+ fprintf(stderr, "Max wait interval: %d %s\n",
maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
- fprintf(stderr, "Command for restore : %s\n", restoreCommand);
- fprintf(stderr, "Keep archive history : ");
+ fprintf(stderr, "Command for restore: %s\n", restoreCommand);
+ fprintf(stderr, "Keep archive history: ");
if (need_cleanup)
fprintf(stderr, "%s and later\n", exclusiveCleanupFileName);
else
- fprintf(stderr, "No cleanup required\n");
+ fprintf(stderr, "no cleanup required\n");
fflush(stderr);
}
diff --git a/contrib/pg_stat_statements/Makefile b/contrib/pg_stat_statements/Makefile
index ce335a656e..e086fd8a82 100644
--- a/contrib/pg_stat_statements/Makefile
+++ b/contrib/pg_stat_statements/Makefile
@@ -1,10 +1,11 @@
-# $PostgreSQL: pgsql/contrib/pg_stat_statements/Makefile,v 1.1 2009/01/04 22:19:59 tgl Exp $
+# contrib/pg_stat_statements/Makefile
MODULE_big = pg_stat_statements
-DATA_built = pg_stat_statements.sql
-DATA = uninstall_pg_stat_statements.sql
OBJS = pg_stat_statements.o
+EXTENSION = pg_stat_statements
+DATA = pg_stat_statements--1.0.sql pg_stat_statements--unpackaged--1.0.sql
+
ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
diff --git a/contrib/pg_stat_statements/pg_stat_statements.sql.in b/contrib/pg_stat_statements/pg_stat_statements--1.0.sql
index cf82a0e3dc..e17b82c616 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.sql.in
+++ b/contrib/pg_stat_statements/pg_stat_statements--1.0.sql
@@ -1,7 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/pg_stat_statements/pg_stat_statements.sql.in,v 1.2 2010/01/08 00:38:19 itagaki Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/pg_stat_statements/pg_stat_statements--1.0.sql */
-- Register functions.
CREATE FUNCTION pg_stat_statements_reset()
diff --git a/contrib/pg_stat_statements/pg_stat_statements--unpackaged--1.0.sql b/contrib/pg_stat_statements/pg_stat_statements--unpackaged--1.0.sql
new file mode 100644
index 0000000000..9dda85cbdf
--- /dev/null
+++ b/contrib/pg_stat_statements/pg_stat_statements--unpackaged--1.0.sql
@@ -0,0 +1,5 @@
+/* contrib/pg_stat_statements/pg_stat_statements--unpackaged--1.0.sql */
+
+ALTER EXTENSION pg_stat_statements ADD function pg_stat_statements_reset();
+ALTER EXTENSION pg_stat_statements ADD function pg_stat_statements();
+ALTER EXTENSION pg_stat_statements ADD view pg_stat_statements;
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index eb89aeca80..0236b87498 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -11,10 +11,10 @@
* disappear!) and also take the entry's mutex spinlock.
*
*
- * Copyright (c) 2008-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2008-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/pg_stat_statements/pg_stat_statements.c,v 1.14 2010/04/28 16:54:15 tgl Exp $
+ * contrib/pg_stat_statements/pg_stat_statements.c
*
*-------------------------------------------------------------------------
*/
@@ -122,6 +122,7 @@ static int nested_level = 0;
static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
static ExecutorStart_hook_type prev_ExecutorStart = NULL;
static ExecutorRun_hook_type prev_ExecutorRun = NULL;
+static ExecutorFinish_hook_type prev_ExecutorFinish = NULL;
static ExecutorEnd_hook_type prev_ExecutorEnd = NULL;
static ProcessUtility_hook_type prev_ProcessUtility = NULL;
@@ -136,7 +137,7 @@ typedef enum
PGSS_TRACK_NONE, /* track no statements */
PGSS_TRACK_TOP, /* only top level statements */
PGSS_TRACK_ALL /* all statements, including nested ones */
-} PGSSTrackLevel;
+} PGSSTrackLevel;
static const struct config_enum_entry track_options[] =
{
@@ -173,6 +174,7 @@ static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags);
static void pgss_ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction,
long count);
+static void pgss_ExecutorFinish(QueryDesc *queryDesc);
static void pgss_ExecutorEnd(QueryDesc *queryDesc);
static void pgss_ProcessUtility(Node *parsetree,
const char *queryString, ParamListInfo params, bool isTopLevel,
@@ -217,6 +219,7 @@ _PG_init(void)
PGC_POSTMASTER,
0,
NULL,
+ NULL,
NULL);
DefineCustomEnumVariable("pg_stat_statements.track",
@@ -228,6 +231,7 @@ _PG_init(void)
PGC_SUSET,
0,
NULL,
+ NULL,
NULL);
DefineCustomBoolVariable("pg_stat_statements.track_utility",
@@ -238,6 +242,7 @@ _PG_init(void)
PGC_SUSET,
0,
NULL,
+ NULL,
NULL);
DefineCustomBoolVariable("pg_stat_statements.save",
@@ -248,6 +253,7 @@ _PG_init(void)
PGC_SIGHUP,
0,
NULL,
+ NULL,
NULL);
EmitWarningsOnPlaceholders("pg_stat_statements");
@@ -269,6 +275,8 @@ _PG_init(void)
ExecutorStart_hook = pgss_ExecutorStart;
prev_ExecutorRun = ExecutorRun_hook;
ExecutorRun_hook = pgss_ExecutorRun;
+ prev_ExecutorFinish = ExecutorFinish_hook;
+ ExecutorFinish_hook = pgss_ExecutorFinish;
prev_ExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = pgss_ExecutorEnd;
prev_ProcessUtility = ProcessUtility_hook;
@@ -285,6 +293,7 @@ _PG_fini(void)
shmem_startup_hook = prev_shmem_startup_hook;
ExecutorStart_hook = prev_ExecutorStart;
ExecutorRun_hook = prev_ExecutorRun;
+ ExecutorFinish_hook = prev_ExecutorFinish;
ExecutorEnd_hook = prev_ExecutorEnd;
ProcessUtility_hook = prev_ProcessUtility;
}
@@ -550,6 +559,29 @@ pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long count)
}
/*
+ * ExecutorFinish hook: all we need do is track nesting depth
+ */
+static void
+pgss_ExecutorFinish(QueryDesc *queryDesc)
+{
+ nested_level++;
+ PG_TRY();
+ {
+ if (prev_ExecutorFinish)
+ prev_ExecutorFinish(queryDesc);
+ else
+ standard_ExecutorFinish(queryDesc);
+ nested_level--;
+ }
+ PG_CATCH();
+ {
+ nested_level--;
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+}
+
+/*
* ExecutorEnd hook: store results if needed
*/
static void
diff --git a/contrib/pg_stat_statements/pg_stat_statements.control b/contrib/pg_stat_statements/pg_stat_statements.control
new file mode 100644
index 0000000000..6f9a947122
--- /dev/null
+++ b/contrib/pg_stat_statements/pg_stat_statements.control
@@ -0,0 +1,5 @@
+# pg_stat_statements extension
+comment = 'track execution statistics of all SQL statements executed'
+default_version = '1.0'
+module_pathname = '$libdir/pg_stat_statements'
+relocatable = true
diff --git a/contrib/pg_stat_statements/uninstall_pg_stat_statements.sql b/contrib/pg_stat_statements/uninstall_pg_stat_statements.sql
deleted file mode 100644
index 31fd0af39d..0000000000
--- a/contrib/pg_stat_statements/uninstall_pg_stat_statements.sql
+++ /dev/null
@@ -1,8 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pg_stat_statements/uninstall_pg_stat_statements.sql,v 1.1 2009/01/04 22:19:59 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP VIEW pg_stat_statements;
-DROP FUNCTION pg_stat_statements();
-DROP FUNCTION pg_stat_statements_reset();
diff --git a/contrib/pg_test_fsync/.gitignore b/contrib/pg_test_fsync/.gitignore
new file mode 100644
index 0000000000..f3b5932498
--- /dev/null
+++ b/contrib/pg_test_fsync/.gitignore
@@ -0,0 +1 @@
+/pg_test_fsync
diff --git a/contrib/pg_test_fsync/Makefile b/contrib/pg_test_fsync/Makefile
new file mode 100644
index 0000000000..b456429098
--- /dev/null
+++ b/contrib/pg_test_fsync/Makefile
@@ -0,0 +1,18 @@
+# contrib/pg_test_fsync/Makefile
+
+PGFILEDESC = "pg_test_fsync - test various disk sync methods"
+PGAPPICON = win32
+
+PROGRAM = pg_test_fsync
+OBJS = pg_test_fsync.o
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/pg_test_fsync
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/pg_test_fsync/pg_test_fsync.c b/contrib/pg_test_fsync/pg_test_fsync.c
new file mode 100644
index 0000000000..3791f5a071
--- /dev/null
+++ b/contrib/pg_test_fsync/pg_test_fsync.c
@@ -0,0 +1,527 @@
+/*
+ * pg_test_fsync.c
+ * tests all supported fsync() methods
+ */
+
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "getopt_long.h"
+#include "access/xlogdefs.h"
+
+
+/*
+ * put the temp files in the local directory
+ * unless the user specifies otherwise
+ */
+#define FSYNC_FILENAME "./pg_test_fsync.out"
+
+#define XLOG_BLCKSZ_K (XLOG_BLCKSZ / 1024)
+
+#define LABEL_FORMAT " %-32s"
+#define NA_FORMAT "%18s"
+#define OPS_FORMAT "%9.3f ops/sec"
+
+static const char *progname;
+
+static int ops_per_test = 2000;
+static char full_buf[XLOG_SEG_SIZE],
+ *buf,
+ *filename = FSYNC_FILENAME;
+static struct timeval start_t,
+ stop_t;
+
+
+static void handle_args(int argc, char *argv[]);
+static void prepare_buf(void);
+static void test_open(void);
+static void test_non_sync(void);
+static void test_sync(int writes_per_op);
+static void test_open_syncs(void);
+static void test_open_sync(const char *msg, int writes_size);
+static void test_file_descriptor_sync(void);
+
+#ifdef HAVE_FSYNC_WRITETHROUGH
+static int pg_fsync_writethrough(int fd);
+#endif
+static void print_elapse(struct timeval start_t, struct timeval stop_t);
+static void die(const char *str);
+
+
+int
+main(int argc, char *argv[])
+{
+ progname = get_progname(argv[0]);
+
+ handle_args(argc, argv);
+
+ prepare_buf();
+
+ test_open();
+
+ /* Test using 1 XLOG_BLCKSZ write */
+ test_sync(1);
+
+ /* Test using 2 XLOG_BLCKSZ writes */
+ test_sync(2);
+
+ test_open_syncs();
+
+ test_file_descriptor_sync();
+
+ test_non_sync();
+
+ unlink(filename);
+
+ return 0;
+}
+
+static void
+handle_args(int argc, char *argv[])
+{
+ static struct option long_options[] = {
+ {"filename", required_argument, NULL, 'f'},
+ {"ops-per-test", required_argument, NULL, 'o'},
+ {NULL, 0, NULL, 0}
+ };
+ int option; /* Command line option */
+ int optindex = 0; /* used by getopt_long */
+
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
+ strcmp(argv[1], "-?") == 0)
+ {
+ printf("Usage: %s [-f FILENAME] [-o OPS-PER-TEST]\n", progname);
+ exit(0);
+ }
+ if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
+ {
+ puts("pg_test_fsync (PostgreSQL) " PG_VERSION);
+ exit(0);
+ }
+ }
+
+ while ((option = getopt_long(argc, argv, "f:o:",
+ long_options, &optindex)) != -1)
+ {
+ switch (option)
+ {
+ case 'f':
+ filename = strdup(optarg);
+ break;
+
+ case 'o':
+ ops_per_test = atoi(optarg);
+ break;
+
+ default:
+ fprintf(stderr, "Try \"%s --help\" for more information.\n",
+ progname);
+ exit(1);
+ break;
+ }
+ }
+
+ if (argc > optind)
+ {
+ fprintf(stderr,
+ "%s: too many command-line arguments (first is \"%s\")\n",
+ progname, argv[optind]);
+ fprintf(stderr, "Try \"%s --help\" for more information.\n",
+ progname);
+ exit(1);
+ }
+
+ printf("%d operations per test\n", ops_per_test);
+#if PG_O_DIRECT != 0
+ printf("O_DIRECT supported on this platform for open_datasync and open_sync.\n");
+#else
+ printf("Direct I/O is not supported on this platform.\n");
+#endif
+}
+
+static void
+prepare_buf(void)
+{
+ int ops;
+
+ /* write random data into buffer */
+ for (ops = 0; ops < XLOG_SEG_SIZE; ops++)
+ full_buf[ops] = random();
+
+ buf = (char *) TYPEALIGN(ALIGNOF_XLOG_BUFFER, full_buf);
+}
+
+static void
+test_open(void)
+{
+ int tmpfile;
+
+ /*
+ * test if we can open the target file
+ */
+ if ((tmpfile = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
+ die("could not open output file");
+ if (write(tmpfile, full_buf, XLOG_SEG_SIZE) != XLOG_SEG_SIZE)
+ die("write failed");
+
+ /* fsync now so that dirty buffers don't skew later tests */
+ if (fsync(tmpfile) != 0)
+ die("fsync failed");
+
+ close(tmpfile);
+}
+
+static void
+test_sync(int writes_per_op)
+{
+ int tmpfile,
+ ops,
+ writes;
+ bool fs_warning = false;
+
+ if (writes_per_op == 1)
+ printf("\nCompare file sync methods using one %dkB write:\n", XLOG_BLCKSZ_K);
+ else
+ printf("\nCompare file sync methods using two %dkB writes:\n", XLOG_BLCKSZ_K);
+ printf("(in wal_sync_method preference order, except fdatasync\n");
+ printf("is Linux's default)\n");
+
+ /*
+ * Test open_datasync if available
+ */
+ printf(LABEL_FORMAT, "open_datasync");
+ fflush(stdout);
+
+#ifdef OPEN_DATASYNC_FLAG
+ if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1)
+ {
+ printf(NA_FORMAT, "n/a*\n");
+ fs_warning = true;
+ }
+ else
+ {
+ if ((tmpfile = open(filename, O_RDWR | O_DSYNC | PG_O_DIRECT, 0)) == -1)
+ die("could not open output file");
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ for (writes = 0; writes < writes_per_op; writes++)
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ if (lseek(tmpfile, 0, SEEK_SET) == -1)
+ die("seek failed");
+ }
+ gettimeofday(&stop_t, NULL);
+ close(tmpfile);
+ print_elapse(start_t, stop_t);
+ }
+#else
+ printf(NA_FORMAT, "n/a\n");
+#endif
+
+/*
+ * Test fdatasync if available
+ */
+ printf(LABEL_FORMAT, "fdatasync");
+ fflush(stdout);
+
+#ifdef HAVE_FDATASYNC
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ for (writes = 0; writes < writes_per_op; writes++)
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ fdatasync(tmpfile);
+ if (lseek(tmpfile, 0, SEEK_SET) == -1)
+ die("seek failed");
+ }
+ gettimeofday(&stop_t, NULL);
+ close(tmpfile);
+ print_elapse(start_t, stop_t);
+#else
+ printf(NA_FORMAT, "n/a\n");
+#endif
+
+/*
+ * Test fsync
+ */
+ printf(LABEL_FORMAT, "fsync");
+ fflush(stdout);
+
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ for (writes = 0; writes < writes_per_op; writes++)
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ if (fsync(tmpfile) != 0)
+ die("fsync failed");
+ if (lseek(tmpfile, 0, SEEK_SET) == -1)
+ die("seek failed");
+ }
+ gettimeofday(&stop_t, NULL);
+ close(tmpfile);
+ print_elapse(start_t, stop_t);
+
+/*
+ * If fsync_writethrough is available, test as well
+ */
+ printf(LABEL_FORMAT, "fsync_writethrough");
+ fflush(stdout);
+
+#ifdef HAVE_FSYNC_WRITETHROUGH
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ for (writes = 0; writes < writes_per_op; writes++)
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ if (pg_fsync_writethrough(tmpfile) != 0)
+ die("fsync failed");
+ if (lseek(tmpfile, 0, SEEK_SET) == -1)
+ die("seek failed");
+ }
+ gettimeofday(&stop_t, NULL);
+ close(tmpfile);
+ print_elapse(start_t, stop_t);
+#else
+ printf(NA_FORMAT, "n/a\n");
+#endif
+
+/*
+ * Test open_sync if available
+ */
+ printf(LABEL_FORMAT, "open_sync");
+ fflush(stdout);
+
+#ifdef OPEN_SYNC_FLAG
+ if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG | PG_O_DIRECT, 0)) == -1)
+ {
+ printf(NA_FORMAT, "n/a*\n");
+ fs_warning = true;
+ }
+ else
+ {
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ for (writes = 0; writes < writes_per_op; writes++)
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ if (lseek(tmpfile, 0, SEEK_SET) == -1)
+ die("seek failed");
+ }
+ gettimeofday(&stop_t, NULL);
+ close(tmpfile);
+ print_elapse(start_t, stop_t);
+ }
+#else
+ printf(NA_FORMAT, "n/a\n");
+#endif
+
+ if (fs_warning)
+ {
+ printf("* This file system and its mount options do not support direct\n");
+ printf("I/O, e.g. ext4 in journaled mode.\n");
+ }
+}
+
+static void
+test_open_syncs(void)
+{
+ printf("\nCompare open_sync with different write sizes:\n");
+ printf("(This is designed to compare the cost of writing 16kB\n");
+ printf("in different write open_sync sizes.)\n");
+
+ test_open_sync("16kB open_sync write", 16);
+ test_open_sync(" 8kB open_sync writes", 8);
+ test_open_sync(" 4kB open_sync writes", 4);
+ test_open_sync(" 2kB open_sync writes", 2);
+ test_open_sync(" 1kB open_sync writes", 1);
+}
+
+/*
+ * Test open_sync with different size files
+ */
+static void
+test_open_sync(const char *msg, int writes_size)
+{
+#ifdef OPEN_SYNC_FLAG
+ int tmpfile,
+ ops,
+ writes;
+#endif
+
+ printf(LABEL_FORMAT, msg);
+ fflush(stdout);
+
+#ifdef OPEN_SYNC_FLAG
+ if ((tmpfile = open(filename, O_RDWR | OPEN_SYNC_FLAG | PG_O_DIRECT, 0)) == -1)
+ printf(NA_FORMAT, "n/a*\n");
+ else
+ {
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ for (writes = 0; writes < 16 / writes_size; writes++)
+ if (write(tmpfile, buf, writes_size * 1024) !=
+ writes_size * 1024)
+ die("write failed");
+ if (lseek(tmpfile, 0, SEEK_SET) == -1)
+ die("seek failed");
+ }
+ gettimeofday(&stop_t, NULL);
+ close(tmpfile);
+ print_elapse(start_t, stop_t);
+ }
+#else
+ printf(NA_FORMAT, "n/a\n");
+#endif
+}
+
+static void
+test_file_descriptor_sync(void)
+{
+ int tmpfile,
+ ops;
+
+ /*
+ * Test whether fsync can sync data written on a different descriptor for
+ * the same file. This checks the efficiency of multi-process fsyncs
+ * against the same file. Possibly this should be done with writethrough
+ * on platforms which support it.
+ */
+ printf("\nTest if fsync on non-write file descriptor is honored:\n");
+ printf("(If the times are similar, fsync() can sync data written\n");
+ printf("on a different descriptor.)\n");
+
+ /*
+ * first write, fsync and close, which is the normal behavior without
+ * multiple descriptors
+ */
+ printf(LABEL_FORMAT, "write, fsync, close");
+ fflush(stdout);
+
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ if (fsync(tmpfile) != 0)
+ die("fsync failed");
+ close(tmpfile);
+
+ /*
+ * open and close the file again to be consistent with the following
+ * test
+ */
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ close(tmpfile);
+ }
+ gettimeofday(&stop_t, NULL);
+ print_elapse(start_t, stop_t);
+
+ /*
+ * Now open, write, close, open again and fsync This simulates processes
+ * fsyncing each other's writes.
+ */
+ printf(LABEL_FORMAT, "write, close, fsync");
+ fflush(stdout);
+
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ close(tmpfile);
+ /* reopen file */
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ if (fsync(tmpfile) != 0)
+ die("fsync failed");
+ close(tmpfile);
+ }
+ gettimeofday(&stop_t, NULL);
+ print_elapse(start_t, stop_t);
+
+}
+
+static void
+test_non_sync(void)
+{
+ int tmpfile,
+ ops;
+
+ /*
+ * Test a simple write without fsync
+ */
+ printf("\nNon-Sync'ed %dkB writes:\n", XLOG_BLCKSZ_K);
+ printf(LABEL_FORMAT, "write");
+ fflush(stdout);
+
+ gettimeofday(&start_t, NULL);
+ for (ops = 0; ops < ops_per_test; ops++)
+ {
+ if ((tmpfile = open(filename, O_RDWR, 0)) == -1)
+ die("could not open output file");
+ if (write(tmpfile, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ die("write failed");
+ close(tmpfile);
+ }
+ gettimeofday(&stop_t, NULL);
+ print_elapse(start_t, stop_t);
+}
+
+#ifdef HAVE_FSYNC_WRITETHROUGH
+
+static int
+pg_fsync_writethrough(int fd)
+{
+#ifdef WIN32
+ return _commit(fd);
+#elif defined(F_FULLFSYNC)
+ return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif
+
+/*
+ * print out the writes per second for tests
+ */
+static void
+print_elapse(struct timeval start_t, struct timeval stop_t)
+{
+ double total_time = (stop_t.tv_sec - start_t.tv_sec) +
+ (stop_t.tv_usec - start_t.tv_usec) * 0.000001;
+ double per_second = ops_per_test / total_time;
+
+ printf(OPS_FORMAT "\n", per_second);
+}
+
+static void
+die(const char *str)
+{
+ fprintf(stderr, "%s: %s\n", str, strerror(errno));
+ exit(1);
+}
diff --git a/contrib/pg_trgm/.gitignore b/contrib/pg_trgm/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/pg_trgm/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/pg_trgm/Makefile b/contrib/pg_trgm/Makefile
index c9f139e9b6..64fd69f2cb 100644
--- a/contrib/pg_trgm/Makefile
+++ b/contrib/pg_trgm/Makefile
@@ -1,10 +1,11 @@
-# $PostgreSQL: pgsql/contrib/pg_trgm/Makefile,v 1.10 2009/04/28 17:07:50 momjian Exp $
+# contrib/pg_trgm/Makefile
MODULE_big = pg_trgm
OBJS = trgm_op.o trgm_gist.o trgm_gin.o
-DATA_built = pg_trgm.sql
-DATA = uninstall_pg_trgm.sql
+EXTENSION = pg_trgm
+DATA = pg_trgm--1.0.sql pg_trgm--unpackaged--1.0.sql
+
REGRESS = pg_trgm
ifdef USE_PGXS
diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expected/pg_trgm.out
index 9838534729..e7af7d4890 100644
--- a/contrib/pg_trgm/expected/pg_trgm.out
+++ b/contrib/pg_trgm/expected/pg_trgm.out
@@ -1,10 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of pg_tgrm.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION pg_trgm;
select show_trgm('');
show_trgm
-----------
@@ -1187,6 +1181,13 @@ select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu198
qwertyu0988 | 0.333333
(1 row)
+select t <-> 'q0987wertyu0988', t from test_trgm order by t <-> 'q0987wertyu0988' limit 2;
+ ?column? | t
+----------+-------------
+ 0.411765 | qwertyu0988
+ 0.5 | qwertyu0987
+(2 rows)
+
create index trgm_idx on test_trgm using gist (t gist_trgm_ops);
set enable_seqscan=off;
select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
@@ -2315,6 +2316,22 @@ select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu198
qwertyu0988 | 0.333333
(1 row)
+explain (costs off)
+select t <-> 'q0987wertyu0988', t from test_trgm order by t <-> 'q0987wertyu0988' limit 2;
+ QUERY PLAN
+---------------------------------------------------
+ Limit
+ -> Index Scan using trgm_idx on test_trgm
+ Order By: (t <-> 'q0987wertyu0988'::text)
+(3 rows)
+
+select t <-> 'q0987wertyu0988', t from test_trgm order by t <-> 'q0987wertyu0988' limit 2;
+ ?column? | t
+----------+-------------
+ 0.411765 | qwertyu0988
+ 0.5 | qwertyu0987
+(2 rows)
+
drop index trgm_idx;
create index trgm_idx on test_trgm using gin (t gin_trgm_ops);
set enable_seqscan=off;
@@ -3444,3 +3461,93 @@ select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu198
qwertyu0988 | 0.333333
(1 row)
+create table test2(t text);
+insert into test2 values ('abcdef');
+insert into test2 values ('quark');
+create index test2_idx_gin on test2 using gin (t gin_trgm_ops);
+set enable_seqscan=off;
+explain (costs off)
+ select * from test2 where t like '%BCD%';
+ QUERY PLAN
+------------------------------------------
+ Bitmap Heap Scan on test2
+ Recheck Cond: (t ~~ '%BCD%'::text)
+ -> Bitmap Index Scan on test2_idx_gin
+ Index Cond: (t ~~ '%BCD%'::text)
+(4 rows)
+
+explain (costs off)
+ select * from test2 where t ilike '%BCD%';
+ QUERY PLAN
+-------------------------------------------
+ Bitmap Heap Scan on test2
+ Recheck Cond: (t ~~* '%BCD%'::text)
+ -> Bitmap Index Scan on test2_idx_gin
+ Index Cond: (t ~~* '%BCD%'::text)
+(4 rows)
+
+select * from test2 where t like '%BCD%';
+ t
+---
+(0 rows)
+
+select * from test2 where t like '%bcd%';
+ t
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ilike '%BCD%';
+ t
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ilike 'qua%';
+ t
+-------
+ quark
+(1 row)
+
+drop index test2_idx_gin;
+create index test2_idx_gist on test2 using gist (t gist_trgm_ops);
+set enable_seqscan=off;
+explain (costs off)
+ select * from test2 where t like '%BCD%';
+ QUERY PLAN
+------------------------------------------
+ Index Scan using test2_idx_gist on test2
+ Index Cond: (t ~~ '%BCD%'::text)
+(2 rows)
+
+explain (costs off)
+ select * from test2 where t ilike '%BCD%';
+ QUERY PLAN
+------------------------------------------
+ Index Scan using test2_idx_gist on test2
+ Index Cond: (t ~~* '%BCD%'::text)
+(2 rows)
+
+select * from test2 where t like '%BCD%';
+ t
+---
+(0 rows)
+
+select * from test2 where t like '%bcd%';
+ t
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ilike '%BCD%';
+ t
+--------
+ abcdef
+(1 row)
+
+select * from test2 where t ilike 'qua%';
+ t
+-------
+ quark
+(1 row)
+
diff --git a/contrib/pg_trgm/pg_trgm--1.0.sql b/contrib/pg_trgm/pg_trgm--1.0.sql
new file mode 100644
index 0000000000..d9cdd23d85
--- /dev/null
+++ b/contrib/pg_trgm/pg_trgm--1.0.sql
@@ -0,0 +1,163 @@
+/* contrib/pg_trgm/pg_trgm--1.0.sql */
+
+CREATE FUNCTION set_limit(float4)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT VOLATILE;
+
+CREATE FUNCTION show_limit()
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+CREATE FUNCTION show_trgm(text)
+RETURNS _text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION similarity(text,text)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION similarity_op(text,text)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE; -- stable because depends on trgm_limit
+
+CREATE OPERATOR % (
+ LEFTARG = text,
+ RIGHTARG = text,
+ PROCEDURE = similarity_op,
+ COMMUTATOR = '%',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
+CREATE FUNCTION similarity_dist(text,text)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR <-> (
+ LEFTARG = text,
+ RIGHTARG = text,
+ PROCEDURE = similarity_dist,
+ COMMUTATOR = '<->'
+);
+
+-- gist key
+CREATE FUNCTION gtrgm_in(cstring)
+RETURNS gtrgm
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION gtrgm_out(gtrgm)
+RETURNS cstring
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+CREATE TYPE gtrgm (
+ INTERNALLENGTH = -1,
+ INPUT = gtrgm_in,
+ OUTPUT = gtrgm_out
+);
+
+-- support functions for gist
+CREATE FUNCTION gtrgm_consistent(internal,text,int,oid,internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gtrgm_distance(internal,text,int,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gtrgm_compress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gtrgm_decompress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gtrgm_penalty(internal,internal,internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gtrgm_picksplit(internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gtrgm_union(bytea, internal)
+RETURNS _int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gtrgm_same(gtrgm, gtrgm, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+-- create the operator class for gist
+CREATE OPERATOR CLASS gist_trgm_ops
+FOR TYPE text USING gist
+AS
+ OPERATOR 1 % (text, text),
+ FUNCTION 1 gtrgm_consistent (internal, text, int, oid, internal),
+ FUNCTION 2 gtrgm_union (bytea, internal),
+ FUNCTION 3 gtrgm_compress (internal),
+ FUNCTION 4 gtrgm_decompress (internal),
+ FUNCTION 5 gtrgm_penalty (internal, internal, internal),
+ FUNCTION 6 gtrgm_picksplit (internal, internal),
+ FUNCTION 7 gtrgm_same (gtrgm, gtrgm, internal),
+ STORAGE gtrgm;
+
+-- Add operators and support functions that are new in 9.1. We do it like
+-- this, leaving them "loose" in the operator family rather than bound into
+-- the gist_trgm_ops opclass, because that's the only state that can be
+-- reproduced during an upgrade from 9.0 (see pg_trgm--unpackaged--1.0.sql).
+
+ALTER OPERATOR FAMILY gist_trgm_ops USING gist ADD
+ OPERATOR 2 <-> (text, text) FOR ORDER BY pg_catalog.float_ops,
+ OPERATOR 3 pg_catalog.~~ (text, text),
+ OPERATOR 4 pg_catalog.~~* (text, text),
+ FUNCTION 8 (text, text) gtrgm_distance (internal, text, int, oid);
+
+-- support functions for gin
+CREATE FUNCTION gin_extract_value_trgm(text, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gin_extract_query_trgm(text, internal, int2, internal, internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gin_trgm_consistent(internal, int2, text, int4, internal, internal, internal, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+-- create the operator class for gin
+CREATE OPERATOR CLASS gin_trgm_ops
+FOR TYPE text USING gin
+AS
+ OPERATOR 1 % (text, text),
+ FUNCTION 1 btint4cmp (int4, int4),
+ FUNCTION 2 gin_extract_value_trgm (text, internal),
+ FUNCTION 3 gin_extract_query_trgm (text, internal, int2, internal, internal, internal, internal),
+ FUNCTION 4 gin_trgm_consistent (internal, int2, text, int4, internal, internal, internal, internal),
+ STORAGE int4;
+
+-- Add operators that are new in 9.1.
+
+ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
+ OPERATOR 3 pg_catalog.~~ (text, text),
+ OPERATOR 4 pg_catalog.~~* (text, text);
diff --git a/contrib/pg_trgm/pg_trgm--unpackaged--1.0.sql b/contrib/pg_trgm/pg_trgm--unpackaged--1.0.sql
new file mode 100644
index 0000000000..0e1c63f075
--- /dev/null
+++ b/contrib/pg_trgm/pg_trgm--unpackaged--1.0.sql
@@ -0,0 +1,95 @@
+/* contrib/pg_trgm/pg_trgm--unpackaged--1.0.sql */
+
+ALTER EXTENSION pg_trgm ADD function set_limit(real);
+ALTER EXTENSION pg_trgm ADD function show_limit();
+ALTER EXTENSION pg_trgm ADD function show_trgm(text);
+ALTER EXTENSION pg_trgm ADD function similarity(text,text);
+ALTER EXTENSION pg_trgm ADD function similarity_op(text,text);
+ALTER EXTENSION pg_trgm ADD operator %(text,text);
+ALTER EXTENSION pg_trgm ADD type gtrgm;
+ALTER EXTENSION pg_trgm ADD function gtrgm_in(cstring);
+ALTER EXTENSION pg_trgm ADD function gtrgm_out(gtrgm);
+ALTER EXTENSION pg_trgm ADD function gtrgm_consistent(internal,text,integer,oid,internal);
+ALTER EXTENSION pg_trgm ADD function gtrgm_compress(internal);
+ALTER EXTENSION pg_trgm ADD function gtrgm_decompress(internal);
+ALTER EXTENSION pg_trgm ADD function gtrgm_penalty(internal,internal,internal);
+ALTER EXTENSION pg_trgm ADD function gtrgm_picksplit(internal,internal);
+ALTER EXTENSION pg_trgm ADD function gtrgm_union(bytea,internal);
+ALTER EXTENSION pg_trgm ADD function gtrgm_same(gtrgm,gtrgm,internal);
+ALTER EXTENSION pg_trgm ADD operator family gist_trgm_ops using gist;
+ALTER EXTENSION pg_trgm ADD operator class gist_trgm_ops using gist;
+ALTER EXTENSION pg_trgm ADD operator family gin_trgm_ops using gin;
+ALTER EXTENSION pg_trgm ADD operator class gin_trgm_ops using gin;
+
+-- These functions had different names/signatures in 9.0. We can't just
+-- drop and recreate them because they are linked into the GIN opclass,
+-- so we need some ugly hacks.
+
+-- First, absorb them into the extension under their old names.
+
+ALTER EXTENSION pg_trgm ADD function gin_extract_trgm(text, internal);
+ALTER EXTENSION pg_trgm ADD function gin_extract_trgm(text, internal, int2, internal, internal);
+ALTER EXTENSION pg_trgm ADD function gin_trgm_consistent(internal,smallint,text,integer,internal,internal);
+
+-- Fix the names, and then do CREATE OR REPLACE to adjust the function
+-- bodies to be correct (ie, reference the correct C symbol).
+
+ALTER FUNCTION gin_extract_trgm(text, internal)
+ RENAME TO gin_extract_value_trgm;
+CREATE OR REPLACE FUNCTION gin_extract_value_trgm(text, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+ALTER FUNCTION gin_extract_trgm(text, internal, int2, internal, internal)
+ RENAME TO gin_extract_query_trgm;
+CREATE OR REPLACE FUNCTION gin_extract_query_trgm(text, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+-- gin_trgm_consistent didn't change name.
+
+-- Last, fix the parameter lists by means of direct UPDATE on the pg_proc
+-- entries. This is ugly as can be, but there's no other way to do it
+-- while preserving the identities (OIDs) of the functions.
+
+UPDATE pg_catalog.pg_proc
+SET pronargs = 7, proargtypes = '25 2281 21 2281 2281 2281 2281'
+WHERE oid = 'gin_extract_query_trgm(text,internal,int2,internal,internal)'::pg_catalog.regprocedure;
+
+UPDATE pg_catalog.pg_proc
+SET pronargs = 8, proargtypes = '2281 21 25 23 2281 2281 2281 2281'
+WHERE oid = 'gin_trgm_consistent(internal,smallint,text,integer,internal,internal)'::pg_catalog.regprocedure;
+
+
+-- These were not in 9.0:
+
+CREATE FUNCTION similarity_dist(text,text)
+RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR <-> (
+ LEFTARG = text,
+ RIGHTARG = text,
+ PROCEDURE = similarity_dist,
+ COMMUTATOR = '<->'
+);
+
+CREATE FUNCTION gtrgm_distance(internal,text,int,oid)
+RETURNS float8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+-- Add new stuff to the operator classes. See comment in pg_trgm--1.0.sql.
+
+ALTER OPERATOR FAMILY gist_trgm_ops USING gist ADD
+ OPERATOR 2 <-> (text, text) FOR ORDER BY pg_catalog.float_ops,
+ OPERATOR 3 pg_catalog.~~ (text, text),
+ OPERATOR 4 pg_catalog.~~* (text, text),
+ FUNCTION 8 (text, text) gtrgm_distance (internal, text, int, oid);
+
+ALTER OPERATOR FAMILY gin_trgm_ops USING gin ADD
+ OPERATOR 3 pg_catalog.~~ (text, text),
+ OPERATOR 4 pg_catalog.~~* (text, text);
diff --git a/contrib/pg_trgm/pg_trgm.control b/contrib/pg_trgm/pg_trgm.control
new file mode 100644
index 0000000000..70404d881d
--- /dev/null
+++ b/contrib/pg_trgm/pg_trgm.control
@@ -0,0 +1,5 @@
+# pg_trgm extension
+comment = 'text similarity measurement and index searching based on trigrams'
+default_version = '1.0'
+module_pathname = '$libdir/pg_trgm'
+relocatable = true
diff --git a/contrib/pg_trgm/pg_trgm.sql.in b/contrib/pg_trgm/pg_trgm.sql.in
deleted file mode 100644
index 5396b52b1b..0000000000
--- a/contrib/pg_trgm/pg_trgm.sql.in
+++ /dev/null
@@ -1,132 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pg_trgm/pg_trgm.sql.in,v 1.10 2009/06/11 18:30:03 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION set_limit(float4)
-RETURNS float4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION show_limit()
-RETURNS float4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT STABLE;
-
-CREATE OR REPLACE FUNCTION show_trgm(text)
-RETURNS _text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION similarity(text,text)
-RETURNS float4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION similarity_op(text,text)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT STABLE;
-
-CREATE OPERATOR % (
- LEFTARG = text,
- RIGHTARG = text,
- PROCEDURE = similarity_op,
- COMMUTATOR = '%',
- RESTRICT = contsel,
- JOIN = contjoinsel
-);
-
--- gist key
-CREATE OR REPLACE FUNCTION gtrgm_in(cstring)
-RETURNS gtrgm
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION gtrgm_out(gtrgm)
-RETURNS cstring
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-
-CREATE TYPE gtrgm (
- INTERNALLENGTH = -1,
- INPUT = gtrgm_in,
- OUTPUT = gtrgm_out
-);
-
--- support functions for gist
-CREATE OR REPLACE FUNCTION gtrgm_consistent(internal,text,int,oid,internal)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gtrgm_compress(internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gtrgm_decompress(internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gtrgm_penalty(internal,internal,internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gtrgm_picksplit(internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gtrgm_union(bytea, internal)
-RETURNS _int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gtrgm_same(gtrgm, gtrgm, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
--- create the operator class for gist
-CREATE OPERATOR CLASS gist_trgm_ops
-FOR TYPE text USING gist
-AS
- OPERATOR 1 % (text, text),
- FUNCTION 1 gtrgm_consistent (internal, text, int, oid, internal),
- FUNCTION 2 gtrgm_union (bytea, internal),
- FUNCTION 3 gtrgm_compress (internal),
- FUNCTION 4 gtrgm_decompress (internal),
- FUNCTION 5 gtrgm_penalty (internal, internal, internal),
- FUNCTION 6 gtrgm_picksplit (internal, internal),
- FUNCTION 7 gtrgm_same (gtrgm, gtrgm, internal),
- STORAGE gtrgm;
-
--- support functions for gin
-CREATE OR REPLACE FUNCTION gin_extract_trgm(text, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gin_extract_trgm(text, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION gin_trgm_consistent(internal, int2, text, int4, internal, internal)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C IMMUTABLE STRICT;
-
--- create the operator class for gin
-CREATE OPERATOR CLASS gin_trgm_ops
-FOR TYPE text USING gin
-AS
- OPERATOR 1 % (text, text),
- FUNCTION 1 btint4cmp (int4, int4),
- FUNCTION 2 gin_extract_trgm (text, internal),
- FUNCTION 3 gin_extract_trgm (text, internal, int2, internal, internal),
- FUNCTION 4 gin_trgm_consistent (internal, int2, text, int4, internal, internal),
- STORAGE int4;
diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm.sql
index 13045827ac..ea902f602f 100644
--- a/contrib/pg_trgm/sql/pg_trgm.sql
+++ b/contrib/pg_trgm/sql/pg_trgm.sql
@@ -1,12 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of pg_tgrm.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i pg_trgm.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION pg_trgm;
select show_trgm('');
select show_trgm('(*&^$@%@');
@@ -26,6 +18,7 @@ CREATE TABLE test_trgm(t text);
select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t;
select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu1988' order by sml desc, t;
+select t <-> 'q0987wertyu0988', t from test_trgm order by t <-> 'q0987wertyu0988' limit 2;
create index trgm_idx on test_trgm using gist (t gist_trgm_ops);
set enable_seqscan=off;
@@ -33,6 +26,9 @@ set enable_seqscan=off;
select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t;
select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu1988' order by sml desc, t;
+explain (costs off)
+select t <-> 'q0987wertyu0988', t from test_trgm order by t <-> 'q0987wertyu0988' limit 2;
+select t <-> 'q0987wertyu0988', t from test_trgm order by t <-> 'q0987wertyu0988' limit 2;
drop index trgm_idx;
create index trgm_idx on test_trgm using gin (t gin_trgm_ops);
@@ -42,3 +38,27 @@ select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu098
select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t;
select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu1988' order by sml desc, t;
+create table test2(t text);
+insert into test2 values ('abcdef');
+insert into test2 values ('quark');
+create index test2_idx_gin on test2 using gin (t gin_trgm_ops);
+set enable_seqscan=off;
+explain (costs off)
+ select * from test2 where t like '%BCD%';
+explain (costs off)
+ select * from test2 where t ilike '%BCD%';
+select * from test2 where t like '%BCD%';
+select * from test2 where t like '%bcd%';
+select * from test2 where t ilike '%BCD%';
+select * from test2 where t ilike 'qua%';
+drop index test2_idx_gin;
+create index test2_idx_gist on test2 using gist (t gist_trgm_ops);
+set enable_seqscan=off;
+explain (costs off)
+ select * from test2 where t like '%BCD%';
+explain (costs off)
+ select * from test2 where t ilike '%BCD%';
+select * from test2 where t like '%BCD%';
+select * from test2 where t like '%bcd%';
+select * from test2 where t ilike '%BCD%';
+select * from test2 where t ilike 'qua%';
diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h
index 4a89760d71..61de5d89d1 100644
--- a/contrib/pg_trgm/trgm.h
+++ b/contrib/pg_trgm/trgm.h
@@ -1,23 +1,34 @@
/*
- * $PostgreSQL: pgsql/contrib/pg_trgm/trgm.h,v 1.11 2009/06/11 14:48:51 momjian Exp $
+ * contrib/pg_trgm/trgm.h
*/
#ifndef __TRGM_H__
#define __TRGM_H__
-#include "postgres.h"
-
#include "access/gist.h"
#include "access/itup.h"
-#include "utils/builtins.h"
#include "storage/bufpage.h"
+#include "utils/builtins.h"
/* options */
#define LPADDING 2
#define RPADDING 1
#define KEEPONLYALNUM
+/*
+ * Caution: IGNORECASE macro means that trigrams are case-insensitive.
+ * If this macro is disabled, the ~~* operator must be removed from the
+ * operator classes, because we can't handle case-insensitive wildcard search
+ * with case-sensitive trigrams. Failure to do this will result in "cannot
+ * handle ~~* with case-sensitive trigrams" errors.
+ */
#define IGNORECASE
#define DIVUNION
+/* operator strategy numbers */
+#define SimilarityStrategyNumber 1
+#define DistanceStrategyNumber 2
+#define LikeStrategyNumber 3
+#define ILikeStrategyNumber 4
+
typedef char trgm[3];
@@ -38,7 +49,11 @@ uint32 trgm2int(trgm *ptr);
#else
#define ISPRINTABLECHAR(a) ( isascii( *(unsigned char*)(a) ) && isprint( *(unsigned char*)(a) ) )
#endif
-#define ISPRINTABLETRGM(t) ( ISPRINTABLECHAR( ((char*)t) ) && ISPRINTABLECHAR( ((char*)t)+1 ) && ISPRINTABLECHAR( ((char*)t)+2 ) )
+#define ISPRINTABLETRGM(t) ( ISPRINTABLECHAR( ((char*)(t)) ) && ISPRINTABLECHAR( ((char*)(t))+1 ) && ISPRINTABLECHAR( ((char*)(t))+2 ) )
+
+#define ISESCAPECHAR(x) (*(x) == '\\') /* Wildcard escape character */
+#define ISWILDCARDCHAR(x) (*(x) == '_' || *(x) == '%') /* Wildcard
+ * meta-character */
typedef struct
{
@@ -63,7 +78,7 @@ typedef char *BITVECP;
for(i=0;i<SIGLEN;i++)
#define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
-#define GETBITBYTE(x,i) ( ((char)(x)) >> i & 0x01 )
+#define GETBITBYTE(x,i) ( (((char)(x)) >> (i)) & 0x01 )
#define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITBYTE ) )
#define SETBIT(x,i) GETBYTE(x,i) |= ( 0x01 << ( (i) % BITBYTE ) )
#define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITBYTE )) & 0x01 )
@@ -87,6 +102,8 @@ typedef char *BITVECP;
extern float4 trgm_limit;
TRGM *generate_trgm(char *str, int slen);
+TRGM *generate_wildcard_trgm(const char *str, int slen);
float4 cnt_sml(TRGM *trg1, TRGM *trg2);
+bool trgm_contained_by(TRGM *trg1, TRGM *trg2);
-#endif
+#endif /* __TRGM_H__ */
diff --git a/contrib/pg_trgm/trgm_gin.c b/contrib/pg_trgm/trgm_gin.c
index a150f8843e..43ac0b0c65 100644
--- a/contrib/pg_trgm/trgm_gin.c
+++ b/contrib/pg_trgm/trgm_gin.c
@@ -1,29 +1,55 @@
/*
- * $PostgreSQL: pgsql/contrib/pg_trgm/trgm_gin.c,v 1.8 2009/06/11 14:48:51 momjian Exp $
+ * contrib/pg_trgm/trgm_gin.c
*/
+#include "postgres.h"
+
#include "trgm.h"
#include "access/gin.h"
#include "access/itup.h"
+#include "access/skey.h"
#include "access/tuptoaster.h"
#include "storage/bufpage.h"
#include "utils/array.h"
#include "utils/builtins.h"
+
PG_FUNCTION_INFO_V1(gin_extract_trgm);
Datum gin_extract_trgm(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(gin_extract_value_trgm);
+Datum gin_extract_value_trgm(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(gin_extract_query_trgm);
+Datum gin_extract_query_trgm(PG_FUNCTION_ARGS);
+
PG_FUNCTION_INFO_V1(gin_trgm_consistent);
Datum gin_trgm_consistent(PG_FUNCTION_ARGS);
+/*
+ * This function can only be called if a pre-9.1 version of the GIN operator
+ * class definition is present in the catalogs (probably as a consequence
+ * of upgrade-in-place). Cope.
+ */
Datum
gin_extract_trgm(PG_FUNCTION_ARGS)
{
+ if (PG_NARGS() == 3)
+ return gin_extract_value_trgm(fcinfo);
+ if (PG_NARGS() == 7)
+ return gin_extract_query_trgm(fcinfo);
+ elog(ERROR, "unexpected number of arguments to gin_extract_trgm");
+ PG_RETURN_NULL();
+}
+
+Datum
+gin_extract_value_trgm(PG_FUNCTION_ARGS)
+{
text *val = (text *) PG_GETARG_TEXT_P(0);
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
Datum *entries = NULL;
TRGM *trg;
- int4 trglen;
+ int32 trglen;
*nentries = 0;
@@ -33,33 +59,87 @@ gin_extract_trgm(PG_FUNCTION_ARGS)
if (trglen > 0)
{
trgm *ptr;
- int4 i = 0,
- item;
+ int32 i;
- *nentries = (int32) trglen;
+ *nentries = trglen;
entries = (Datum *) palloc(sizeof(Datum) * trglen);
ptr = GETARR(trg);
- while (ptr - GETARR(trg) < ARRNELEM(trg))
+ for (i = 0; i < trglen; i++)
{
- item = trgm2int(ptr);
- entries[i++] = Int32GetDatum(item);
+ int32 item = trgm2int(ptr);
+ entries[i] = Int32GetDatum(item);
ptr++;
}
- if (PG_NARGS() > 4)
- {
+ }
+
+ PG_RETURN_POINTER(entries);
+}
+
+Datum
+gin_extract_query_trgm(PG_FUNCTION_ARGS)
+{
+ text *val = (text *) PG_GETARG_TEXT_P(0);
+ int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
+ StrategyNumber strategy = PG_GETARG_UINT16(2);
+
+ /* bool **pmatch = (bool **) PG_GETARG_POINTER(3); */
+ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+ /* bool **nullFlags = (bool **) PG_GETARG_POINTER(5); */
+ int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
+ Datum *entries = NULL;
+ TRGM *trg;
+ int32 trglen;
+ trgm *ptr;
+ int32 i;
+
+ switch (strategy)
+ {
+ case SimilarityStrategyNumber:
+ trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
+ break;
+ case ILikeStrategyNumber:
+#ifndef IGNORECASE
+ elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
+#endif
+ /* FALL THRU */
+ case LikeStrategyNumber:
+
/*
- * Function called from query extracting
+ * For wildcard search we extract all the trigrams that every
+ * potentially-matching string must include.
*/
- Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
+ trg = generate_wildcard_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
+ break;
+ default:
+ elog(ERROR, "unrecognized strategy number: %d", strategy);
+ trg = NULL; /* keep compiler quiet */
+ break;
+ }
- *extra_data = (Pointer *) palloc0(sizeof(Pointer) * (*nentries));
+ trglen = ARRNELEM(trg);
+ *nentries = trglen;
- *(int32 *) (*extra_data) = trglen;
+ if (trglen > 0)
+ {
+ entries = (Datum *) palloc(sizeof(Datum) * trglen);
+ ptr = GETARR(trg);
+ for (i = 0; i < trglen; i++)
+ {
+ int32 item = trgm2int(ptr);
+
+ entries[i] = Int32GetDatum(item);
+ ptr++;
}
}
+ /*
+ * If no trigram was extracted then we have to scan all the index.
+ */
+ if (trglen == 0)
+ *searchMode = GIN_SEARCH_MODE_ALL;
+
PG_RETURN_POINTER(entries);
}
@@ -67,31 +147,58 @@ Datum
gin_trgm_consistent(PG_FUNCTION_ARGS)
{
bool *check = (bool *) PG_GETARG_POINTER(0);
+ StrategyNumber strategy = PG_GETARG_UINT16(1);
- /* StrategyNumber strategy = PG_GETARG_UINT16(1); */
/* text *query = PG_GETARG_TEXT_P(2); */
- /* int32 nkeys = PG_GETARG_INT32(3); */
- Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
+ int32 nkeys = PG_GETARG_INT32(3);
+
+ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
bool *recheck = (bool *) PG_GETARG_POINTER(5);
- bool res = FALSE;
- int4 i,
- trglen,
- ntrue = 0;
+ bool res;
+ int32 i,
+ ntrue;
/* All cases served by this function are inexact */
*recheck = true;
- trglen = *(int32 *) extra_data;
-
- for (i = 0; i < trglen; i++)
- if (check[i])
- ntrue++;
-
+ switch (strategy)
+ {
+ case SimilarityStrategyNumber:
+ /* Count the matches */
+ ntrue = 0;
+ for (i = 0; i < nkeys; i++)
+ {
+ if (check[i])
+ ntrue++;
+ }
#ifdef DIVUNION
- res = (trglen == ntrue) ? true : ((((((float4) ntrue) / ((float4) (trglen - ntrue)))) >= trgm_limit) ? true : false);
+ res = (nkeys == ntrue) ? true : ((((((float4) ntrue) / ((float4) (nkeys - ntrue)))) >= trgm_limit) ? true : false);
#else
- res = (trglen == 0) ? false : ((((((float4) ntrue) / ((float4) trglen))) >= trgm_limit) ? true : false);
+ res = (nkeys == 0) ? false : ((((((float4) ntrue) / ((float4) nkeys))) >= trgm_limit) ? true : false);
#endif
+ break;
+ case ILikeStrategyNumber:
+#ifndef IGNORECASE
+ elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
+#endif
+ /* FALL THRU */
+ case LikeStrategyNumber:
+ /* Check if all extracted trigrams are presented. */
+ res = true;
+ for (i = 0; i < nkeys; i++)
+ {
+ if (!check[i])
+ {
+ res = false;
+ break;
+ }
+ }
+ break;
+ default:
+ elog(ERROR, "unrecognized strategy number: %d", strategy);
+ res = false; /* keep compiler quiet */
+ break;
+ }
PG_RETURN_BOOL(res);
}
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
index 7014394bb2..b328a09f41 100644
--- a/contrib/pg_trgm/trgm_gist.c
+++ b/contrib/pg_trgm/trgm_gist.c
@@ -1,15 +1,19 @@
/*
- * $PostgreSQL: pgsql/contrib/pg_trgm/trgm_gist.c,v 1.16 2009/06/11 14:48:51 momjian Exp $
+ * contrib/pg_trgm/trgm_gist.c
*/
+#include "postgres.h"
+
#include "trgm.h"
#include "access/gist.h"
#include "access/itup.h"
+#include "access/skey.h"
#include "access/tuptoaster.h"
#include "storage/bufpage.h"
#include "utils/array.h"
#include "utils/builtins.h"
+
PG_FUNCTION_INFO_V1(gtrgm_in);
Datum gtrgm_in(PG_FUNCTION_ARGS);
@@ -25,6 +29,9 @@ Datum gtrgm_decompress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(gtrgm_consistent);
Datum gtrgm_consistent(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(gtrgm_distance);
+Datum gtrgm_distance(PG_FUNCTION_ARGS);
+
PG_FUNCTION_INFO_V1(gtrgm_union);
Datum gtrgm_union(PG_FUNCTION_ARGS);
@@ -159,22 +166,175 @@ gtrgm_decompress(PG_FUNCTION_ARGS)
}
}
+static int4
+cnt_sml_sign_common(TRGM *qtrg, BITVECP sign)
+{
+ int4 count = 0;
+ int4 k,
+ len = ARRNELEM(qtrg);
+ trgm *ptr = GETARR(qtrg);
+ int4 tmp = 0;
+
+ for (k = 0; k < len; k++)
+ {
+ CPTRGM(((char *) &tmp), ptr + k);
+ count += GETBIT(sign, HASHVAL(tmp));
+ }
+
+ return count;
+}
+
Datum
gtrgm_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
text *query = PG_GETARG_TEXT_P(1);
+ StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
- /* StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); */
/* Oid subtype = PG_GETARG_OID(3); */
bool *recheck = (bool *) PG_GETARG_POINTER(4);
TRGM *key = (TRGM *) DatumGetPointer(entry->key);
TRGM *qtrg;
- bool res = false;
- char *cache = (char *) fcinfo->flinfo->fn_extra;
+ bool res;
+ char *cache = (char *) fcinfo->flinfo->fn_extra,
+ *cacheContents = cache + MAXALIGN(sizeof(StrategyNumber));
+
+ /*
+ * Store both the strategy number and extracted trigrams in cache, because
+ * trigram extraction is relatively CPU-expensive. We must include
+ * strategy number because trigram extraction depends on strategy.
+ */
+ if (cache == NULL || strategy != *((StrategyNumber *) cache) ||
+ VARSIZE(cacheContents) != VARSIZE(query) ||
+ memcmp(cacheContents, query, VARSIZE(query)) != 0)
+ {
+ switch (strategy)
+ {
+ case SimilarityStrategyNumber:
+ qtrg = generate_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
+ break;
+ case ILikeStrategyNumber:
+#ifndef IGNORECASE
+ elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
+#endif
+ /* FALL THRU */
+ case LikeStrategyNumber:
+ qtrg = generate_wildcard_trgm(VARDATA(query), VARSIZE(query) - VARHDRSZ);
+ break;
+ default:
+ elog(ERROR, "unrecognized strategy number: %d", strategy);
+ qtrg = NULL; /* keep compiler quiet */
+ break;
+ }
+
+ if (cache)
+ pfree(cache);
+
+ fcinfo->flinfo->fn_extra =
+ MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
+ MAXALIGN(sizeof(StrategyNumber)) +
+ MAXALIGN(VARSIZE(query)) +
+ VARSIZE(qtrg));
+ cache = (char *) fcinfo->flinfo->fn_extra;
+ cacheContents = cache + MAXALIGN(sizeof(StrategyNumber));
+
+ *((StrategyNumber *) cache) = strategy;
+ memcpy(cacheContents, query, VARSIZE(query));
+ memcpy(cacheContents + MAXALIGN(VARSIZE(query)), qtrg, VARSIZE(qtrg));
+ }
+
+ qtrg = (TRGM *) (cacheContents + MAXALIGN(VARSIZE(query)));
+
+ switch (strategy)
+ {
+ case SimilarityStrategyNumber:
+ /* Similarity search is exact */
+ *recheck = false;
+
+ if (GIST_LEAF(entry))
+ { /* all leafs contains orig trgm */
+ float4 tmpsml = cnt_sml(key, qtrg);
+
+ /* strange bug at freebsd 5.2.1 and gcc 3.3.3 */
+ res = (*(int *) &tmpsml == *(int *) &trgm_limit || tmpsml > trgm_limit) ? true : false;
+ }
+ else if (ISALLTRUE(key))
+ { /* non-leaf contains signature */
+ res = true;
+ }
+ else
+ { /* non-leaf contains signature */
+ int4 count = cnt_sml_sign_common(qtrg, GETSIGN(key));
+ int4 len = ARRNELEM(qtrg);
+
+ if (len == 0)
+ res = false;
+ else
+ res = (((((float8) count) / ((float8) len))) >= trgm_limit) ? true : false;
+ }
+ break;
+ case ILikeStrategyNumber:
+#ifndef IGNORECASE
+ elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
+#endif
+ /* FALL THRU */
+ case LikeStrategyNumber:
+ /* Wildcard search is inexact */
+ *recheck = true;
+
+ /*
+ * Check if all the extracted trigrams can be present in child
+ * nodes.
+ */
+ if (GIST_LEAF(entry))
+ { /* all leafs contains orig trgm */
+ res = trgm_contained_by(qtrg, key);
+ }
+ else if (ISALLTRUE(key))
+ { /* non-leaf contains signature */
+ res = true;
+ }
+ else
+ { /* non-leaf contains signature */
+ int32 k,
+ tmp = 0,
+ len = ARRNELEM(qtrg);
+ trgm *ptr = GETARR(qtrg);
+ BITVECP sign = GETSIGN(key);
+
+ res = true;
+ for (k = 0; k < len; k++)
+ {
+ CPTRGM(((char *) &tmp), ptr + k);
+ if (!GETBIT(sign, HASHVAL(tmp)))
+ {
+ res = false;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ elog(ERROR, "unrecognized strategy number: %d", strategy);
+ res = false; /* keep compiler quiet */
+ break;
+ }
- /* All cases served by this function are exact */
- *recheck = false;
+ PG_RETURN_BOOL(res);
+}
+
+Datum
+gtrgm_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ text *query = PG_GETARG_TEXT_P(1);
+ StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ TRGM *key = (TRGM *) DatumGetPointer(entry->key);
+ TRGM *qtrg;
+ float8 res;
+ char *cache = (char *) fcinfo->flinfo->fn_extra;
if (cache == NULL || VARSIZE(cache) != VARSIZE(query) || memcmp(cache, query, VARSIZE(query)) != 0)
{
@@ -193,39 +353,32 @@ gtrgm_consistent(PG_FUNCTION_ARGS)
qtrg = (TRGM *) (cache + MAXALIGN(VARSIZE(query)));
- if (GIST_LEAF(entry))
- { /* all leafs contains orig trgm */
- float4 tmpsml = cnt_sml(key, qtrg);
-
- /* strange bug at freebsd 5.2.1 and gcc 3.3.3 */
- res = (*(int *) &tmpsml == *(int *) &trgm_limit || tmpsml > trgm_limit) ? true : false;
- }
- else if (ISALLTRUE(key))
- { /* non-leaf contains signature */
- res = true;
- }
- else
- { /* non-leaf contains signature */
- int4 count = 0;
- int4 k,
- len = ARRNELEM(qtrg);
- trgm *ptr = GETARR(qtrg);
- BITVECP sign = GETSIGN(key);
- int4 tmp = 0;
+ switch (strategy)
+ {
+ case DistanceStrategyNumber:
+ if (GIST_LEAF(entry))
+ { /* all leafs contains orig trgm */
+ res = 1.0 - cnt_sml(key, qtrg);
+ }
+ else if (ISALLTRUE(key))
+ { /* all leafs contains orig trgm */
+ res = 0.0;
+ }
+ else
+ { /* non-leaf contains signature */
+ int4 count = cnt_sml_sign_common(qtrg, GETSIGN(key));
+ int4 len = ARRNELEM(qtrg);
- for (k = 0; k < len; k++)
- {
- CPTRGM(((char *) &tmp), ptr + k);
- count += GETBIT(sign, HASHVAL(tmp));
- }
-#ifdef DIVUNION
- res = (len == count) ? true : ((((((float4) count) / ((float4) (len - count)))) >= trgm_limit) ? true : false);
-#else
- res = (len == 0) ? false : ((((((float4) count) / ((float4) len))) >= trgm_limit) ? true : false);
-#endif
+ res = (len == 0) ? -1.0 : 1.0 - ((float8) count) / ((float8) len);
+ }
+ break;
+ default:
+ elog(ERROR, "unrecognized strategy number: %d", strategy);
+ res = 0; /* keep compiler quiet */
+ break;
}
- PG_RETURN_BOOL(res);
+ PG_RETURN_FLOAT8(res);
}
static int4
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 19b6747d68..dfb2df5048 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -1,11 +1,16 @@
/*
- * $PostgreSQL: pgsql/contrib/pg_trgm/trgm_op.c,v 1.12 2009/06/11 14:48:51 momjian Exp $
+ * contrib/pg_trgm/trgm_op.c
*/
-#include "trgm.h"
+#include "postgres.h"
+
#include <ctype.h>
-#include "utils/array.h"
+
+#include "trgm.h"
+
#include "catalog/pg_type.h"
#include "tsearch/ts_locale.h"
+#include "utils/array.h"
+
PG_MODULE_MAGIC;
@@ -13,6 +18,23 @@ float4 trgm_limit = 0.3f;
PG_FUNCTION_INFO_V1(set_limit);
Datum set_limit(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(show_limit);
+Datum show_limit(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(show_trgm);
+Datum show_trgm(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(similarity);
+Datum similarity(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(similarity_dist);
+Datum similarity_dist(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(similarity_op);
+Datum similarity_op(PG_FUNCTION_ARGS);
+
+
Datum
set_limit(PG_FUNCTION_ARGS)
{
@@ -24,8 +46,6 @@ set_limit(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT4(trgm_limit);
}
-PG_FUNCTION_INFO_V1(show_limit);
-Datum show_limit(PG_FUNCTION_ARGS);
Datum
show_limit(PG_FUNCTION_ARGS)
{
@@ -115,7 +135,7 @@ cnt_trigram(trgm *tptr, char *str, int bytelen)
#endif
/*
- * Adds trigramm from words (already padded).
+ * Adds trigrams from words (already padded).
*/
static trgm *
make_trigrams(trgm *tptr, char *str, int bytelen, int charlen)
@@ -231,6 +251,225 @@ generate_trgm(char *str, int slen)
return trg;
}
+/*
+ * Extract the next non-wildcard part of a search string, ie, a word bounded
+ * by '_' or '%' meta-characters, non-word characters or string end.
+ *
+ * str: source string, of length lenstr bytes (need not be null-terminated)
+ * buf: where to return the substring (must be long enough)
+ * *bytelen: receives byte length of the found substring
+ * *charlen: receives character length of the found substring
+ *
+ * Returns pointer to end+1 of the found substring in the source string.
+ * Returns NULL if no word found (in which case buf, bytelen, charlen not set)
+ *
+ * If the found word is bounded by non-word characters or string boundaries
+ * then this function will include corresponding padding spaces into buf.
+ */
+static const char *
+get_wildcard_part(const char *str, int lenstr,
+ char *buf, int *bytelen, int *charlen)
+{
+ const char *beginword = str;
+ const char *endword;
+ char *s = buf;
+ bool in_wildcard_meta = false;
+ bool in_escape = false;
+ int clen;
+
+ /*
+ * Find the first word character remembering whether last character was
+ * wildcard meta-character.
+ */
+ while (beginword - str < lenstr)
+ {
+ if (in_escape)
+ {
+ in_escape = false;
+ in_wildcard_meta = false;
+ if (iswordchr(beginword))
+ break;
+ }
+ else
+ {
+ if (ISESCAPECHAR(beginword))
+ in_escape = true;
+ else if (ISWILDCARDCHAR(beginword))
+ in_wildcard_meta = true;
+ else if (iswordchr(beginword))
+ break;
+ else
+ in_wildcard_meta = false;
+ }
+ beginword += pg_mblen(beginword);
+ }
+
+ /*
+ * Handle string end.
+ */
+ if (beginword - str >= lenstr)
+ return NULL;
+
+ /*
+ * Add left padding spaces if last character wasn't wildcard
+ * meta-character.
+ */
+ *charlen = 0;
+ if (!in_wildcard_meta)
+ {
+ if (LPADDING > 0)
+ {
+ *s++ = ' ';
+ (*charlen)++;
+ if (LPADDING > 1)
+ {
+ *s++ = ' ';
+ (*charlen)++;
+ }
+ }
+ }
+
+ /*
+ * Copy data into buf until wildcard meta-character, non-word character or
+ * string boundary. Strip escapes during copy.
+ */
+ endword = beginword;
+ in_wildcard_meta = false;
+ in_escape = false;
+ while (endword - str < lenstr)
+ {
+ clen = pg_mblen(endword);
+ if (in_escape)
+ {
+ in_escape = false;
+ in_wildcard_meta = false;
+ if (iswordchr(endword))
+ {
+ memcpy(s, endword, clen);
+ (*charlen)++;
+ s += clen;
+ }
+ else
+ break;
+ }
+ else
+ {
+ if (ISESCAPECHAR(endword))
+ in_escape = true;
+ else if (ISWILDCARDCHAR(endword))
+ {
+ in_wildcard_meta = true;
+ break;
+ }
+ else if (iswordchr(endword))
+ {
+ memcpy(s, endword, clen);
+ (*charlen)++;
+ s += clen;
+ }
+ else
+ {
+ in_wildcard_meta = false;
+ break;
+ }
+ }
+ endword += clen;
+ }
+
+ /*
+ * Add right padding spaces if last character wasn't wildcard
+ * meta-character.
+ */
+ if (!in_wildcard_meta)
+ {
+ if (RPADDING > 0)
+ {
+ *s++ = ' ';
+ (*charlen)++;
+ if (RPADDING > 1)
+ {
+ *s++ = ' ';
+ (*charlen)++;
+ }
+ }
+ }
+
+ *bytelen = s - buf;
+ return endword;
+}
+
+/*
+ * Generates trigrams for wildcard search string.
+ *
+ * Returns array of trigrams that must occur in any string that matches the
+ * wildcard string. For example, given pattern "a%bcd%" the trigrams
+ * " a", "bcd" would be extracted.
+ */
+TRGM *
+generate_wildcard_trgm(const char *str, int slen)
+{
+ TRGM *trg;
+ char *buf,
+ *buf2;
+ trgm *tptr;
+ int len,
+ charlen,
+ bytelen;
+ const char *eword;
+
+ trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3);
+ trg->flag = ARRKEY;
+ SET_VARSIZE(trg, TRGMHDRSIZE);
+
+ if (slen + LPADDING + RPADDING < 3 || slen == 0)
+ return trg;
+
+ tptr = GETARR(trg);
+
+ buf = palloc(sizeof(char) * (slen + 4));
+
+ /*
+ * Extract trigrams from each substring extracted by get_wildcard_part.
+ */
+ eword = str;
+ while ((eword = get_wildcard_part(eword, slen - (eword - str),
+ buf, &bytelen, &charlen)) != NULL)
+ {
+#ifdef IGNORECASE
+ buf2 = lowerstr_with_len(buf, bytelen);
+ bytelen = strlen(buf2);
+#else
+ buf2 = buf;
+#endif
+
+ /*
+ * count trigrams
+ */
+ tptr = make_trigrams(tptr, buf2, bytelen, charlen);
+#ifdef IGNORECASE
+ pfree(buf2);
+#endif
+ }
+
+ pfree(buf);
+
+ if ((len = tptr - GETARR(trg)) == 0)
+ return trg;
+
+ /*
+ * Make trigrams unique.
+ */
+ if (len > 0)
+ {
+ qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
+ len = unique_array(GETARR(trg), len);
+ }
+
+ SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len));
+
+ return trg;
+}
+
uint32
trgm2int(trgm *ptr)
{
@@ -245,8 +484,6 @@ trgm2int(trgm *ptr)
return val;
}
-PG_FUNCTION_INFO_V1(show_trgm);
-Datum show_trgm(PG_FUNCTION_ARGS);
Datum
show_trgm(PG_FUNCTION_ARGS)
{
@@ -335,8 +572,44 @@ cnt_sml(TRGM *trg1, TRGM *trg2)
}
-PG_FUNCTION_INFO_V1(similarity);
-Datum similarity(PG_FUNCTION_ARGS);
+/*
+ * Returns whether trg2 contains all trigrams in trg1.
+ * This relies on the trigram arrays being sorted.
+ */
+bool
+trgm_contained_by(TRGM *trg1, TRGM *trg2)
+{
+ trgm *ptr1,
+ *ptr2;
+ int len1,
+ len2;
+
+ ptr1 = GETARR(trg1);
+ ptr2 = GETARR(trg2);
+
+ len1 = ARRNELEM(trg1);
+ len2 = ARRNELEM(trg2);
+
+ while (ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2)
+ {
+ int res = CMPTRGM(ptr1, ptr2);
+
+ if (res < 0)
+ return false;
+ else if (res > 0)
+ ptr2++;
+ else
+ {
+ ptr1++;
+ ptr2++;
+ }
+ }
+ if (ptr1 - GETARR(trg1) < len1)
+ return false;
+ else
+ return true;
+}
+
Datum
similarity(PG_FUNCTION_ARGS)
{
@@ -359,16 +632,22 @@ similarity(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT4(res);
}
-PG_FUNCTION_INFO_V1(similarity_op);
-Datum similarity_op(PG_FUNCTION_ARGS);
+Datum
+similarity_dist(PG_FUNCTION_ARGS)
+{
+ float4 res = DatumGetFloat4(DirectFunctionCall2(similarity,
+ PG_GETARG_DATUM(0),
+ PG_GETARG_DATUM(1)));
+
+ PG_RETURN_FLOAT4(1.0 - res);
+}
+
Datum
similarity_op(PG_FUNCTION_ARGS)
{
- float4 res = DatumGetFloat4(DirectFunctionCall2(
- similarity,
+ float4 res = DatumGetFloat4(DirectFunctionCall2(similarity,
PG_GETARG_DATUM(0),
- PG_GETARG_DATUM(1)
- ));
+ PG_GETARG_DATUM(1)));
PG_RETURN_BOOL(res >= trgm_limit);
}
diff --git a/contrib/pg_trgm/uninstall_pg_trgm.sql b/contrib/pg_trgm/uninstall_pg_trgm.sql
deleted file mode 100644
index 42c1d741f9..0000000000
--- a/contrib/pg_trgm/uninstall_pg_trgm.sql
+++ /dev/null
@@ -1,42 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pg_trgm/uninstall_pg_trgm.sql,v 1.7 2009/03/25 22:19:01 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR CLASS gist_trgm_ops USING gist;
-
-DROP FUNCTION gtrgm_same(gtrgm, gtrgm, internal);
-
-DROP FUNCTION gtrgm_union(bytea, internal);
-
-DROP FUNCTION gtrgm_picksplit(internal, internal);
-
-DROP FUNCTION gtrgm_penalty(internal,internal,internal);
-
-DROP FUNCTION gtrgm_decompress(internal);
-
-DROP FUNCTION gtrgm_compress(internal);
-
-DROP FUNCTION gtrgm_consistent(internal,text,int,oid,internal);
-
-DROP TYPE gtrgm CASCADE;
-
-DROP OPERATOR CLASS gin_trgm_ops USING gin;
-
-DROP FUNCTION gin_extract_trgm(text, internal);
-
-DROP FUNCTION gin_extract_trgm(text, internal, int2, internal, internal);
-
-DROP FUNCTION gin_trgm_consistent(internal, int2, text, int4, internal, internal);
-
-DROP OPERATOR % (text, text);
-
-DROP FUNCTION similarity_op(text,text);
-
-DROP FUNCTION similarity(text,text);
-
-DROP FUNCTION show_trgm(text);
-
-DROP FUNCTION show_limit();
-
-DROP FUNCTION set_limit(float4);
diff --git a/contrib/pg_upgrade/.gitignore b/contrib/pg_upgrade/.gitignore
new file mode 100644
index 0000000000..03ec737bf2
--- /dev/null
+++ b/contrib/pg_upgrade/.gitignore
@@ -0,0 +1 @@
+/pg_upgrade
diff --git a/contrib/pg_upgrade/IMPLEMENTATION b/contrib/pg_upgrade/IMPLEMENTATION
index 91bee727b4..a0cfcf15da 100644
--- a/contrib/pg_upgrade/IMPLEMENTATION
+++ b/contrib/pg_upgrade/IMPLEMENTATION
@@ -1,4 +1,4 @@
-$PostgreSQL: pgsql/contrib/pg_upgrade/IMPLEMENTATION,v 1.3 2010/07/03 14:23:13 momjian Exp $
+contrib/pg_upgrade/IMPLEMENTATION
------------------------------------------------------------------------------
PG_UPGRADE: IN-PLACE UPGRADES FOR POSTGRESQL
@@ -13,7 +13,7 @@ old data. If you have a lot of data, that can take a considerable amount
of time. If you have too much data, you may have to buy more storage
since you need enough room to hold the original data plus the exported
data. pg_upgrade can reduce the amount of time and disk space required
-for many upgrades.
+for many upgrades.
The URL http://momjian.us/main/writings/pgsql/pg_upgrade.pdf contains a
presentation about pg_upgrade internals that mirrors the text
diff --git a/contrib/pg_upgrade/Makefile b/contrib/pg_upgrade/Makefile
index 1998ffe899..8f3fd7c9bb 100644
--- a/contrib/pg_upgrade/Makefile
+++ b/contrib/pg_upgrade/Makefile
@@ -1,7 +1,4 @@
-#
-# Makefile for pg_upgrade
-#
-# $PostgreSQL: pgsql/contrib/pg_upgrade/Makefile,v 1.4 2010/07/03 14:23:13 momjian Exp $
+# contrib/pg_upgrade/Makefile
PGFILEDESC = "pg_upgrade - an in-place binary upgrade utility"
PGAPPICON = win32
diff --git a/contrib/pg_upgrade/TESTING b/contrib/pg_upgrade/TESTING
index ca771fefdd..85de8da7f7 100644
--- a/contrib/pg_upgrade/TESTING
+++ b/contrib/pg_upgrade/TESTING
@@ -1,4 +1,4 @@
-$PostgreSQL: pgsql/contrib/pg_upgrade/TESTING,v 1.2 2010/07/03 14:23:13 momjian Exp $
+contrib/pg_upgrade/TESTING
The most effective way to test pg_upgrade, aside from testing on user
data, is by upgrading the PostgreSQL regression database.
@@ -22,11 +22,6 @@ Here are the steps needed to create a regression database dump file:
a) Change CREATE FUNCTION shared object paths to use '$libdir'
The old and new cluster will have different shared object paths.
- b) Remove 'regex_flavor' (not supported in Postgres 9.0)
-
- c) Change CREATE OR REPLACE LANGUAGE to CREATE LANGUAGE
- The former syntax is only supported in Postgres 9.0.
-
d) Perform the load/dump twice
This fixes problems with the ordering of COPY columns for
inherited tables.
@@ -35,11 +30,15 @@ Here are the steps needed to create a regression database dump file:
Commands like CREATE TRIGGER and ALTER TABLE sometimes have
differences.
- f) Adjust extra_float_digits
- Postgres 9.0 pg_dump uses extra_float_digits=-2 for pre-9.0
- databases, and extra_float_digits=-3 for >= 9.0 databases.
- It is necessary to modify 9.0 pg_dump to always use -3, and
- modify the pre-9.0 old server to accept extra_float_digits=-3.
+ c) For pre-9.0, change CREATE OR REPLACE LANGUAGE to CREATE LANGUAGE
+
+ b) For pre-9.0, remove 'regex_flavor'
+
+ f) For pre-9.0, adjust extra_float_digits
+ Postgres 9.0 pg_dump uses extra_float_digits=-2 for pre-9.0
+ databases, and extra_float_digits=-3 for >= 9.0 databases.
+ It is necessary to modify 9.0 pg_dump to always use -3, and
+ modify the pre-9.0 old server to accept extra_float_digits=-3.
Once the dump is created, it can be repeatedly loaded into the old
database, upgraded, and dumped out of the new database, and then
@@ -53,7 +52,7 @@ steps:
3) Create the regression database in the old server.
-4) Load the dump file created above into the regression database;
+4) Load the dump file created above into the regression database;
check for errors while loading.
5) Upgrade the old database to the new major version, as outlined in
@@ -63,7 +62,3 @@ steps:
7) Diff the regression database dump file with the regression dump
file loaded into the old server.
-
-
-
-
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index 0e96705b2d..fdec6e34af 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -3,76 +3,81 @@
*
* server checks and output routines
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/check.c,v 1.11 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/check.c
*/
#include "pg_upgrade.h"
-static void set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster);
-static void check_new_db_is_empty(migratorContext *ctx);
-static void check_locale_and_encoding(migratorContext *ctx, ControlData *oldctrl,
+static void set_locale_and_encoding(ClusterInfo *cluster);
+static void check_new_cluster_is_empty(void);
+static void check_old_cluster_has_new_cluster_dbs(void);
+static void check_locale_and_encoding(ControlData *oldctrl,
ControlData *newctrl);
+static void check_is_super_user(ClusterInfo *cluster);
+static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
+static void check_for_reg_data_type_usage(ClusterInfo *cluster);
void
-output_check_banner(migratorContext *ctx, bool *live_check)
+output_check_banner(bool *live_check)
{
- if (ctx->check && is_server_running(ctx, ctx->old.pgdata))
+ if (user_opts.check && is_server_running(old_cluster.pgdata))
{
*live_check = true;
- if (ctx->old.port == ctx->new.port)
- pg_log(ctx, PG_FATAL, "When checking a live server, "
+ if (old_cluster.port == new_cluster.port)
+ pg_log(PG_FATAL, "When checking a live server, "
"the old and new port numbers must be different.\n");
- pg_log(ctx, PG_REPORT, "PerForming Consistency Checks on Old Live Server\n");
- pg_log(ctx, PG_REPORT, "------------------------------------------------\n");
+ pg_log(PG_REPORT, "PerForming Consistency Checks on Old Live Server\n");
+ pg_log(PG_REPORT, "------------------------------------------------\n");
}
else
{
- pg_log(ctx, PG_REPORT, "Performing Consistency Checks\n");
- pg_log(ctx, PG_REPORT, "-----------------------------\n");
+ pg_log(PG_REPORT, "Performing Consistency Checks\n");
+ pg_log(PG_REPORT, "-----------------------------\n");
}
}
void
-check_old_cluster(migratorContext *ctx, bool live_check,
+check_old_cluster(bool live_check,
char **sequence_script_file_name)
{
/* -- OLD -- */
if (!live_check)
- start_postmaster(ctx, CLUSTER_OLD, false);
+ start_postmaster(&old_cluster);
- set_locale_and_encoding(ctx, CLUSTER_OLD);
+ set_locale_and_encoding(&old_cluster);
- get_pg_database_relfilenode(ctx, CLUSTER_OLD);
+ get_pg_database_relfilenode(&old_cluster);
/* Extract a list of databases and tables from the old cluster */
- get_db_and_rel_infos(ctx, &ctx->old.dbarr, CLUSTER_OLD);
+ get_db_and_rel_infos(&old_cluster);
- init_tablespaces(ctx);
+ init_tablespaces();
- get_loadable_libraries(ctx);
+ get_loadable_libraries();
/*
* Check for various failure cases
*/
-
- old_8_3_check_for_isn_and_int8_passing_mismatch(ctx, CLUSTER_OLD);
+ check_is_super_user(&old_cluster);
+ check_for_reg_data_type_usage(&old_cluster);
+ check_for_isn_and_int8_passing_mismatch(&old_cluster);
/* old = PG 8.3 checks? */
- if (GET_MAJOR_VERSION(ctx->old.major_version) <= 803)
+ if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
{
- old_8_3_check_for_name_data_type_usage(ctx, CLUSTER_OLD);
- old_8_3_check_for_tsquery_usage(ctx, CLUSTER_OLD);
- if (ctx->check)
+ old_8_3_check_for_name_data_type_usage(&old_cluster);
+ old_8_3_check_for_tsquery_usage(&old_cluster);
+ if (user_opts.check)
{
- old_8_3_rebuild_tsvector_tables(ctx, true, CLUSTER_OLD);
- old_8_3_invalidate_hash_gin_indexes(ctx, true, CLUSTER_OLD);
- old_8_3_invalidate_bpchar_pattern_ops_indexes(ctx, true, CLUSTER_OLD);
+ old_8_3_rebuild_tsvector_tables(&old_cluster, true);
+ old_8_3_invalidate_hash_gin_indexes(&old_cluster, true);
+ old_8_3_invalidate_bpchar_pattern_ops_indexes(&old_cluster, true);
}
else
@@ -82,120 +87,123 @@ check_old_cluster(migratorContext *ctx, bool live_check,
* end.
*/
*sequence_script_file_name =
- old_8_3_create_sequence_script(ctx, CLUSTER_OLD);
+ old_8_3_create_sequence_script(&old_cluster);
}
/* Pre-PG 9.0 had no large object permissions */
- if (GET_MAJOR_VERSION(ctx->old.major_version) <= 804)
- new_9_0_populate_pg_largeobject_metadata(ctx, true, CLUSTER_OLD);
+ if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
+ new_9_0_populate_pg_largeobject_metadata(&old_cluster, true);
/*
* While not a check option, we do this now because this is the only time
* the old server is running.
*/
- if (!ctx->check)
+ if (!user_opts.check)
{
- generate_old_dump(ctx);
- split_old_dump(ctx);
+ generate_old_dump();
+ split_old_dump();
}
if (!live_check)
- stop_postmaster(ctx, false, false);
+ stop_postmaster(false);
}
void
-check_new_cluster(migratorContext *ctx)
+check_new_cluster(void)
{
- set_locale_and_encoding(ctx, CLUSTER_NEW);
+ set_locale_and_encoding(&new_cluster);
+
+ get_db_and_rel_infos(&new_cluster);
- check_new_db_is_empty(ctx);
+ check_new_cluster_is_empty();
+ check_old_cluster_has_new_cluster_dbs();
- check_loadable_libraries(ctx);
+ check_loadable_libraries();
- check_locale_and_encoding(ctx, &ctx->old.controldata, &ctx->new.controldata);
+ check_locale_and_encoding(&old_cluster.controldata, &new_cluster.controldata);
- if (ctx->transfer_mode == TRANSFER_MODE_LINK)
- check_hard_link(ctx);
+ if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
+ check_hard_link();
}
void
-report_clusters_compatible(migratorContext *ctx)
+report_clusters_compatible(void)
{
- if (ctx->check)
+ if (user_opts.check)
{
- pg_log(ctx, PG_REPORT, "\n*Clusters are compatible*\n");
+ pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
/* stops new cluster */
- stop_postmaster(ctx, false, false);
- exit_nicely(ctx, false);
+ stop_postmaster(false);
+ exit(0);
}
- pg_log(ctx, PG_REPORT, "\n"
+ pg_log(PG_REPORT, "\n"
"| If pg_upgrade fails after this point, you must\n"
"| re-initdb the new cluster before continuing.\n"
"| You will also need to remove the \".old\" suffix\n"
- "| from %s/global/pg_control.old.\n", ctx->old.pgdata);
+ "| from %s/global/pg_control.old.\n", old_cluster.pgdata);
}
void
-issue_warnings(migratorContext *ctx, char *sequence_script_file_name)
+issue_warnings(char *sequence_script_file_name)
{
/* old = PG 8.3 warnings? */
- if (GET_MAJOR_VERSION(ctx->old.major_version) <= 803)
+ if (GET_MAJOR_VERSION(old_cluster.major_version) <= 803)
{
- start_postmaster(ctx, CLUSTER_NEW, true);
+ start_postmaster(&new_cluster);
/* restore proper sequence values using file created from old server */
if (sequence_script_file_name)
{
- prep_status(ctx, "Adjusting sequences");
- exec_prog(ctx, true,
- SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on --port %d "
- "--username \"%s\" -f \"%s\" --dbname template1 >> \"%s\""
- SYSTEMQUOTE,
- ctx->new.bindir, ctx->new.port, ctx->user,
- sequence_script_file_name, ctx->logfile);
+ prep_status("Adjusting sequences");
+ exec_prog(true,
+ SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on "
+ "--no-psqlrc --port %d --username \"%s\" "
+ "-f \"%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
+ new_cluster.bindir, new_cluster.port, os_info.user,
+ sequence_script_file_name, log_opts.filename);
unlink(sequence_script_file_name);
- check_ok(ctx);
+ check_ok();
}
- old_8_3_rebuild_tsvector_tables(ctx, false, CLUSTER_NEW);
- old_8_3_invalidate_hash_gin_indexes(ctx, false, CLUSTER_NEW);
- old_8_3_invalidate_bpchar_pattern_ops_indexes(ctx, false, CLUSTER_NEW);
- stop_postmaster(ctx, false, true);
+ old_8_3_rebuild_tsvector_tables(&new_cluster, false);
+ old_8_3_invalidate_hash_gin_indexes(&new_cluster, false);
+ old_8_3_invalidate_bpchar_pattern_ops_indexes(&new_cluster, false);
+ stop_postmaster(false);
}
/* Create dummy large object permissions for old < PG 9.0? */
- if (GET_MAJOR_VERSION(ctx->old.major_version) <= 804)
+ if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
{
- start_postmaster(ctx, CLUSTER_NEW, true);
- new_9_0_populate_pg_largeobject_metadata(ctx, false, CLUSTER_NEW);
- stop_postmaster(ctx, false, true);
+ start_postmaster(&new_cluster);
+ new_9_0_populate_pg_largeobject_metadata(&new_cluster, false);
+ stop_postmaster(false);
}
}
void
-output_completion_banner(migratorContext *ctx, char *deletion_script_file_name)
+output_completion_banner(char *deletion_script_file_name)
{
- /* Did we migrate the free space files? */
- if (GET_MAJOR_VERSION(ctx->old.major_version) >= 804)
- pg_log(ctx, PG_REPORT,
- "| Optimizer statistics is not transferred by pg_upgrade\n"
+ /* Did we copy the free space files? */
+ if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
+ pg_log(PG_REPORT,
+ "| Optimizer statistics are not transferred by pg_upgrade\n"
"| so consider running:\n"
"| \tvacuumdb --all --analyze-only\n"
"| on the newly-upgraded cluster.\n\n");
else
- pg_log(ctx, PG_REPORT,
+ pg_log(PG_REPORT,
"| Optimizer statistics and free space information\n"
"| are not transferred by pg_upgrade so consider\n"
"| running:\n"
"| \tvacuumdb --all --analyze\n"
"| on the newly-upgraded cluster.\n\n");
- pg_log(ctx, PG_REPORT,
+ pg_log(PG_REPORT,
"| Running this script will delete the old cluster's data files:\n"
"| \t%s\n",
deletion_script_file_name);
@@ -203,33 +211,36 @@ output_completion_banner(migratorContext *ctx, char *deletion_script_file_name)
void
-check_cluster_versions(migratorContext *ctx)
+check_cluster_versions(void)
{
/* get old and new cluster versions */
- ctx->old.major_version = get_major_server_version(ctx, &ctx->old.major_version_str, CLUSTER_OLD);
- ctx->new.major_version = get_major_server_version(ctx, &ctx->new.major_version_str, CLUSTER_NEW);
+ old_cluster.major_version = get_major_server_version(&old_cluster);
+ new_cluster.major_version = get_major_server_version(&new_cluster);
- /* We allow migration from/to the same major version for beta upgrades */
+ /*
+ * We allow upgrades from/to the same major version for alpha/beta
+ * upgrades
+ */
- if (GET_MAJOR_VERSION(ctx->old.major_version) < 803)
- pg_log(ctx, PG_FATAL, "This utility can only upgrade from PostgreSQL version 8.3 and later.\n");
+ if (GET_MAJOR_VERSION(old_cluster.major_version) < 803)
+ pg_log(PG_FATAL, "This utility can only upgrade from PostgreSQL version 8.3 and later.\n");
/* Only current PG version is supported as a target */
- if (GET_MAJOR_VERSION(ctx->new.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
- pg_log(ctx, PG_FATAL, "This utility can only upgrade to PostgreSQL version %s.\n",
+ if (GET_MAJOR_VERSION(new_cluster.major_version) != GET_MAJOR_VERSION(PG_VERSION_NUM))
+ pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version %s.\n",
PG_MAJORVERSION);
/*
* We can't allow downgrading because we use the target pg_dumpall, and
* pg_dumpall cannot operate on new datbase versions, only older versions.
*/
- if (ctx->old.major_version > ctx->new.major_version)
- pg_log(ctx, PG_FATAL, "This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
+ if (old_cluster.major_version > new_cluster.major_version)
+ pg_log(PG_FATAL, "This utility cannot be used to downgrade to older major PostgreSQL versions.\n");
}
void
-check_cluster_compatibility(migratorContext *ctx, bool live_check)
+check_cluster_compatibility(bool live_check)
{
char libfile[MAXPGPATH];
FILE *lib_test;
@@ -238,24 +249,24 @@ check_cluster_compatibility(migratorContext *ctx, bool live_check)
* Test pg_upgrade_support.so is in the proper place. We cannot copy it
* ourselves because install directories are typically root-owned.
*/
- snprintf(libfile, sizeof(libfile), "%s/pg_upgrade_support%s", ctx->new.libpath,
+ snprintf(libfile, sizeof(libfile), "%s/pg_upgrade_support%s", new_cluster.libpath,
DLSUFFIX);
if ((lib_test = fopen(libfile, "r")) == NULL)
- pg_log(ctx, PG_FATAL,
- "\npg_upgrade_support%s must be created and installed in %s\n", DLSUFFIX, libfile);
+ pg_log(PG_FATAL,
+ "pg_upgrade_support%s must be created and installed in %s\n", DLSUFFIX, libfile);
else
fclose(lib_test);
/* get/check pg_control data of servers */
- get_control_data(ctx, &ctx->old, live_check);
- get_control_data(ctx, &ctx->new, false);
- check_control_data(ctx, &ctx->old.controldata, &ctx->new.controldata);
+ get_control_data(&old_cluster, live_check);
+ get_control_data(&new_cluster, false);
+ check_control_data(&old_cluster.controldata, &new_cluster.controldata);
/* Is it 9.0 but without tablespace directories? */
- if (GET_MAJOR_VERSION(ctx->new.major_version) == 900 &&
- ctx->new.controldata.cat_ver < TABLE_SPACE_SUBDIRS)
- pg_log(ctx, PG_FATAL, "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n"
+ if (GET_MAJOR_VERSION(new_cluster.major_version) == 900 &&
+ new_cluster.controldata.cat_ver < TABLE_SPACE_SUBDIRS_CAT_VER)
+ pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n"
"because of backend API changes made during development.\n");
}
@@ -266,17 +277,15 @@ check_cluster_compatibility(migratorContext *ctx, bool live_check)
* query the database to get the template0 locale
*/
static void
-set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster)
+set_locale_and_encoding(ClusterInfo *cluster)
{
+ ControlData *ctrl = &cluster->controldata;
PGconn *conn;
PGresult *res;
int i_encoding;
- ControlData *ctrl = (whichCluster == CLUSTER_OLD) ?
- &ctx->old.controldata : &ctx->new.controldata;
- int cluster_version = (whichCluster == CLUSTER_OLD) ?
- ctx->old.major_version : ctx->new.major_version;
+ int cluster_version = cluster->major_version;
- conn = connectToServer(ctx, "template1", whichCluster);
+ conn = connectToServer(cluster, "template1");
/* for pg < 80400, we got the values from pg_controldata */
if (cluster_version >= 80400)
@@ -284,7 +293,7 @@ set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster)
int i_datcollate;
int i_datctype;
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT datcollate, datctype "
"FROM pg_catalog.pg_database "
"WHERE datname = 'template0' ");
@@ -293,20 +302,20 @@ set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster)
i_datcollate = PQfnumber(res, "datcollate");
i_datctype = PQfnumber(res, "datctype");
- ctrl->lc_collate = pg_strdup(ctx, PQgetvalue(res, 0, i_datcollate));
- ctrl->lc_ctype = pg_strdup(ctx, PQgetvalue(res, 0, i_datctype));
+ ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
+ ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
PQclear(res);
}
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT pg_catalog.pg_encoding_to_char(encoding) "
"FROM pg_catalog.pg_database "
"WHERE datname = 'template0' ");
assert(PQntuples(res) == 1);
i_encoding = PQfnumber(res, "pg_encoding_to_char");
- ctrl->encoding = pg_strdup(ctx, PQgetvalue(res, 0, i_encoding));
+ ctrl->encoding = pg_strdup(PQgetvalue(res, 0, i_encoding));
PQclear(res);
@@ -321,50 +330,70 @@ set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster)
* we probably had to get via a database query.
*/
static void
-check_locale_and_encoding(migratorContext *ctx, ControlData *oldctrl,
+check_locale_and_encoding(ControlData *oldctrl,
ControlData *newctrl)
{
- if (strcmp(oldctrl->lc_collate, newctrl->lc_collate) != 0)
- pg_log(ctx, PG_FATAL,
+ /* These are often defined with inconsistent case, so use pg_strcasecmp(). */
+ if (pg_strcasecmp(oldctrl->lc_collate, newctrl->lc_collate) != 0)
+ pg_log(PG_FATAL,
"old and new cluster lc_collate values do not match\n");
- if (strcmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0)
- pg_log(ctx, PG_FATAL,
+ if (pg_strcasecmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0)
+ pg_log(PG_FATAL,
"old and new cluster lc_ctype values do not match\n");
- if (strcmp(oldctrl->encoding, newctrl->encoding) != 0)
- pg_log(ctx, PG_FATAL,
+ if (pg_strcasecmp(oldctrl->encoding, newctrl->encoding) != 0)
+ pg_log(PG_FATAL,
"old and new cluster encoding values do not match\n");
}
static void
-check_new_db_is_empty(migratorContext *ctx)
+check_new_cluster_is_empty(void)
{
int dbnum;
- bool found = false;
-
- get_db_and_rel_infos(ctx, &ctx->new.dbarr, CLUSTER_NEW);
- for (dbnum = 0; dbnum < ctx->new.dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
{
int relnum;
- RelInfoArr *rel_arr = &ctx->new.dbarr.dbs[dbnum].rel_arr;
+ RelInfoArr *rel_arr = &new_cluster.dbarr.dbs[dbnum].rel_arr;
for (relnum = 0; relnum < rel_arr->nrels;
relnum++)
{
/* pg_largeobject and its index should be skipped */
if (strcmp(rel_arr->rels[relnum].nspname, "pg_catalog") != 0)
- {
- found = true;
- break;
- }
+ pg_log(PG_FATAL, "New cluster database \"%s\" is not empty\n",
+ new_cluster.dbarr.dbs[dbnum].db_name);
}
}
- dbarr_free(&ctx->new.dbarr);
+}
+
- if (found)
- pg_log(ctx, PG_FATAL, "New cluster is not empty; exiting\n");
+/*
+ * If someone removes the 'postgres' database from the old cluster and
+ * the new cluster has a 'postgres' database, the number of databases
+ * will not match. We actually could upgrade such a setup, but it would
+ * violate the 1-to-1 mapping of database counts, so we throw an error
+ * instead. We would detect this as a database count mismatch during
+ * upgrade, but we want to detect it during the check phase and report
+ * the database name.
+ */
+static void
+check_old_cluster_has_new_cluster_dbs(void)
+{
+ int old_dbnum,
+ new_dbnum;
+
+ for (new_dbnum = 0; new_dbnum < new_cluster.dbarr.ndbs; new_dbnum++)
+ {
+ for (old_dbnum = 0; old_dbnum < old_cluster.dbarr.ndbs; old_dbnum++)
+ if (strcmp(old_cluster.dbarr.dbs[old_dbnum].db_name,
+ new_cluster.dbarr.dbs[new_dbnum].db_name) == 0)
+ break;
+ if (old_dbnum == old_cluster.dbarr.ndbs)
+ pg_log(PG_FATAL, "New cluster database \"%s\" does not exist in the old cluster\n",
+ new_cluster.dbarr.dbs[new_dbnum].db_name);
+ }
}
@@ -374,21 +403,21 @@ check_new_db_is_empty(migratorContext *ctx)
* This is particularly useful for tablespace deletion.
*/
void
-create_script_for_old_cluster_deletion(migratorContext *ctx,
+create_script_for_old_cluster_deletion(
char **deletion_script_file_name)
{
FILE *script = NULL;
int tblnum;
- *deletion_script_file_name = pg_malloc(ctx, MAXPGPATH);
+ *deletion_script_file_name = pg_malloc(MAXPGPATH);
- prep_status(ctx, "Creating script to delete old cluster");
+ prep_status("Creating script to delete old cluster");
snprintf(*deletion_script_file_name, MAXPGPATH, "%s/delete_old_cluster.%s",
- ctx->cwd, EXEC_EXT);
+ os_info.cwd, SCRIPT_EXT);
if ((script = fopen(*deletion_script_file_name, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n",
+ pg_log(PG_FATAL, "Could not create necessary file: %s\n",
*deletion_script_file_name);
#ifndef WIN32
@@ -397,26 +426,31 @@ create_script_for_old_cluster_deletion(migratorContext *ctx,
#endif
/* delete old cluster's default tablespace */
- fprintf(script, RMDIR_CMD " %s\n", ctx->old.pgdata);
+ fprintf(script, RMDIR_CMD " %s\n", old_cluster.pgdata);
/* delete old cluster's alternate tablespaces */
- for (tblnum = 0; tblnum < ctx->num_tablespaces; tblnum++)
+ for (tblnum = 0; tblnum < os_info.num_tablespaces; tblnum++)
{
/*
* Do the old cluster's per-database directories share a directory
* with a new version-specific tablespace?
*/
- if (strlen(ctx->old.tablespace_suffix) == 0)
+ if (strlen(old_cluster.tablespace_suffix) == 0)
{
/* delete per-database directories */
int dbnum;
fprintf(script, "\n");
- for (dbnum = 0; dbnum < ctx->new.dbarr.ndbs; dbnum++)
+ /* remove PG_VERSION? */
+ if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
+ fprintf(script, RM_CMD " %s%s/PG_VERSION\n",
+ os_info.tablespaces[tblnum], old_cluster.tablespace_suffix);
+
+ for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
{
fprintf(script, RMDIR_CMD " %s%s/%d\n",
- ctx->tablespaces[tblnum], ctx->old.tablespace_suffix,
- ctx->old.dbarr.dbs[dbnum].db_oid);
+ os_info.tablespaces[tblnum], old_cluster.tablespace_suffix,
+ old_cluster.dbarr.dbs[dbnum].db_oid);
}
}
else
@@ -426,16 +460,240 @@ create_script_for_old_cluster_deletion(migratorContext *ctx,
* or a version-specific subdirectory.
*/
fprintf(script, RMDIR_CMD " %s%s\n",
- ctx->tablespaces[tblnum], ctx->old.tablespace_suffix);
+ os_info.tablespaces[tblnum], old_cluster.tablespace_suffix);
}
fclose(script);
#ifndef WIN32
if (chmod(*deletion_script_file_name, S_IRWXU) != 0)
- pg_log(ctx, PG_FATAL, "Could not add execute permission to file: %s\n",
+ pg_log(PG_FATAL, "Could not add execute permission to file: %s\n",
*deletion_script_file_name);
#endif
- check_ok(ctx);
+ check_ok();
+}
+
+
+/*
+ * check_is_super_user()
+ *
+ * Make sure we are the super-user.
+ */
+static void
+check_is_super_user(ClusterInfo *cluster)
+{
+ PGresult *res;
+ PGconn *conn = connectToServer(cluster, "template1");
+
+ prep_status("Checking database user is a superuser");
+
+ /* Can't use pg_authid because only superusers can view it. */
+ res = executeQueryOrDie(conn,
+ "SELECT rolsuper "
+ "FROM pg_catalog.pg_roles "
+ "WHERE rolname = current_user");
+
+ if (PQntuples(res) != 1 || strcmp(PQgetvalue(res, 0, 0), "t") != 0)
+ pg_log(PG_FATAL, "database user \"%s\" is not a superuser\n",
+ os_info.user);
+
+ PQclear(res);
+
+ PQfinish(conn);
+
+ check_ok();
+}
+
+
+/*
+ * check_for_isn_and_int8_passing_mismatch()
+ *
+ * contrib/isn relies on data type int8, and in 8.4 int8 can now be passed
+ * by value. The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
+ * it must match for the old and new servers.
+ */
+static void
+check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster)
+{
+ int dbnum;
+ FILE *script = NULL;
+ bool found = false;
+ char output_path[MAXPGPATH];
+
+ prep_status("Checking for contrib/isn with bigint-passing mismatch");
+
+ if (old_cluster.controldata.float8_pass_by_value ==
+ new_cluster.controldata.float8_pass_by_value)
+ {
+ /* no mismatch */
+ check_ok();
+ return;
+ }
+
+ snprintf(output_path, sizeof(output_path), "%s/contrib_isn_and_int8_pass_by_value.txt",
+ os_info.cwd);
+
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
+ {
+ PGresult *res;
+ bool db_used = false;
+ int ntups;
+ int rowno;
+ int i_nspname,
+ i_proname;
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
+
+ /* Find any functions coming from contrib/isn */
+ res = executeQueryOrDie(conn,
+ "SELECT n.nspname, p.proname "
+ "FROM pg_catalog.pg_proc p, "
+ " pg_catalog.pg_namespace n "
+ "WHERE p.pronamespace = n.oid AND "
+ " p.probin = '$libdir/isn'");
+
+ ntups = PQntuples(res);
+ i_nspname = PQfnumber(res, "nspname");
+ i_proname = PQfnumber(res, "proname");
+ for (rowno = 0; rowno < ntups; rowno++)
+ {
+ found = true;
+ if (script == NULL && (script = fopen(output_path, "w")) == NULL)
+ pg_log(PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ if (!db_used)
+ {
+ fprintf(script, "Database: %s\n", active_db->db_name);
+ db_used = true;
+ }
+ fprintf(script, " %s.%s\n",
+ PQgetvalue(res, rowno, i_nspname),
+ PQgetvalue(res, rowno, i_proname));
+ }
+
+ PQclear(res);
+
+ PQfinish(conn);
+ }
+
+ if (script)
+ fclose(script);
+
+ if (found)
+ {
+ pg_log(PG_REPORT, "fatal\n");
+ pg_log(PG_FATAL,
+ "| Your installation contains \"contrib/isn\" functions\n"
+ "| which rely on the bigint data type. Your old and\n"
+ "| new clusters pass bigint values differently so this\n"
+ "| cluster cannot currently be upgraded. You can\n"
+ "| manually upgrade data that use \"contrib/isn\"\n"
+ "| facilities and remove \"contrib/isn\" from the\n"
+ "| old cluster and restart the upgrade. A list\n"
+ "| of the problem functions is in the file:\n"
+ "| \t%s\n\n", output_path);
+ }
+ else
+ check_ok();
+}
+
+
+/*
+ * check_for_reg_data_type_usage()
+ * pg_upgrade only preserves these system values:
+ * pg_class.relfilenode
+ * pg_type.oid
+ * pg_enum.oid
+ *
+ * Most of the reg* data types reference system catalog info that is
+ * not preserved, and hence these data types cannot be used in user
+ * tables upgraded by pg_upgrade.
+ */
+static void
+check_for_reg_data_type_usage(ClusterInfo *cluster)
+{
+ int dbnum;
+ FILE *script = NULL;
+ bool found = false;
+ char output_path[MAXPGPATH];
+
+ prep_status("Checking for reg* system oid user data types");
+
+ snprintf(output_path, sizeof(output_path), "%s/tables_using_reg.txt",
+ os_info.cwd);
+
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
+ {
+ PGresult *res;
+ bool db_used = false;
+ int ntups;
+ int rowno;
+ int i_nspname,
+ i_relname,
+ i_attname;
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
+
+ res = executeQueryOrDie(conn,
+ "SELECT n.nspname, c.relname, a.attname "
+ "FROM pg_catalog.pg_class c, "
+ " pg_catalog.pg_namespace n, "
+ " pg_catalog.pg_attribute a "
+ "WHERE c.oid = a.attrelid AND "
+ " NOT a.attisdropped AND "
+ " a.atttypid IN ( "
+ " 'pg_catalog.regproc'::pg_catalog.regtype, "
+ " 'pg_catalog.regprocedure'::pg_catalog.regtype, "
+ " 'pg_catalog.regoper'::pg_catalog.regtype, "
+ " 'pg_catalog.regoperator'::pg_catalog.regtype, "
+ " 'pg_catalog.regclass'::pg_catalog.regtype, "
+ /* regtype.oid is preserved, so 'regtype' is OK */
+ " 'pg_catalog.regconfig'::pg_catalog.regtype, "
+ " 'pg_catalog.regdictionary'::pg_catalog.regtype) AND "
+ " c.relnamespace = n.oid AND "
+ " n.nspname != 'pg_catalog' AND "
+ " n.nspname != 'information_schema'");
+
+ ntups = PQntuples(res);
+ i_nspname = PQfnumber(res, "nspname");
+ i_relname = PQfnumber(res, "relname");
+ i_attname = PQfnumber(res, "attname");
+ for (rowno = 0; rowno < ntups; rowno++)
+ {
+ found = true;
+ if (script == NULL && (script = fopen(output_path, "w")) == NULL)
+ pg_log(PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ if (!db_used)
+ {
+ fprintf(script, "Database: %s\n", active_db->db_name);
+ db_used = true;
+ }
+ fprintf(script, " %s.%s.%s\n",
+ PQgetvalue(res, rowno, i_nspname),
+ PQgetvalue(res, rowno, i_relname),
+ PQgetvalue(res, rowno, i_attname));
+ }
+
+ PQclear(res);
+
+ PQfinish(conn);
+ }
+
+ if (script)
+ fclose(script);
+
+ if (found)
+ {
+ pg_log(PG_REPORT, "fatal\n");
+ pg_log(PG_FATAL,
+ "| Your installation contains one of the reg* data types in\n"
+ "| user tables. These data types reference system oids that\n"
+ "| are not preserved by pg_upgrade, so this cluster cannot\n"
+ "| currently be upgraded. You can remove the problem tables\n"
+ "| and restart the upgrade. A list of the problem columns\n"
+ "| is in the file:\n"
+ "| \t%s\n\n", output_path);
+ }
+ else
+ check_ok();
}
diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c
index 18c1e89f4b..25ee81f2a0 100644
--- a/contrib/pg_upgrade/controldata.c
+++ b/contrib/pg_upgrade/controldata.c
@@ -3,15 +3,14 @@
*
* controldata functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/controldata.c,v 1.9 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/controldata.c
*/
#include "pg_upgrade.h"
#include <ctype.h>
-
/*
* get_control_data()
*
@@ -25,12 +24,12 @@
* and then pipe its output. With little string parsing we get the
* pg_control data. pg_resetxlog cannot be run while the server is running
* so we use pg_controldata; pg_controldata doesn't provide all the fields
- * we need to actually perform the migration, but it provides enough for
+ * we need to actually perform the upgrade, but it provides enough for
* check mode. We do not implement pg_resetxlog -n because it is hard to
* return valid xid data for a running server.
*/
void
-get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
+get_control_data(ClusterInfo *cluster, bool live_check)
{
char cmd[MAXPGPATH];
char bufin[MAX_STRING];
@@ -51,19 +50,55 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
bool got_toast = false;
bool got_date_is_int = false;
bool got_float8_pass_by_value = false;
+ char *lc_collate = NULL;
+ char *lc_ctype = NULL;
+ char *lc_monetary = NULL;
+ char *lc_numeric = NULL;
+ char *lc_time = NULL;
char *lang = NULL;
+ char *language = NULL;
+ char *lc_all = NULL;
+ char *lc_messages = NULL;
/*
- * Because we test the pg_resetxlog output strings, it has to be in
- * English.
+ * Because we test the pg_resetxlog output as strings, it has to be in
+ * English. Copied from pg_regress.c.
*/
+ if (getenv("LC_COLLATE"))
+ lc_collate = pg_strdup(getenv("LC_COLLATE"));
+ if (getenv("LC_CTYPE"))
+ lc_ctype = pg_strdup(getenv("LC_CTYPE"));
+ if (getenv("LC_MONETARY"))
+ lc_monetary = pg_strdup(getenv("LC_MONETARY"));
+ if (getenv("LC_NUMERIC"))
+ lc_numeric = pg_strdup(getenv("LC_NUMERIC"));
+ if (getenv("LC_TIME"))
+ lc_time = pg_strdup(getenv("LC_TIME"));
if (getenv("LANG"))
- lang = pg_strdup(ctx, getenv("LANG"));
+ lang = pg_strdup(getenv("LANG"));
+ if (getenv("LANGUAGE"))
+ language = pg_strdup(getenv("LANGUAGE"));
+ if (getenv("LC_ALL"))
+ lc_all = pg_strdup(getenv("LC_ALL"));
+ if (getenv("LC_MESSAGES"))
+ lc_messages = pg_strdup(getenv("LC_MESSAGES"));
+
+ pg_putenv("LC_COLLATE", NULL);
+ pg_putenv("LC_CTYPE", NULL);
+ pg_putenv("LC_MONETARY", NULL);
+ pg_putenv("LC_NUMERIC", NULL);
+ pg_putenv("LC_TIME", NULL);
+ pg_putenv("LANG",
#ifndef WIN32
- putenv(pg_strdup(ctx, "LANG=C"));
+ NULL);
#else
- SetEnvironmentVariableA("LANG", "C");
+ /* On Windows the default locale cannot be English, so force it */
+ "en");
#endif
+ pg_putenv("LANGUAGE", NULL);
+ pg_putenv("LC_ALL", NULL);
+ pg_putenv("LC_MESSAGES", "C");
+
snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/%s \"%s\"" SYSTEMQUOTE,
cluster->bindir,
live_check ? "pg_controldata\"" : "pg_resetxlog\" -n",
@@ -72,7 +107,7 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
fflush(stderr);
if ((output = popen(cmd, "r")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not get control data: %s\n",
+ pg_log(PG_FATAL, "Could not get control data: %s\n",
getErrorText(errno));
/* Only pre-8.4 has these so if they are not set below we will check later */
@@ -89,8 +124,8 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
/* we have the result of cmd in "output". so parse it line by line now */
while (fgets(bufin, sizeof(bufin), output))
{
- if (ctx->debug)
- fputs(bufin, ctx->debug_fd);
+ if (log_opts.debug)
+ fputs(bufin, log_opts.debug_fd);
#ifdef WIN32
@@ -103,7 +138,7 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
{
for (p = bufin; *p; p++)
if (!isascii(*p))
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"The 8.3 cluster's pg_controldata is incapable of outputting ASCII, even\n"
"with LANG=C. You must upgrade this cluster to a newer version of Postgres\n"
"8.3 to fix this bug. Postgres 8.3.7 and later are known to work properly.\n");
@@ -115,30 +150,30 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: pg_resetxlog problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: pg_resetxlog problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.ctrl_ver = (uint32) atol(p);
+ cluster->controldata.ctrl_ver = str2uint(p);
}
else if ((p = strstr(bufin, "Catalog version number:")) != NULL)
{
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.cat_ver = (uint32) atol(p);
+ cluster->controldata.cat_ver = str2uint(p);
}
else if ((p = strstr(bufin, "First log file ID after reset:")) != NULL)
{
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.logid = (uint32) atol(p);
+ cluster->controldata.logid = str2uint(p);
got_log_id = true;
}
else if ((p = strstr(bufin, "First log file segment after reset:")) != NULL)
@@ -146,10 +181,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.nxtlogseg = (uint32) atol(p);
+ cluster->controldata.nxtlogseg = str2uint(p);
got_log_seg = true;
}
else if ((p = strstr(bufin, "Latest checkpoint's TimeLineID:")) != NULL)
@@ -157,10 +192,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.chkpnt_tli = (uint32) atol(p);
+ cluster->controldata.chkpnt_tli = str2uint(p);
got_tli = true;
}
else if ((p = strstr(bufin, "Latest checkpoint's NextXID:")) != NULL)
@@ -171,10 +206,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
op = strchr(p, ':');
if (op == NULL || strlen(op) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
op++; /* removing ':' char */
- cluster->controldata.chkpnt_nxtxid = (uint32) atol(op);
+ cluster->controldata.chkpnt_nxtxid = str2uint(op);
got_xid = true;
}
else if ((p = strstr(bufin, "Latest checkpoint's NextOID:")) != NULL)
@@ -182,10 +217,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.chkpnt_nxtoid = (uint32) atol(p);
+ cluster->controldata.chkpnt_nxtoid = str2uint(p);
got_oid = true;
}
else if ((p = strstr(bufin, "Maximum data alignment:")) != NULL)
@@ -193,10 +228,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.align = (uint32) atol(p);
+ cluster->controldata.align = str2uint(p);
got_align = true;
}
else if ((p = strstr(bufin, "Database block size:")) != NULL)
@@ -204,10 +239,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.blocksz = (uint32) atol(p);
+ cluster->controldata.blocksz = str2uint(p);
got_blocksz = true;
}
else if ((p = strstr(bufin, "Blocks per segment of large relation:")) != NULL)
@@ -215,10 +250,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.largesz = (uint32) atol(p);
+ cluster->controldata.largesz = str2uint(p);
got_largesz = true;
}
else if ((p = strstr(bufin, "WAL block size:")) != NULL)
@@ -226,10 +261,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.walsz = (uint32) atol(p);
+ cluster->controldata.walsz = str2uint(p);
got_walsz = true;
}
else if ((p = strstr(bufin, "Bytes per WAL segment:")) != NULL)
@@ -237,10 +272,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.walseg = (uint32) atol(p);
+ cluster->controldata.walseg = str2uint(p);
got_walseg = true;
}
else if ((p = strstr(bufin, "Maximum length of identifiers:")) != NULL)
@@ -248,10 +283,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.ident = (uint32) atol(p);
+ cluster->controldata.ident = str2uint(p);
got_ident = true;
}
else if ((p = strstr(bufin, "Maximum columns in an index:")) != NULL)
@@ -259,10 +294,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.index = (uint32) atol(p);
+ cluster->controldata.index = str2uint(p);
got_index = true;
}
else if ((p = strstr(bufin, "Maximum size of a TOAST chunk:")) != NULL)
@@ -270,10 +305,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- cluster->controldata.toast = (uint32) atol(p);
+ cluster->controldata.toast = str2uint(p);
got_toast = true;
}
else if ((p = strstr(bufin, "Date/time type storage:")) != NULL)
@@ -281,7 +316,7 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
cluster->controldata.date_is_int = strstr(p, "64-bit integers") != NULL;
@@ -292,10 +327,10 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
- /* used later for /contrib check */
+ /* used later for contrib check */
cluster->controldata.float8_pass_by_value = strstr(p, "by value") != NULL;
got_float8_pass_by_value = true;
}
@@ -305,14 +340,14 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
/* skip leading spaces and remove trailing newline */
p += strspn(p, " ");
if (strlen(p) > 0 && *(p + strlen(p) - 1) == '\n')
*(p + strlen(p) - 1) = '\0';
- cluster->controldata.lc_collate = pg_strdup(ctx, p);
+ cluster->controldata.lc_collate = pg_strdup(p);
}
/* In pre-8.4 only */
else if ((p = strstr(bufin, "LC_CTYPE:")) != NULL)
@@ -320,41 +355,42 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
p = strchr(p, ':');
if (p == NULL || strlen(p) <= 1)
- pg_log(ctx, PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
+ pg_log(PG_FATAL, "%d: controldata retrieval problem\n", __LINE__);
p++; /* removing ':' char */
/* skip leading spaces and remove trailing newline */
p += strspn(p, " ");
if (strlen(p) > 0 && *(p + strlen(p) - 1) == '\n')
*(p + strlen(p) - 1) = '\0';
- cluster->controldata.lc_ctype = pg_strdup(ctx, p);
+ cluster->controldata.lc_ctype = pg_strdup(p);
}
}
if (output)
pclose(output);
- /* restore LANG */
- if (lang)
- {
-#ifndef WIN32
- char *envstr = (char *) pg_malloc(ctx, strlen(lang) + 6);
-
- sprintf(envstr, "LANG=%s", lang);
- putenv(envstr);
-#else
- SetEnvironmentVariableA("LANG", lang);
-#endif
- pg_free(lang);
- }
- else
- {
-#ifndef WIN32
- unsetenv("LANG");
-#else
- SetEnvironmentVariableA("LANG", "");
-#endif
- }
+ /*
+ * Restore environment variables
+ */
+ pg_putenv("LC_COLLATE", lc_collate);
+ pg_putenv("LC_CTYPE", lc_ctype);
+ pg_putenv("LC_MONETARY", lc_monetary);
+ pg_putenv("LC_NUMERIC", lc_numeric);
+ pg_putenv("LC_TIME", lc_time);
+ pg_putenv("LANG", lang);
+ pg_putenv("LANGUAGE", language);
+ pg_putenv("LC_ALL", lc_all);
+ pg_putenv("LC_MESSAGES", lc_messages);
+
+ pg_free(lc_collate);
+ pg_free(lc_ctype);
+ pg_free(lc_monetary);
+ pg_free(lc_numeric);
+ pg_free(lc_time);
+ pg_free(lang);
+ pg_free(language);
+ pg_free(lc_all);
+ pg_free(lc_messages);
/* verify that we got all the mandatory pg_control data */
if (!got_xid || !got_oid ||
@@ -365,56 +401,56 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
!got_walseg || !got_ident || !got_index || !got_toast ||
!got_date_is_int || !got_float8_pass_by_value)
{
- pg_log(ctx, PG_REPORT,
+ pg_log(PG_REPORT,
"Some required control information is missing; cannot find:\n");
if (!got_xid)
- pg_log(ctx, PG_REPORT, " checkpoint next XID\n");
+ pg_log(PG_REPORT, " checkpoint next XID\n");
if (!got_oid)
- pg_log(ctx, PG_REPORT, " latest checkpoint next OID\n");
+ pg_log(PG_REPORT, " latest checkpoint next OID\n");
if (!live_check && !got_log_id)
- pg_log(ctx, PG_REPORT, " first log file ID after reset\n");
+ pg_log(PG_REPORT, " first log file ID after reset\n");
if (!live_check && !got_log_seg)
- pg_log(ctx, PG_REPORT, " first log file segment after reset\n");
+ pg_log(PG_REPORT, " first log file segment after reset\n");
if (!got_tli)
- pg_log(ctx, PG_REPORT, " latest checkpoint timeline ID\n");
+ pg_log(PG_REPORT, " latest checkpoint timeline ID\n");
if (!got_align)
- pg_log(ctx, PG_REPORT, " maximum alignment\n");
+ pg_log(PG_REPORT, " maximum alignment\n");
if (!got_blocksz)
- pg_log(ctx, PG_REPORT, " block size\n");
+ pg_log(PG_REPORT, " block size\n");
if (!got_largesz)
- pg_log(ctx, PG_REPORT, " large relation segment size\n");
+ pg_log(PG_REPORT, " large relation segment size\n");
if (!got_walsz)
- pg_log(ctx, PG_REPORT, " WAL block size\n");
+ pg_log(PG_REPORT, " WAL block size\n");
if (!got_walseg)
- pg_log(ctx, PG_REPORT, " WAL segment size\n");
+ pg_log(PG_REPORT, " WAL segment size\n");
if (!got_ident)
- pg_log(ctx, PG_REPORT, " maximum identifier length\n");
+ pg_log(PG_REPORT, " maximum identifier length\n");
if (!got_index)
- pg_log(ctx, PG_REPORT, " maximum number of indexed columns\n");
+ pg_log(PG_REPORT, " maximum number of indexed columns\n");
if (!got_toast)
- pg_log(ctx, PG_REPORT, " maximum TOAST chunk size\n");
+ pg_log(PG_REPORT, " maximum TOAST chunk size\n");
if (!got_date_is_int)
- pg_log(ctx, PG_REPORT, " dates/times are integers?\n");
+ pg_log(PG_REPORT, " dates/times are integers?\n");
/* value added in Postgres 8.4 */
if (!got_float8_pass_by_value)
- pg_log(ctx, PG_REPORT, " float8 argument passing method\n");
+ pg_log(PG_REPORT, " float8 argument passing method\n");
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"Unable to continue without required control information, terminating\n");
}
}
@@ -426,51 +462,50 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check)
* check to make sure the control data settings are compatible
*/
void
-check_control_data(migratorContext *ctx, ControlData *oldctrl,
+check_control_data(ControlData *oldctrl,
ControlData *newctrl)
{
if (oldctrl->align == 0 || oldctrl->align != newctrl->align)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata alignments are invalid or do not match\n");
if (oldctrl->blocksz == 0 || oldctrl->blocksz != newctrl->blocksz)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata block sizes are invalid or do not match\n");
if (oldctrl->largesz == 0 || oldctrl->largesz != newctrl->largesz)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata maximum relation segement sizes are invalid or do not match\n");
if (oldctrl->walsz == 0 || oldctrl->walsz != newctrl->walsz)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata WAL block sizes are invalid or do not match\n");
if (oldctrl->walseg == 0 || oldctrl->walseg != newctrl->walseg)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata WAL segment sizes are invalid or do not match\n");
if (oldctrl->ident == 0 || oldctrl->ident != newctrl->ident)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata maximum identifier lengths are invalid or do not match\n");
if (oldctrl->index == 0 || oldctrl->index != newctrl->index)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata maximum indexed columns are invalid or do not match\n");
if (oldctrl->toast == 0 || oldctrl->toast != newctrl->toast)
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match\n");
if (oldctrl->date_is_int != newctrl->date_is_int)
{
- pg_log(ctx, PG_WARNING,
+ pg_log(PG_WARNING,
"\nOld and new pg_controldata date/time storage types do not match.\n");
/*
- * This is a common 8.3 -> 8.4 migration problem, so we are more
- * verboase
+ * This is a common 8.3 -> 8.4 upgrade problem, so we are more verbose
*/
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"You will need to rebuild the new server with configure\n"
"--disable-integer-datetimes or get server binaries built\n"
"with those options.\n");
@@ -479,16 +514,16 @@ check_control_data(migratorContext *ctx, ControlData *oldctrl,
void
-rename_old_pg_control(migratorContext *ctx)
+rename_old_pg_control(void)
{
char old_path[MAXPGPATH],
new_path[MAXPGPATH];
- prep_status(ctx, "Adding \".old\" suffix to old global/pg_control");
+ prep_status("Adding \".old\" suffix to old global/pg_control");
- snprintf(old_path, sizeof(old_path), "%s/global/pg_control", ctx->old.pgdata);
- snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", ctx->old.pgdata);
+ snprintf(old_path, sizeof(old_path), "%s/global/pg_control", old_cluster.pgdata);
+ snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", old_cluster.pgdata);
if (pg_mv_file(old_path, new_path) != 0)
- pg_log(ctx, PG_FATAL, "Unable to rename %s to %s.\n", old_path, new_path);
- check_ok(ctx);
+ pg_log(PG_FATAL, "Unable to rename %s to %s.\n", old_path, new_path);
+ check_ok();
}
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
index 3a2ded629c..aba95f44c9 100644
--- a/contrib/pg_upgrade/dump.c
+++ b/contrib/pg_upgrade/dump.c
@@ -3,29 +3,28 @@
*
* dump functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/dump.c,v 1.7 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/dump.c
*/
#include "pg_upgrade.h"
-
void
-generate_old_dump(migratorContext *ctx)
+generate_old_dump(void)
{
/* run new pg_dumpall binary */
- prep_status(ctx, "Creating catalog dump");
+ prep_status("Creating catalog dump");
/*
* --binary-upgrade records the width of dropped columns in pg_class, and
* restores the frozenid's for databases and relations.
*/
- exec_prog(ctx, true,
+ exec_prog(true,
SYSTEMQUOTE "\"%s/pg_dumpall\" --port %d --username \"%s\" "
"--schema-only --binary-upgrade > \"%s/" ALL_DUMP_FILE "\""
- SYSTEMQUOTE, ctx->new.bindir, ctx->old.port, ctx->user, ctx->cwd);
- check_ok(ctx);
+ SYSTEMQUOTE, new_cluster.bindir, old_cluster.port, os_info.user, os_info.cwd);
+ check_ok();
}
@@ -34,7 +33,7 @@ generate_old_dump(migratorContext *ctx)
*
* This function splits pg_dumpall output into global values and
* database creation, and per-db schemas. This allows us to create
- * the toast place holders between restoring these two parts of the
+ * the support functions between restoring these two parts of the
* dump. We split on the first "\connect " after a CREATE ROLE
* username match; this is where the per-db restore starts.
*
@@ -42,7 +41,7 @@ generate_old_dump(migratorContext *ctx)
* an error during restore
*/
void
-split_old_dump(migratorContext *ctx)
+split_old_dump(void)
{
FILE *all_dump,
*globals_dump,
@@ -55,22 +54,22 @@ split_old_dump(migratorContext *ctx)
char filename[MAXPGPATH];
bool suppressed_username = false;
- snprintf(filename, sizeof(filename), "%s/%s", ctx->cwd, ALL_DUMP_FILE);
+ snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ALL_DUMP_FILE);
if ((all_dump = fopen(filename, "r")) == NULL)
- pg_log(ctx, PG_FATAL, "Cannot open dump file %s\n", filename);
- snprintf(filename, sizeof(filename), "%s/%s", ctx->cwd, GLOBALS_DUMP_FILE);
+ pg_log(PG_FATAL, "Cannot open dump file %s\n", filename);
+ snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, GLOBALS_DUMP_FILE);
if ((globals_dump = fopen(filename, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Cannot write to dump file %s\n", filename);
- snprintf(filename, sizeof(filename), "%s/%s", ctx->cwd, DB_DUMP_FILE);
+ pg_log(PG_FATAL, "Cannot write to dump file %s\n", filename);
+ snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, DB_DUMP_FILE);
if ((db_dump = fopen(filename, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Cannot write to dump file %s\n", filename);
+ pg_log(PG_FATAL, "Cannot write to dump file %s\n", filename);
current_output = globals_dump;
/* patterns used to prevent our own username from being recreated */
snprintf(create_role_str, sizeof(create_role_str),
- "CREATE ROLE %s;", ctx->user);
+ "CREATE ROLE %s;", os_info.user);
snprintf(create_role_str_quote, sizeof(create_role_str_quote),
- "CREATE ROLE %s;", quote_identifier(ctx, ctx->user));
+ "CREATE ROLE %s;", quote_identifier(os_info.user));
while (fgets(line, sizeof(line), all_dump) != NULL)
{
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 88a2129e89..b7d82663ff 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -3,20 +3,19 @@
*
* execution functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/exec.c,v 1.8 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/exec.c
*/
#include "pg_upgrade.h"
#include <fcntl.h>
-#include <grp.h>
+#include <unistd.h>
-static void checkBinDir(migratorContext *ctx, ClusterInfo *cluster);
-static int check_exec(migratorContext *ctx, const char *dir, const char *cmdName);
-static const char *validate_exec(const char *path);
-static int check_data_dir(migratorContext *ctx, const char *pg_data);
+static void check_data_dir(const char *pg_data);
+static void check_bin_dir(ClusterInfo *cluster);
+static void validate_exec(const char *dir, const char *cmdName);
/*
@@ -30,7 +29,7 @@ static int check_data_dir(migratorContext *ctx, const char *pg_data);
* instead of returning should an error occur.
*/
int
-exec_prog(migratorContext *ctx, bool throw_error, const char *fmt,...)
+exec_prog(bool throw_error, const char *fmt,...)
{
va_list args;
int result;
@@ -40,14 +39,14 @@ exec_prog(migratorContext *ctx, bool throw_error, const char *fmt,...)
vsnprintf(cmd, MAXPGPATH, fmt, args);
va_end(args);
- pg_log(ctx, PG_INFO, "%s\n", cmd);
+ pg_log(PG_INFO, "%s\n", cmd);
result = system(cmd);
if (result != 0)
{
- pg_log(ctx, throw_error ? PG_FATAL : PG_INFO,
- "\nThere were problems executing %s\n", cmd);
+ pg_log(throw_error ? PG_FATAL : PG_INFO,
+ "There were problems executing %s\n", cmd);
return 1;
}
@@ -56,56 +55,13 @@ exec_prog(migratorContext *ctx, bool throw_error, const char *fmt,...)
/*
- * verify_directories()
- *
- * does all the hectic work of verifying directories and executables
- * of old and new server.
- *
- * NOTE: May update the values of all parameters
- */
-void
-verify_directories(migratorContext *ctx)
-{
- prep_status(ctx, "Checking old data directory (%s)", ctx->old.pgdata);
- if (check_data_dir(ctx, ctx->old.pgdata) != 0)
- pg_log(ctx, PG_FATAL, "Failed\n");
- checkBinDir(ctx, &ctx->old);
- check_ok(ctx);
-
- prep_status(ctx, "Checking new data directory (%s)", ctx->new.pgdata);
- if (check_data_dir(ctx, ctx->new.pgdata) != 0)
- pg_log(ctx, PG_FATAL, "Failed\n");
- checkBinDir(ctx, &ctx->new);
- check_ok(ctx);
-}
-
-
-/*
- * checkBinDir()
- *
- * This function searches for the executables that we expect to find
- * in the binaries directory. If we find that a required executable
- * is missing (or secured against us), we display an error message and
- * exit().
- */
-static void
-checkBinDir(migratorContext *ctx, ClusterInfo *cluster)
-{
- check_exec(ctx, cluster->bindir, "postgres");
- check_exec(ctx, cluster->bindir, "psql");
- check_exec(ctx, cluster->bindir, "pg_ctl");
- check_exec(ctx, cluster->bindir, "pg_dumpall");
-}
-
-
-/*
* is_server_running()
*
* checks whether postmaster on the given data directory is running or not.
* The check is performed by looking for the existence of postmaster.pid file.
*/
bool
-is_server_running(migratorContext *ctx, const char *datadir)
+is_server_running(const char *datadir)
{
char path[MAXPGPATH];
int fd;
@@ -114,8 +70,9 @@ is_server_running(migratorContext *ctx, const char *datadir)
if ((fd = open(path, O_RDONLY, 0)) < 0)
{
- if (errno != ENOENT)
- pg_log(ctx, PG_FATAL, "\ncould not open file \"%s\" for reading\n",
+ /* ENOTDIR means we will throw a more useful error later */
+ if (errno != ENOENT && errno != ENOTDIR)
+ pg_log(PG_FATAL, "could not open file \"%s\" for reading\n",
path);
return false;
@@ -127,28 +84,111 @@ is_server_running(migratorContext *ctx, const char *datadir)
/*
- * check_exec()
+ * verify_directories()
+ *
+ * does all the hectic work of verifying directories and executables
+ * of old and new server.
*
- * Checks whether either of the two command names (cmdName and alternative)
- * appears to be an executable (in the given directory). If dir/cmdName is
- * an executable, this function returns 1. If dir/alternative is an
- * executable, this function returns 2. If neither of the given names is
- * a valid executable, this function returns 0 to indicated failure.
+ * NOTE: May update the values of all parameters
*/
-static int
-check_exec(migratorContext *ctx, const char *dir, const char *cmdName)
+void
+verify_directories(void)
{
- char path[MAXPGPATH];
- const char *errMsg;
- snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
+ prep_status("Checking current, bin, and data directories");
- if ((errMsg = validate_exec(path)) == NULL)
- return 1; /* 1 -> first alternative OK */
- else
- pg_log(ctx, PG_FATAL, "check for %s failed - %s\n", cmdName, errMsg);
+ if (access(".", R_OK | W_OK
+#ifndef WIN32
- return 0; /* 0 -> neither alternative is acceptable */
+ /*
+ * Do a directory execute check only on Unix because execute permission on
+ * NTFS means "can execute scripts", which we don't care about. Also, X_OK
+ * is not defined in the Windows API.
+ */
+ | X_OK
+#endif
+ ) != 0)
+ pg_log(PG_FATAL,
+ "You must have read and write access in the current directory.\n");
+
+ check_bin_dir(&old_cluster);
+ check_data_dir(old_cluster.pgdata);
+ check_bin_dir(&new_cluster);
+ check_data_dir(new_cluster.pgdata);
+ check_ok();
+}
+
+
+/*
+ * check_data_dir()
+ *
+ * This function validates the given cluster directory - we search for a
+ * small set of subdirectories that we expect to find in a valid $PGDATA
+ * directory. If any of the subdirectories are missing (or secured against
+ * us) we display an error message and exit()
+ *
+ */
+static void
+check_data_dir(const char *pg_data)
+{
+ char subDirName[MAXPGPATH];
+ int subdirnum;
+
+ /* start check with top-most directory */
+ const char *requiredSubdirs[] = {"", "base", "global", "pg_clog",
+ "pg_multixact", "pg_subtrans", "pg_tblspc", "pg_twophase",
+ "pg_xlog"};
+
+ for (subdirnum = 0;
+ subdirnum < sizeof(requiredSubdirs) / sizeof(requiredSubdirs[0]);
+ ++subdirnum)
+ {
+ struct stat statBuf;
+
+ snprintf(subDirName, sizeof(subDirName), "%s/%s", pg_data,
+ requiredSubdirs[subdirnum]);
+
+ if (stat(subDirName, &statBuf) != 0)
+ report_status(PG_FATAL, "check for %s failed: %s\n",
+ subDirName, getErrorText(errno));
+ else if (!S_ISDIR(statBuf.st_mode))
+ report_status(PG_FATAL, "%s is not a directory\n",
+ subDirName);
+ }
+}
+
+
+/*
+ * check_bin_dir()
+ *
+ * This function searches for the executables that we expect to find
+ * in the binaries directory. If we find that a required executable
+ * is missing (or secured against us), we display an error message and
+ * exit().
+ */
+static void
+check_bin_dir(ClusterInfo *cluster)
+{
+ struct stat statBuf;
+
+ /* check bindir */
+ if (stat(cluster->bindir, &statBuf) != 0)
+ report_status(PG_FATAL, "check for %s failed: %s\n",
+ cluster->bindir, getErrorText(errno));
+ else if (!S_ISDIR(statBuf.st_mode))
+ report_status(PG_FATAL, "%s is not a directory\n",
+ cluster->bindir);
+
+ validate_exec(cluster->bindir, "postgres");
+ validate_exec(cluster->bindir, "pg_ctl");
+ validate_exec(cluster->bindir, "pg_resetxlog");
+ if (cluster == &new_cluster)
+ {
+ /* these are only needed in the new cluster */
+ validate_exec(cluster->bindir, "pg_config");
+ validate_exec(cluster->bindir, "psql");
+ validate_exec(cluster->bindir, "pg_dumpall");
+ }
}
@@ -156,158 +196,49 @@ check_exec(migratorContext *ctx, const char *dir, const char *cmdName)
* validate_exec()
*
* validate "path" as an executable file
- * returns 0 if the file is found and no error is encountered.
- * -1 if the regular file "path" does not exist or cannot be executed.
- * -2 if the file is otherwise valid but cannot be read.
*/
-static const char *
-validate_exec(const char *path)
+static void
+validate_exec(const char *dir, const char *cmdName)
{
+ char path[MAXPGPATH];
struct stat buf;
-#ifndef WIN32
- uid_t euid;
- struct group *gp;
- struct passwd *pwp;
- int in_grp = 0;
-#else
- char path_exe[MAXPGPATH + sizeof(EXE_EXT) - 1];
-#endif
+ snprintf(path, sizeof(path), "%s/%s", dir, cmdName);
#ifdef WIN32
- /* Win32 requires a .exe suffix for stat() */
-
- if (strlen(path) >= strlen(EXE_EXT) &&
+ /* Windows requires a .exe suffix for stat() */
+ if (strlen(path) <= strlen(EXE_EXT) ||
pg_strcasecmp(path + strlen(path) - strlen(EXE_EXT), EXE_EXT) != 0)
- {
- strcpy(path_exe, path);
- strcat(path_exe, EXE_EXT);
- path = path_exe;
- }
+ strlcat(path, EXE_EXT, sizeof(path));
#endif
/*
* Ensure that the file exists and is a regular file.
*/
if (stat(path, &buf) < 0)
- return getErrorText(errno);
-
- if ((buf.st_mode & S_IFMT) != S_IFREG)
- return "not an executable file";
-
- /*
- * Ensure that we are using an authorized executable.
- */
+ pg_log(PG_FATAL, "check for %s failed - %s\n",
+ path, getErrorText(errno));
+ else if (!S_ISREG(buf.st_mode))
+ pg_log(PG_FATAL, "check for %s failed - not an executable file\n",
+ path);
/*
* Ensure that the file is both executable and readable (required for
* dynamic loading).
*/
#ifndef WIN32
- euid = geteuid();
-
- /* If owned by us, just check owner bits */
- if (euid == buf.st_uid)
- {
- if ((buf.st_mode & S_IRUSR) == 0)
- return "can't read file (permission denied)";
- if ((buf.st_mode & S_IXUSR) == 0)
- return "can't execute (permission denied)";
- return NULL;
- }
-
- /* OK, check group bits */
- pwp = getpwuid(euid); /* not thread-safe */
-
- if (pwp)
- {
- if (pwp->pw_gid == buf.st_gid) /* my primary group? */
- ++in_grp;
- else if (pwp->pw_name &&
- (gp = getgrgid(buf.st_gid)) != NULL &&
- /* not thread-safe */ gp->gr_mem != NULL)
- {
- /* try list of member groups */
- int i;
-
- for (i = 0; gp->gr_mem[i]; ++i)
- {
- if (!strcmp(gp->gr_mem[i], pwp->pw_name))
- {
- ++in_grp;
- break;
- }
- }
- }
-
- if (in_grp)
- {
- if ((buf.st_mode & S_IRGRP) == 0)
- return "can't read file (permission denied)";
- if ((buf.st_mode & S_IXGRP) == 0)
- return "can't execute (permission denied)";
- return NULL;
- }
- }
-
- /* Check "other" bits */
- if ((buf.st_mode & S_IROTH) == 0)
- return "can't read file (permission denied)";
- if ((buf.st_mode & S_IXOTH) == 0)
- return "can't execute (permission denied)";
- return NULL;
+ if (access(path, R_OK) != 0)
#else
if ((buf.st_mode & S_IRUSR) == 0)
- return "can't read file (permission denied)";
- if ((buf.st_mode & S_IXUSR) == 0)
- return "can't execute (permission denied)";
- return NULL;
#endif
-}
-
+ pg_log(PG_FATAL, "check for %s failed - cannot read file (permission denied)\n",
+ path);
-/*
- * check_data_dir()
- *
- * This function validates the given cluster directory - we search for a
- * small set of subdirectories that we expect to find in a valid $PGDATA
- * directory. If any of the subdirectories are missing (or secured against
- * us) we display an error message and exit()
- *
- */
-static int
-check_data_dir(migratorContext *ctx, const char *pg_data)
-{
- char subDirName[MAXPGPATH];
- const char *requiredSubdirs[] = {"base", "global", "pg_clog",
- "pg_multixact", "pg_subtrans",
- "pg_tblspc", "pg_twophase", "pg_xlog"};
- bool fail = false;
- int subdirnum;
-
- for (subdirnum = 0; subdirnum < sizeof(requiredSubdirs) / sizeof(requiredSubdirs[0]); ++subdirnum)
- {
- struct stat statBuf;
-
- snprintf(subDirName, sizeof(subDirName), "%s/%s", pg_data,
- requiredSubdirs[subdirnum]);
-
- if ((stat(subDirName, &statBuf)) != 0)
- {
- report_status(ctx, PG_WARNING, "check for %s warning: %s",
- requiredSubdirs[subdirnum], getErrorText(errno));
- fail = true;
- }
- else
- {
- if (!S_ISDIR(statBuf.st_mode))
- {
- report_status(ctx, PG_WARNING, "%s is not a directory",
- requiredSubdirs[subdirnum]);
- fail = true;
- }
- }
- }
-
- return (fail) ? -1 : 0;
+#ifndef WIN32
+ if (access(path, X_OK) != 0)
+#else
+ if ((buf.st_mode & S_IXUSR) == 0)
+#endif
+ pg_log(PG_FATAL, "check for %s failed - cannot execute (permission denied)\n",
+ path);
}
diff --git a/contrib/pg_upgrade/file.c b/contrib/pg_upgrade/file.c
index 7ddaddafd6..a7e40090e2 100644
--- a/contrib/pg_upgrade/file.c
+++ b/contrib/pg_upgrade/file.c
@@ -3,8 +3,8 @@
*
* file system operations
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/file.c,v 1.13 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/file.c
*/
#include "pg_upgrade.h"
@@ -12,17 +12,15 @@
#include <fcntl.h>
-static int copy_file(const char *fromfile, const char *tofile, bool force);
-#ifdef WIN32
+#ifndef WIN32
+static int copy_file(const char *fromfile, const char *tofile, bool force);
+#else
static int win32_pghardlink(const char *src, const char *dst);
#endif
-#ifdef NOT_USED
-static int copy_dir(const char *from, const char *to, bool force);
-#endif
#ifndef HAVE_SCANDIR
-static int pg_scandir_internal(migratorContext *ctx, const char *dirname,
+static int pg_scandir_internal(const char *dirname,
struct dirent *** namelist,
int (*selector) (const struct dirent *));
#endif
@@ -35,7 +33,7 @@ static int pg_scandir_internal(migratorContext *ctx, const char *dirname,
* uses that pageConverter to do a page-by-page conversion.
*/
const char *
-copyAndUpdateFile(migratorContext *ctx, pageCnvCtx *pageConverter,
+copyAndUpdateFile(pageCnvCtx *pageConverter,
const char *src, const char *dst, bool force)
{
if (pageConverter == NULL)
@@ -74,7 +72,10 @@ copyAndUpdateFile(migratorContext *ctx, pageCnvCtx *pageConverter,
return "can't open source file";
if ((dstfd = open(dst, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0)
+ {
+ close(src_fd);
return "can't create destination file";
+ }
while ((bytesRead = read(src_fd, buf, BLCKSZ)) == BLCKSZ)
{
@@ -113,7 +114,7 @@ copyAndUpdateFile(migratorContext *ctx, pageCnvCtx *pageConverter,
* instead of copying the data from the old cluster to the new cluster.
*/
const char *
-linkAndUpdateFile(migratorContext *ctx, pageCnvCtx *pageConverter,
+linkAndUpdateFile(pageCnvCtx *pageConverter,
const char *src, const char *dst)
{
if (pageConverter != NULL)
@@ -126,6 +127,7 @@ linkAndUpdateFile(migratorContext *ctx, pageCnvCtx *pageConverter,
}
+#ifndef WIN32
static int
copy_file(const char *srcfile, const char *dstfile, bool force)
{
@@ -170,6 +172,8 @@ copy_file(const char *srcfile, const char *dstfile, bool force)
if (nbytes < 0)
{
+ int save_errno = errno;
+
if (buffer != NULL)
free(buffer);
@@ -179,6 +183,7 @@ copy_file(const char *srcfile, const char *dstfile, bool force)
if (dest_fd != 0)
close(dest_fd);
+ errno = save_errno;
return -1;
}
@@ -190,8 +195,7 @@ copy_file(const char *srcfile, const char *dstfile, bool force)
if (write(dest_fd, buffer, nbytes) != nbytes)
{
/* if write didn't set errno, assume problem is no disk space */
- if (errno == 0)
- errno = ENOSPC;
+ int save_errno = errno ? errno : ENOSPC;
if (buffer != NULL)
free(buffer);
@@ -202,6 +206,7 @@ copy_file(const char *srcfile, const char *dstfile, bool force)
if (dest_fd != 0)
close(dest_fd);
+ errno = save_errno;
return -1;
}
}
@@ -217,6 +222,7 @@ copy_file(const char *srcfile, const char *dstfile, bool force)
return 1;
}
+#endif
/*
@@ -225,12 +231,12 @@ copy_file(const char *srcfile, const char *dstfile, bool force)
* Wrapper for portable scandir functionality
*/
int
-pg_scandir(migratorContext *ctx, const char *dirname,
+pg_scandir(const char *dirname,
struct dirent *** namelist,
int (*selector) (const struct dirent *))
{
#ifndef HAVE_SCANDIR
- return pg_scandir_internal(ctx, dirname, namelist, selector);
+ return pg_scandir_internal(dirname, namelist, selector);
/*
* scandir() is originally from BSD 4.3, which had the third argument as
@@ -271,7 +277,7 @@ pg_scandir(migratorContext *ctx, const char *dirname,
* .2, etc.) and should therefore be invoked a small number of times.
*/
static int
-pg_scandir_internal(migratorContext *ctx, const char *dirname,
+pg_scandir_internal(const char *dirname,
struct dirent *** namelist, int (*selector) (const struct dirent *))
{
DIR *dirdesc;
@@ -281,7 +287,7 @@ pg_scandir_internal(migratorContext *ctx, const char *dirname,
size_t entrysize;
if ((dirdesc = opendir(dirname)) == NULL)
- pg_log(ctx, PG_FATAL, "Could not open directory \"%s\": %m\n", dirname);
+ pg_log(PG_FATAL, "could not open directory \"%s\": %m\n", dirname);
*namelist = NULL;
@@ -296,7 +302,10 @@ pg_scandir_internal(migratorContext *ctx, const char *dirname,
(size_t) ((name_num + 1) * sizeof(struct dirent *)));
if (*namelist == NULL)
+ {
+ closedir(dirdesc);
return -1;
+ }
entrysize = sizeof(struct dirent) - sizeof(direntry->d_name) +
strlen(direntry->d_name) + 1;
@@ -304,7 +313,10 @@ pg_scandir_internal(migratorContext *ctx, const char *dirname,
(*namelist)[name_num] = (struct dirent *) malloc(entrysize);
if ((*namelist)[name_num] == NULL)
+ {
+ closedir(dirdesc);
return -1;
+ }
memcpy((*namelist)[name_num], direntry, entrysize);
@@ -336,18 +348,18 @@ dir_matching_filenames(const struct dirent * scan_ent)
void
-check_hard_link(migratorContext *ctx)
+check_hard_link(void)
{
char existing_file[MAXPGPATH];
char new_link_file[MAXPGPATH];
- snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", ctx->old.pgdata);
- snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", ctx->new.pgdata);
+ snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
+ snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
unlink(new_link_file); /* might fail */
if (pg_link_file(existing_file, new_link_file) == -1)
{
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"Could not create hard link between old and new data directories: %s\n"
"In link mode the old and new data directories must be on the same file system volume.\n",
getErrorText(errno));
@@ -368,98 +380,5 @@ win32_pghardlink(const char *src, const char *dst)
else
return 0;
}
-#endif
-
-
-#ifdef NOT_USED
-/*
- * copy_dir()
- *
- * Copies either a directory or a single file within a directory. If the
- * source argument names a directory, we recursively copy that directory,
- * otherwise we copy a single file.
- */
-static int
-copy_dir(const char *src, const char *dst, bool force)
-{
- DIR *srcdir;
- struct dirent *de = NULL;
- struct stat fst;
-
- if (src == NULL || dst == NULL)
- return -1;
-
- /*
- * Try to open the source directory - if it turns out not to be a
- * directory, assume that it's a file and copy that instead.
- */
- if ((srcdir = opendir(src)) == NULL)
- {
- if (errno == ENOTDIR)
- return copy_file(src, dst, true);
- return -1;
- }
-
- if (mkdir(dst, S_IRWXU) != 0)
- {
- /*
- * ignore directory already exist error
- */
- if (errno != EEXIST)
- return -1;
- }
-
- while ((de = readdir(srcdir)) != NULL)
- {
- char src_file[MAXPGPATH];
- char dest_file[MAXPGPATH];
-
- if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
- continue;
-
- memset(src_file, 0, sizeof(src_file));
- memset(dest_file, 0, sizeof(dest_file));
-
- snprintf(src_file, sizeof(src_file), "%s/%s", src, de->d_name);
- snprintf(dest_file, sizeof(dest_file), "%s/%s", dst, de->d_name);
-
- if (stat(src_file, &fst) < 0)
- {
- if (srcdir != NULL)
- {
- closedir(srcdir);
- srcdir = NULL;
- }
-
- return -1;
- }
-
- if (fst.st_mode & S_IFDIR)
- {
- /* recurse to handle subdirectories */
- if (force)
- copy_dir(src_file, dest_file, true);
- }
- else if (fst.st_mode & S_IFREG)
- {
- if ((copy_file(src_file, dest_file, 1)) == -1)
- {
- if (srcdir != NULL)
- {
- closedir(srcdir);
- srcdir = NULL;
- }
- return -1;
- }
- }
- }
-
- if (srcdir != NULL)
- {
- closedir(srcdir);
- srcdir = NULL;
- }
- return 1;
-}
#endif
diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
index 3187506df0..322014cd23 100644
--- a/contrib/pg_upgrade/function.c
+++ b/contrib/pg_upgrade/function.c
@@ -3,8 +3,8 @@
*
* server-side function support
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/function.c,v 1.6 2010/07/03 16:33:14 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/function.c
*/
#include "pg_upgrade.h"
@@ -13,104 +13,107 @@
/*
- * install_support_functions()
+ * install_support_functions_in_new_db()
*
* pg_upgrade requires some support functions that enable it to modify
* backend behavior.
*/
void
-install_support_functions(migratorContext *ctx)
+install_support_functions_in_new_db(const char *db_name)
{
- int dbnum;
-
- prep_status(ctx, "Adding support functions to new cluster");
-
- for (dbnum = 0; dbnum < ctx->new.dbarr.ndbs; dbnum++)
- {
- DbInfo *newdb = &ctx->new.dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, newdb->db_name, CLUSTER_NEW);
+ PGconn *conn = connectToServer(&new_cluster, db_name);
- /* suppress NOTICE of dropped objects */
- PQclear(executeQueryOrDie(ctx, conn,
- "SET client_min_messages = warning;"));
- PQclear(executeQueryOrDie(ctx, conn,
+ /* suppress NOTICE of dropped objects */
+ PQclear(executeQueryOrDie(conn,
+ "SET client_min_messages = warning;"));
+ PQclear(executeQueryOrDie(conn,
"DROP SCHEMA IF EXISTS binary_upgrade CASCADE;"));
- PQclear(executeQueryOrDie(ctx, conn,
- "RESET client_min_messages;"));
-
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE SCHEMA binary_upgrade;"));
-
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE OR REPLACE FUNCTION "
- " binary_upgrade.set_next_pg_type_oid(OID) "
- "RETURNS VOID "
- "AS '$libdir/pg_upgrade_support' "
- "LANGUAGE C STRICT;"));
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE OR REPLACE FUNCTION "
- " binary_upgrade.set_next_pg_type_array_oid(OID) "
- "RETURNS VOID "
- "AS '$libdir/pg_upgrade_support' "
- "LANGUAGE C STRICT;"));
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE OR REPLACE FUNCTION "
- " binary_upgrade.set_next_pg_type_toast_oid(OID) "
- "RETURNS VOID "
- "AS '$libdir/pg_upgrade_support' "
- "LANGUAGE C STRICT;"));
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE OR REPLACE FUNCTION "
- " binary_upgrade.set_next_heap_relfilenode(OID) "
- "RETURNS VOID "
- "AS '$libdir/pg_upgrade_support' "
- "LANGUAGE C STRICT;"));
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE OR REPLACE FUNCTION "
- " binary_upgrade.set_next_toast_relfilenode(OID) "
- "RETURNS VOID "
- "AS '$libdir/pg_upgrade_support' "
- "LANGUAGE C STRICT;"));
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE OR REPLACE FUNCTION "
- " binary_upgrade.set_next_index_relfilenode(OID) "
- "RETURNS VOID "
- "AS '$libdir/pg_upgrade_support' "
- "LANGUAGE C STRICT;"));
- PQclear(executeQueryOrDie(ctx, conn,
- "CREATE OR REPLACE FUNCTION "
- " binary_upgrade.add_pg_enum_label(OID, OID, NAME) "
- "RETURNS VOID "
- "AS '$libdir/pg_upgrade_support' "
- "LANGUAGE C STRICT;"));
- PQfinish(conn);
- }
- check_ok(ctx);
+ PQclear(executeQueryOrDie(conn,
+ "RESET client_min_messages;"));
+
+ PQclear(executeQueryOrDie(conn,
+ "CREATE SCHEMA binary_upgrade;"));
+
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_pg_type_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_array_pg_type_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_toast_pg_type_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_heap_pg_class_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_index_pg_class_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_toast_pg_class_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_pg_enum_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.set_next_pg_authid_oid(OID) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C STRICT;"));
+ PQclear(executeQueryOrDie(conn,
+ "CREATE OR REPLACE FUNCTION "
+ "binary_upgrade.create_empty_extension(text, text, bool, text, oid[], text[], text[]) "
+ "RETURNS VOID "
+ "AS '$libdir/pg_upgrade_support' "
+ "LANGUAGE C;"));
+ PQfinish(conn);
}
void
-uninstall_support_functions(migratorContext *ctx)
+uninstall_support_functions_from_new_cluster(void)
{
int dbnum;
- prep_status(ctx, "Removing support functions from new cluster");
+ prep_status("Removing support functions from new cluster");
- for (dbnum = 0; dbnum < ctx->new.dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
{
- DbInfo *newdb = &ctx->new.dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, newdb->db_name, CLUSTER_NEW);
+ DbInfo *new_db = &new_cluster.dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(&new_cluster, new_db->db_name);
/* suppress NOTICE of dropped objects */
- PQclear(executeQueryOrDie(ctx, conn,
+ PQclear(executeQueryOrDie(conn,
"SET client_min_messages = warning;"));
- PQclear(executeQueryOrDie(ctx, conn,
+ PQclear(executeQueryOrDie(conn,
"DROP SCHEMA binary_upgrade CASCADE;"));
- PQclear(executeQueryOrDie(ctx, conn,
+ PQclear(executeQueryOrDie(conn,
"RESET client_min_messages;"));
PQfinish(conn);
}
- check_ok(ctx);
+ check_ok();
}
@@ -121,30 +124,29 @@ uninstall_support_functions(migratorContext *ctx)
* We will later check that they all exist in the new installation.
*/
void
-get_loadable_libraries(migratorContext *ctx)
+get_loadable_libraries(void)
{
- ClusterInfo *active_cluster = &ctx->old;
PGresult **ress;
int totaltups;
int dbnum;
ress = (PGresult **)
- pg_malloc(ctx, active_cluster->dbarr.ndbs * sizeof(PGresult *));
+ pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
totaltups = 0;
/* Fetch all library names, removing duplicates within each DB */
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
{
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, CLUSTER_OLD);
+ DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(&old_cluster, active_db->db_name);
/* Fetch all libraries referenced in this DB */
- ress[dbnum] = executeQueryOrDie(ctx, conn,
+ ress[dbnum] = executeQueryOrDie(conn,
"SELECT DISTINCT probin "
"FROM pg_catalog.pg_proc "
"WHERE prolang = 13 /* C */ AND "
- " probin IS NOT NULL AND "
- " oid >= %u;",
+ "probin IS NOT NULL AND "
+ "oid >= %u;",
FirstNormalObjectId);
totaltups += PQntuples(ress[dbnum]);
@@ -153,9 +155,9 @@ get_loadable_libraries(migratorContext *ctx)
/* Allocate what's certainly enough space */
if (totaltups > 0)
- ctx->libraries = (char **) pg_malloc(ctx, totaltups * sizeof(char *));
+ os_info.libraries = (char **) pg_malloc(totaltups * sizeof(char *));
else
- ctx->libraries = NULL;
+ os_info.libraries = NULL;
/*
* Now remove duplicates across DBs. This is pretty inefficient code, but
@@ -163,7 +165,7 @@ get_loadable_libraries(migratorContext *ctx)
*/
totaltups = 0;
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
{
PGresult *res = ress[dbnum];
int ntups;
@@ -178,20 +180,20 @@ get_loadable_libraries(migratorContext *ctx)
for (n = 0; n < totaltups; n++)
{
- if (strcmp(lib, ctx->libraries[n]) == 0)
+ if (strcmp(lib, os_info.libraries[n]) == 0)
{
dup = true;
break;
}
}
if (!dup)
- ctx->libraries[totaltups++] = pg_strdup(ctx, lib);
+ os_info.libraries[totaltups++] = pg_strdup(lib);
}
PQclear(res);
}
- ctx->num_libraries = totaltups;
+ os_info.num_libraries = totaltups;
pg_free(ress);
}
@@ -205,24 +207,24 @@ get_loadable_libraries(migratorContext *ctx)
* compatibility as well as presence.
*/
void
-check_loadable_libraries(migratorContext *ctx)
+check_loadable_libraries(void)
{
- PGconn *conn = connectToServer(ctx, "template1", CLUSTER_NEW);
+ PGconn *conn = connectToServer(&new_cluster, "template1");
int libnum;
FILE *script = NULL;
bool found = false;
char output_path[MAXPGPATH];
- prep_status(ctx, "Checking for presence of required libraries");
+ prep_status("Checking for presence of required libraries");
snprintf(output_path, sizeof(output_path), "%s/loadable_libraries.txt",
- ctx->cwd);
+ os_info.cwd);
- for (libnum = 0; libnum < ctx->num_libraries; libnum++)
+ for (libnum = 0; libnum < os_info.num_libraries; libnum++)
{
- char *lib = ctx->libraries[libnum];
+ char *lib = os_info.libraries[libnum];
int llen = strlen(lib);
- char *cmd = (char *) pg_malloc(ctx, 8 + 2 * llen + 1);
+ char *cmd = (char *) pg_malloc(8 + 2 * llen + 1);
PGresult *res;
strcpy(cmd, "LOAD '");
@@ -235,7 +237,7 @@ check_loadable_libraries(migratorContext *ctx)
{
found = true;
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n",
+ pg_log(PG_FATAL, "Could not create necessary file: %s\n",
output_path);
fprintf(script, "Failed to load library: %s\n%s\n",
lib,
@@ -251,9 +253,9 @@ check_loadable_libraries(migratorContext *ctx)
if (found)
{
fclose(script);
- pg_log(ctx, PG_REPORT, "fatal\n");
- pg_log(ctx, PG_FATAL,
- "| Your installation uses loadable libraries that are missing\n"
+ pg_log(PG_REPORT, "fatal\n");
+ pg_log(PG_FATAL,
+ "| Your installation references loadable libraries that are missing\n"
"| from the new installation. You can add these libraries to\n"
"| the new installation, or remove the functions using them\n"
"| from the old installation. A list of the problem libraries\n"
@@ -261,5 +263,5 @@ check_loadable_libraries(migratorContext *ctx)
"| \"%s\".\n\n", output_path);
}
else
- check_ok(ctx);
+ check_ok();
}
diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
index dad2a5f8d1..f0cd8e5ede 100644
--- a/contrib/pg_upgrade/info.c
+++ b/contrib/pg_upgrade/info.c
@@ -3,8 +3,8 @@
*
* information support functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/info.c,v 1.11 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/info.c
*/
#include "pg_upgrade.h"
@@ -12,29 +12,15 @@
#include "access/transam.h"
-static void get_db_infos(migratorContext *ctx, DbInfoArr *dbinfos,
- Cluster whichCluster);
-static void dbarr_print(migratorContext *ctx, DbInfoArr *arr,
- Cluster whichCluster);
-static void relarr_print(migratorContext *ctx, RelInfoArr *arr);
-static void get_rel_infos(migratorContext *ctx, const DbInfo *dbinfo,
- RelInfoArr *relarr, Cluster whichCluster);
-static void relarr_free(RelInfoArr *rel_arr);
-static void map_rel(migratorContext *ctx, const RelInfo *oldrel,
- const RelInfo *newrel, const DbInfo *old_db,
- const DbInfo *new_db, const char *olddata,
- const char *newdata, FileNameMap *map);
-static void map_rel_by_id(migratorContext *ctx, Oid oldid, Oid newid,
- const char *old_nspname, const char *old_relname,
- const char *new_nspname, const char *new_relname,
- const char *old_tablespace, const DbInfo *old_db,
- const DbInfo *new_db, const char *olddata,
- const char *newdata, FileNameMap *map);
-static RelInfo *relarr_lookup_reloid(migratorContext *ctx,
- RelInfoArr *rel_arr, Oid oid, Cluster whichCluster);
-static RelInfo *relarr_lookup_rel(migratorContext *ctx, RelInfoArr *rel_arr,
- const char *nspname, const char *relname,
- Cluster whichCluster);
+static void create_rel_filename_map(const char *old_data, const char *new_data,
+ const DbInfo *old_db, const DbInfo *new_db,
+ const RelInfo *old_rel, const RelInfo *new_rel,
+ FileNameMap *map);
+static void get_db_infos(ClusterInfo *cluster);
+static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo);
+static void free_rel_infos(RelInfoArr *rel_arr);
+static void print_db_infos(DbInfoArr *dbinfo);
+static void print_rel_infos(RelInfoArr *arr);
/*
@@ -43,90 +29,48 @@ static RelInfo *relarr_lookup_rel(migratorContext *ctx, RelInfoArr *rel_arr,
* generates database mappings for "old_db" and "new_db". Returns a malloc'ed
* array of mappings. nmaps is a return parameter which refers to the number
* mappings.
- *
- * NOTE: Its the Caller's responsibility to free the returned array.
*/
FileNameMap *
-gen_db_file_maps(migratorContext *ctx, DbInfo *old_db, DbInfo *new_db,
+gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
int *nmaps, const char *old_pgdata, const char *new_pgdata)
{
FileNameMap *maps;
int relnum;
int num_maps = 0;
- maps = (FileNameMap *) pg_malloc(ctx, sizeof(FileNameMap) *
- new_db->rel_arr.nrels);
+ if (old_db->rel_arr.nrels != new_db->rel_arr.nrels)
+ pg_log(PG_FATAL, "old and new databases \"%s\" have a different number of relations\n",
+ old_db->db_name);
- for (relnum = 0; relnum < new_db->rel_arr.nrels; relnum++)
- {
- RelInfo *newrel = &new_db->rel_arr.rels[relnum];
- RelInfo *oldrel;
+ maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) *
+ old_db->rel_arr.nrels);
- /* toast tables are handled by their parent */
- if (strcmp(newrel->nspname, "pg_toast") == 0)
- continue;
+ for (relnum = 0; relnum < old_db->rel_arr.nrels; relnum++)
+ {
+ RelInfo *old_rel = &old_db->rel_arr.rels[relnum];
+ RelInfo *new_rel = &new_db->rel_arr.rels[relnum];
- oldrel = relarr_lookup_rel(ctx, &(old_db->rel_arr), newrel->nspname,
- newrel->relname, CLUSTER_OLD);
-
- map_rel(ctx, oldrel, newrel, old_db, new_db, old_pgdata, new_pgdata,
- maps + num_maps);
- num_maps++;
+ if (old_rel->reloid != new_rel->reloid)
+ pg_log(PG_FATAL, "Mismatch of relation id: database \"%s\", old relid %d, new relid %d\n",
+ old_db->db_name, old_rel->reloid, new_rel->reloid);
/*
- * so much for the mapping of this relation. Now we need a mapping for
- * its corresponding toast relation if any.
+ * In pre-8.4, TOAST table names change during CLUSTER; in >= 8.4
+ * TOAST relation names always use heap table oids, hence we cannot
+ * check relation names when upgrading from pre-8.4.
*/
- if (oldrel->toastrelid > 0)
- {
- RelInfo *new_toast;
- RelInfo *old_toast;
- char new_name[MAXPGPATH];
- char old_name[MAXPGPATH];
-
- /* construct the new and old relnames for the toast relation */
- snprintf(old_name, sizeof(old_name), "pg_toast_%u",
- oldrel->reloid);
- snprintf(new_name, sizeof(new_name), "pg_toast_%u",
- newrel->reloid);
-
- /* look them up in their respective arrays */
- old_toast = relarr_lookup_reloid(ctx, &old_db->rel_arr,
- oldrel->toastrelid, CLUSTER_OLD);
- new_toast = relarr_lookup_rel(ctx, &new_db->rel_arr,
- "pg_toast", new_name, CLUSTER_NEW);
-
- /* finally create a mapping for them */
- map_rel(ctx, old_toast, new_toast, old_db, new_db, old_pgdata, new_pgdata,
- maps + num_maps);
- num_maps++;
-
- /*
- * also need to provide a mapping for the index of this toast
- * relation. The procedure is similar to what we did above for
- * toast relation itself, the only difference being that the
- * relnames need to be appended with _index.
- */
-
- /*
- * construct the new and old relnames for the toast index
- * relations
- */
- snprintf(old_name, sizeof(old_name), "%s_index", old_toast->relname);
- snprintf(new_name, sizeof(new_name), "pg_toast_%u_index",
- newrel->reloid);
-
- /* look them up in their respective arrays */
- old_toast = relarr_lookup_rel(ctx, &old_db->rel_arr,
- "pg_toast", old_name, CLUSTER_OLD);
- new_toast = relarr_lookup_rel(ctx, &new_db->rel_arr,
- "pg_toast", new_name, CLUSTER_NEW);
-
- /* finally create a mapping for them */
- map_rel(ctx, old_toast, new_toast, old_db, new_db, old_pgdata,
- new_pgdata, maps + num_maps);
- num_maps++;
- }
+ if (strcmp(old_rel->nspname, new_rel->nspname) != 0 ||
+ ((GET_MAJOR_VERSION(old_cluster.major_version) >= 804 ||
+ strcmp(old_rel->nspname, "pg_toast") != 0) &&
+ strcmp(old_rel->relname, new_rel->relname) != 0))
+ pg_log(PG_FATAL, "Mismatch of relation names: database \"%s\", "
+ "old rel %s.%s, new rel %s.%s\n",
+ old_db->db_name, old_rel->nspname, old_rel->relname,
+ new_rel->nspname, new_rel->relname);
+
+ create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db,
+ old_rel, new_rel, maps + num_maps);
+ num_maps++;
}
*nmaps = num_maps;
@@ -134,76 +78,95 @@ gen_db_file_maps(migratorContext *ctx, DbInfo *old_db, DbInfo *new_db,
}
-static void
-map_rel(migratorContext *ctx, const RelInfo *oldrel, const RelInfo *newrel,
- const DbInfo *old_db, const DbInfo *new_db, const char *olddata,
- const char *newdata, FileNameMap *map)
-{
- map_rel_by_id(ctx, oldrel->relfilenode, newrel->relfilenode, oldrel->nspname,
- oldrel->relname, newrel->nspname, newrel->relname, oldrel->tablespace, old_db,
- new_db, olddata, newdata, map);
-}
-
-
/*
- * map_rel_by_id()
+ * create_rel_filename_map()
*
* fills a file node map structure and returns it in "map".
*/
static void
-map_rel_by_id(migratorContext *ctx, Oid oldid, Oid newid,
- const char *old_nspname, const char *old_relname,
- const char *new_nspname, const char *new_relname,
- const char *old_tablespace, const DbInfo *old_db,
- const DbInfo *new_db, const char *olddata,
- const char *newdata, FileNameMap *map)
+create_rel_filename_map(const char *old_data, const char *new_data,
+ const DbInfo *old_db, const DbInfo *new_db,
+ const RelInfo *old_rel, const RelInfo *new_rel,
+ FileNameMap *map)
{
- map->new = newid;
- map->old = oldid;
-
- snprintf(map->old_nspname, sizeof(map->old_nspname), "%s", old_nspname);
- snprintf(map->old_relname, sizeof(map->old_relname), "%s", old_relname);
- snprintf(map->new_nspname, sizeof(map->new_nspname), "%s", new_nspname);
- snprintf(map->new_relname, sizeof(map->new_relname), "%s", new_relname);
-
- if (strlen(old_tablespace) == 0)
+ if (strlen(old_rel->tablespace) == 0)
{
/*
- * relation belongs to the default tablespace, hence relfiles would
+ * relation belongs to the default tablespace, hence relfiles should
* exist in the data directories.
*/
- snprintf(map->old_file, sizeof(map->old_file), "%s/base/%u", olddata, old_db->db_oid);
- snprintf(map->new_file, sizeof(map->new_file), "%s/base/%u", newdata, new_db->db_oid);
+ snprintf(map->old_dir, sizeof(map->old_dir), "%s/base/%u", old_data,
+ old_db->db_oid);
+ snprintf(map->new_dir, sizeof(map->new_dir), "%s/base/%u", new_data,
+ new_db->db_oid);
}
else
{
- /*
- * relation belongs to some tablespace, hence copy its physical
- * location
- */
- snprintf(map->old_file, sizeof(map->old_file), "%s%s/%u", old_tablespace,
- ctx->old.tablespace_suffix, old_db->db_oid);
- snprintf(map->new_file, sizeof(map->new_file), "%s%s/%u", old_tablespace,
- ctx->new.tablespace_suffix, new_db->db_oid);
+ /* relation belongs to a tablespace, so use the tablespace location */
+ snprintf(map->old_dir, sizeof(map->old_dir), "%s%s/%u", old_rel->tablespace,
+ old_cluster.tablespace_suffix, old_db->db_oid);
+ snprintf(map->new_dir, sizeof(map->new_dir), "%s%s/%u", new_rel->tablespace,
+ new_cluster.tablespace_suffix, new_db->db_oid);
}
+
+ /*
+ * old_relfilenode might differ from pg_class.oid (and hence
+ * new_relfilenode) because of CLUSTER, REINDEX, or VACUUM FULL.
+ */
+ map->old_relfilenode = old_rel->relfilenode;
+
+ /* new_relfilenode will match old and new pg_class.oid */
+ map->new_relfilenode = new_rel->relfilenode;
+
+ /* used only for logging and error reporing, old/new are identical */
+ snprintf(map->nspname, sizeof(map->nspname), "%s", old_rel->nspname);
+ snprintf(map->relname, sizeof(map->relname), "%s", old_rel->relname);
}
void
-print_maps(migratorContext *ctx, FileNameMap *maps, int n, const char *dbName)
+print_maps(FileNameMap *maps, int n_maps, const char *db_name)
{
- if (ctx->debug)
+ if (log_opts.debug)
{
int mapnum;
- pg_log(ctx, PG_DEBUG, "mappings for db %s:\n", dbName);
+ pg_log(PG_DEBUG, "mappings for db %s:\n", db_name);
+
+ for (mapnum = 0; mapnum < n_maps; mapnum++)
+ pg_log(PG_DEBUG, "%s.%s: %u to %u\n",
+ maps[mapnum].nspname, maps[mapnum].relname,
+ maps[mapnum].old_relfilenode,
+ maps[mapnum].new_relfilenode);
+
+ pg_log(PG_DEBUG, "\n\n");
+ }
+}
+
+
+/*
+ * get_db_and_rel_infos()
+ *
+ * higher level routine to generate dbinfos for the database running
+ * on the given "port". Assumes that server is already running.
+ */
+void
+get_db_and_rel_infos(ClusterInfo *cluster)
+{
+ int dbnum;
+
+ if (cluster->dbarr.dbs != NULL)
+ free_db_and_rel_infos(&cluster->dbarr);
- for (mapnum = 0; mapnum < n; mapnum++)
- pg_log(ctx, PG_DEBUG, "%s.%s:%u ==> %s.%s:%u\n",
- maps[mapnum].old_nspname, maps[mapnum].old_relname, maps[mapnum].old,
- maps[mapnum].new_nspname, maps[mapnum].new_relname, maps[mapnum].new);
+ get_db_infos(cluster);
- pg_log(ctx, PG_DEBUG, "\n\n");
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
+ get_rel_infos(cluster, &cluster->dbarr.dbs[dbnum]);
+
+ if (log_opts.debug)
+ {
+ pg_log(PG_DEBUG, "\n%s databases:\n", CLUSTER_NAME(cluster));
+ print_db_infos(&cluster->dbarr);
}
}
@@ -211,39 +174,40 @@ print_maps(migratorContext *ctx, FileNameMap *maps, int n, const char *dbName)
/*
* get_db_infos()
*
- * Scans pg_database system catalog and returns (in dbinfs_arr) all user
+ * Scans pg_database system catalog and populates all user
* databases.
*/
static void
-get_db_infos(migratorContext *ctx, DbInfoArr *dbinfs_arr, Cluster whichCluster)
+get_db_infos(ClusterInfo *cluster)
{
- PGconn *conn = connectToServer(ctx, "template1", whichCluster);
+ PGconn *conn = connectToServer(cluster, "template1");
PGresult *res;
int ntups;
int tupnum;
DbInfo *dbinfos;
- int i_datname;
- int i_oid;
- int i_spclocation;
+ int i_datname,
+ i_oid,
+ i_spclocation;
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT d.oid, d.datname, t.spclocation "
"FROM pg_catalog.pg_database d "
" LEFT OUTER JOIN pg_catalog.pg_tablespace t "
" ON d.dattablespace = t.oid "
- "WHERE d.datallowconn = true");
+ "WHERE d.datallowconn = true "
+ /* we don't preserve pg_database.oid so we sort by name */
+ "ORDER BY 2");
- i_datname = PQfnumber(res, "datname");
i_oid = PQfnumber(res, "oid");
+ i_datname = PQfnumber(res, "datname");
i_spclocation = PQfnumber(res, "spclocation");
ntups = PQntuples(res);
- dbinfos = (DbInfo *) pg_malloc(ctx, sizeof(DbInfo) * ntups);
+ dbinfos = (DbInfo *) pg_malloc(sizeof(DbInfo) * ntups);
for (tupnum = 0; tupnum < ntups; tupnum++)
{
- dbinfos[tupnum].db_oid = atol(PQgetvalue(res, tupnum, i_oid));
-
+ dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
snprintf(dbinfos[tupnum].db_name, sizeof(dbinfos[tupnum].db_name), "%s",
PQgetvalue(res, tupnum, i_datname));
snprintf(dbinfos[tupnum].db_tblspace, sizeof(dbinfos[tupnum].db_tblspace), "%s",
@@ -253,30 +217,8 @@ get_db_infos(migratorContext *ctx, DbInfoArr *dbinfs_arr, Cluster whichCluster)
PQfinish(conn);
- dbinfs_arr->dbs = dbinfos;
- dbinfs_arr->ndbs = ntups;
-}
-
-
-/*
- * get_db_and_rel_infos()
- *
- * higher level routine to generate dbinfos for the database running
- * on the given "port". Assumes that server is already running.
- */
-void
-get_db_and_rel_infos(migratorContext *ctx, DbInfoArr *db_arr, Cluster whichCluster)
-{
- int dbnum;
-
- get_db_infos(ctx, db_arr, whichCluster);
-
- for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
- get_rel_infos(ctx, &db_arr->dbs[dbnum],
- &(db_arr->dbs[dbnum].rel_arr), whichCluster);
-
- if (ctx->debug)
- dbarr_print(ctx, db_arr, whichCluster);
+ cluster->dbarr.dbs = dbinfos;
+ cluster->dbarr.ndbs = ntups;
}
@@ -290,10 +232,10 @@ get_db_and_rel_infos(migratorContext *ctx, DbInfoArr *db_arr, Cluster whichClust
* FirstNormalObjectId belongs to the user
*/
static void
-get_rel_infos(migratorContext *ctx, const DbInfo *dbinfo,
- RelInfoArr *relarr, Cluster whichCluster)
+get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
{
- PGconn *conn = connectToServer(ctx, dbinfo->db_name, whichCluster);
+ PGconn *conn = connectToServer(cluster,
+ dbinfo->db_name);
PGresult *res;
RelInfo *relinfos;
int ntups;
@@ -301,58 +243,54 @@ get_rel_infos(migratorContext *ctx, const DbInfo *dbinfo,
int num_rels = 0;
char *nspname = NULL;
char *relname = NULL;
- int i_spclocation = -1;
- int i_nspname = -1;
- int i_relname = -1;
- int i_oid = -1;
- int i_relfilenode = -1;
- int i_reltoastrelid = -1;
+ int i_spclocation,
+ i_nspname,
+ i_relname,
+ i_oid,
+ i_relfilenode;
char query[QUERY_ALLOC];
/*
- * pg_largeobject contains user data that does not appear the pg_dumpall
- * --schema-only output, so we have to migrate that system table heap and
- * index. Ideally we could just get the relfilenode from template1 but
- * pg_largeobject_loid_pn_index's relfilenode can change if the table was
- * reindexed so we get the relfilenode for each database and migrate it as
- * a normal user table.
+ * pg_largeobject contains user data that does not appear in pg_dumpall
+ * --schema-only output, so we have to copy that system table heap and
+ * index. We could grab the pg_largeobject oids from template1, but it is
+ * easy to treat it as a normal table. Order by oid so we can join old/new
+ * structures efficiently.
*/
snprintf(query, sizeof(query),
- "SELECT DISTINCT c.oid, n.nspname, c.relname, "
- " c.relfilenode, c.reltoastrelid, t.spclocation "
- "FROM pg_catalog.pg_class c JOIN "
- " pg_catalog.pg_namespace n "
- " ON c.relnamespace = n.oid "
- " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
- " ON c.reltablespace = t.oid "
- "WHERE (( n.nspname NOT IN ('pg_catalog', 'information_schema') "
- " AND c.oid >= %u "
- " ) OR ( "
- " n.nspname = 'pg_catalog' "
- " AND relname IN "
- " ('pg_largeobject', 'pg_largeobject_loid_pn_index') )) "
- " AND relkind IN ('r','t', 'i'%s)"
- "GROUP BY c.oid, n.nspname, c.relname, c.relfilenode,"
- " c.reltoastrelid, t.spclocation, "
- " n.nspname "
- "ORDER BY n.nspname, c.relname;",
- FirstNormalObjectId,
+ "SELECT c.oid, n.nspname, c.relname, "
+ " c.relfilenode, t.spclocation "
+ "FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
+ " ON c.relnamespace = n.oid "
+ " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
+ " ON c.reltablespace = t.oid "
+ "WHERE relkind IN ('r','t', 'i'%s) AND "
+ " ((n.nspname NOT IN ('pg_catalog', 'information_schema', 'binary_upgrade') AND "
+ " c.oid >= %u) "
+ " OR (n.nspname = 'pg_catalog' AND "
+ " relname IN ('pg_largeobject', 'pg_largeobject_loid_pn_index'%s) )) "
+ /* we preserve pg_class.oid so we sort by it to match old/new */
+ "ORDER BY 1;",
/* see the comment at the top of old_8_3_create_sequence_script() */
- (GET_MAJOR_VERSION(ctx->old.major_version) <= 803) ?
- "" : ", 'S'");
+ (GET_MAJOR_VERSION(old_cluster.major_version) <= 803) ?
+ "" : ", 'S'",
+ /* this oid allows us to skip system toast tables */
+ FirstNormalObjectId,
+ /* does pg_largeobject_metadata need to be migrated? */
+ (GET_MAJOR_VERSION(old_cluster.major_version) <= 804) ?
+ "" : ", 'pg_largeobject_metadata', 'pg_largeobject_metadata_oid_index'");
- res = executeQueryOrDie(ctx, conn, query);
+ res = executeQueryOrDie(conn, query);
ntups = PQntuples(res);
- relinfos = (RelInfo *) pg_malloc(ctx, sizeof(RelInfo) * ntups);
+ relinfos = (RelInfo *) pg_malloc(sizeof(RelInfo) * ntups);
i_oid = PQfnumber(res, "oid");
i_nspname = PQfnumber(res, "nspname");
i_relname = PQfnumber(res, "relname");
i_relfilenode = PQfnumber(res, "relfilenode");
- i_reltoastrelid = PQfnumber(res, "reltoastrelid");
i_spclocation = PQfnumber(res, "spclocation");
for (relnum = 0; relnum < ntups; relnum++)
@@ -360,7 +298,7 @@ get_rel_infos(migratorContext *ctx, const DbInfo *dbinfo,
RelInfo *curr = &relinfos[num_rels++];
const char *tblspace;
- curr->reloid = atol(PQgetvalue(res, relnum, i_oid));
+ curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
nspname = PQgetvalue(res, relnum, i_nspname);
strlcpy(curr->nspname, nspname, sizeof(curr->nspname));
@@ -368,8 +306,7 @@ get_rel_infos(migratorContext *ctx, const DbInfo *dbinfo,
relname = PQgetvalue(res, relnum, i_relname);
strlcpy(curr->relname, relname, sizeof(curr->relname));
- curr->relfilenode = atol(PQgetvalue(res, relnum, i_relfilenode));
- curr->toastrelid = atol(PQgetvalue(res, relnum, i_reltoastrelid));
+ curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
tblspace = PQgetvalue(res, relnum, i_spclocation);
/* if no table tablespace, use the database tablespace */
@@ -381,131 +318,53 @@ get_rel_infos(migratorContext *ctx, const DbInfo *dbinfo,
PQfinish(conn);
- relarr->rels = relinfos;
- relarr->nrels = num_rels;
+ dbinfo->rel_arr.rels = relinfos;
+ dbinfo->rel_arr.nrels = num_rels;
}
-/*
- * dbarr_lookup_db()
- *
- * Returns the pointer to the DbInfo structure
- */
-DbInfo *
-dbarr_lookup_db(DbInfoArr *db_arr, const char *db_name)
+void
+free_db_and_rel_infos(DbInfoArr *db_arr)
{
int dbnum;
- if (!db_arr || !db_name)
- return NULL;
-
for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
- {
- if (strcmp(db_arr->dbs[dbnum].db_name, db_name) == 0)
- return &db_arr->dbs[dbnum];
- }
-
- return NULL;
-}
-
-
-/*
- * relarr_lookup_rel()
- *
- * Searches "relname" in rel_arr. Returns the *real* pointer to the
- * RelInfo structure.
- */
-static RelInfo *
-relarr_lookup_rel(migratorContext *ctx, RelInfoArr *rel_arr,
- const char *nspname, const char *relname,
- Cluster whichCluster)
-{
- int relnum;
-
- if (!rel_arr || !relname)
- return NULL;
-
- for (relnum = 0; relnum < rel_arr->nrels; relnum++)
- {
- if (strcmp(rel_arr->rels[relnum].nspname, nspname) == 0 &&
- strcmp(rel_arr->rels[relnum].relname, relname) == 0)
- return &rel_arr->rels[relnum];
- }
- pg_log(ctx, PG_FATAL, "Could not find %s.%s in %s cluster\n",
- nspname, relname, CLUSTERNAME(whichCluster));
- return NULL;
-}
-
-
-/*
- * relarr_lookup_reloid()
- *
- * Returns a pointer to the RelInfo structure for the
- * given oid or NULL if the desired entry cannot be
- * found.
- */
-static RelInfo *
-relarr_lookup_reloid(migratorContext *ctx, RelInfoArr *rel_arr, Oid oid,
- Cluster whichCluster)
-{
- int relnum;
-
- if (!rel_arr || !oid)
- return NULL;
-
- for (relnum = 0; relnum < rel_arr->nrels; relnum++)
- {
- if (rel_arr->rels[relnum].reloid == oid)
- return &rel_arr->rels[relnum];
- }
- pg_log(ctx, PG_FATAL, "Could not find %d in %s cluster\n",
- oid, CLUSTERNAME(whichCluster));
- return NULL;
+ free_rel_infos(&db_arr->dbs[dbnum].rel_arr);
+ pg_free(db_arr->dbs);
+ db_arr->dbs = NULL;
+ db_arr->ndbs = 0;
}
static void
-relarr_free(RelInfoArr *rel_arr)
+free_rel_infos(RelInfoArr *rel_arr)
{
pg_free(rel_arr->rels);
rel_arr->nrels = 0;
}
-void
-dbarr_free(DbInfoArr *db_arr)
-{
- int dbnum;
-
- for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
- relarr_free(&db_arr->dbs[dbnum].rel_arr);
- db_arr->ndbs = 0;
-}
-
-
static void
-dbarr_print(migratorContext *ctx, DbInfoArr *arr, Cluster whichCluster)
+print_db_infos(DbInfoArr *db_arr)
{
int dbnum;
- pg_log(ctx, PG_DEBUG, "%s databases\n", CLUSTERNAME(whichCluster));
-
- for (dbnum = 0; dbnum < arr->ndbs; dbnum++)
+ for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
{
- pg_log(ctx, PG_DEBUG, "Database: %s\n", arr->dbs[dbnum].db_name);
- relarr_print(ctx, &arr->dbs[dbnum].rel_arr);
- pg_log(ctx, PG_DEBUG, "\n\n");
+ pg_log(PG_DEBUG, "Database: %s\n", db_arr->dbs[dbnum].db_name);
+ print_rel_infos(&db_arr->dbs[dbnum].rel_arr);
+ pg_log(PG_DEBUG, "\n\n");
}
}
static void
-relarr_print(migratorContext *ctx, RelInfoArr *arr)
+print_rel_infos(RelInfoArr *arr)
{
int relnum;
for (relnum = 0; relnum < arr->nrels; relnum++)
- pg_log(ctx, PG_DEBUG, "relname: %s.%s: reloid: %u reltblspace: %s\n",
+ pg_log(PG_DEBUG, "relname: %s.%s: reloid: %u reltblspace: %s\n",
arr->rels[relnum].nspname, arr->rels[relnum].relname,
arr->rels[relnum].reloid, arr->rels[relnum].tablespace);
}
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
index 1704069b34..abb74a5bfa 100644
--- a/contrib/pg_upgrade/option.c
+++ b/contrib/pg_upgrade/option.c
@@ -3,8 +3,8 @@
*
* options functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/option.c,v 1.12 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/option.c
*/
#include "pg_upgrade.h"
@@ -16,21 +16,23 @@
#endif
-static void usage(migratorContext *ctx);
-static void validateDirectoryOption(migratorContext *ctx, char **dirpath,
+static void usage(void);
+static void validateDirectoryOption(char **dirpath,
char *envVarName, char *cmdLineOption, char *description);
-static void get_pkglibdirs(migratorContext *ctx);
-static char *get_pkglibdir(migratorContext *ctx, const char *bindir);
+static void get_pkglibdirs(void);
+static char *get_pkglibdir(const char *bindir);
+
+
+UserOpts user_opts;
/*
* parseCommandLine()
*
- * Parses the command line (argc, argv[]) into the given migratorContext object
- * and initializes the rest of the object.
+ * Parses the command line (argc, argv[]) and loads structures
*/
void
-parseCommandLine(migratorContext *ctx, int argc, char *argv[])
+parseCommandLine(int argc, char *argv[])
{
static struct option long_options[] = {
{"old-datadir", required_argument, NULL, 'd'},
@@ -51,125 +53,133 @@ parseCommandLine(migratorContext *ctx, int argc, char *argv[])
};
int option; /* Command line option */
int optindex = 0; /* used by getopt_long */
- int user_id;
+ int os_user_effective_id;
- if (getenv("PGUSER"))
- {
- pg_free(ctx->user);
- ctx->user = pg_strdup(ctx, getenv("PGUSER"));
- }
+ user_opts.transfer_mode = TRANSFER_MODE_COPY;
- ctx->progname = get_progname(argv[0]);
- ctx->old.port = getenv("PGPORT") ? atoi(getenv("PGPORT")) : DEF_PGPORT;
- ctx->new.port = getenv("PGPORT") ? atoi(getenv("PGPORT")) : DEF_PGPORT;
- /* must save value, getenv()'s pointer is not stable */
+ os_info.progname = get_progname(argv[0]);
- ctx->transfer_mode = TRANSFER_MODE_COPY;
+ /* Process libpq env. variables; load values here for usage() output */
+ old_cluster.port = getenv("PGPORT") ? atoi(getenv("PGPORT")) : DEF_PGPORT;
+ new_cluster.port = getenv("PGPORT") ? atoi(getenv("PGPORT")) : DEF_PGPORT;
- /* user lookup and 'root' test must be split because of usage() */
- user_id = get_user_info(ctx, &ctx->user);
+ os_user_effective_id = get_user_info(&os_info.user);
+ /* we override just the database user name; we got the OS id above */
+ if (getenv("PGUSER"))
+ {
+ pg_free(os_info.user);
+ /* must save value, getenv()'s pointer is not stable */
+ os_info.user = pg_strdup(getenv("PGUSER"));
+ }
if (argc > 1)
{
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ||
strcmp(argv[1], "-?") == 0)
{
- usage(ctx);
- exit_nicely(ctx, false);
+ usage();
+ exit(0);
}
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
{
- pg_log(ctx, PG_REPORT, "pg_upgrade " PG_VERSION "\n");
- exit_nicely(ctx, false);
+ puts("pg_upgrade (PostgreSQL) " PG_VERSION);
+ exit(0);
}
}
- if (user_id == 0)
- pg_log(ctx, PG_FATAL, "%s: cannot be run as root\n", ctx->progname);
+ /* Allow help and version to be run as root, so do the test here. */
+ if (os_user_effective_id == 0)
+ pg_log(PG_FATAL, "%s: cannot be run as root\n", os_info.progname);
- getcwd(ctx->cwd, MAXPGPATH);
+ getcwd(os_info.cwd, MAXPGPATH);
while ((option = getopt_long(argc, argv, "d:D:b:B:cgG:kl:p:P:u:v",
long_options, &optindex)) != -1)
{
switch (option)
{
- case 'd':
- ctx->old.pgdata = pg_strdup(ctx, optarg);
+ case 'b':
+ old_cluster.bindir = pg_strdup(optarg);
break;
- case 'D':
- ctx->new.pgdata = pg_strdup(ctx, optarg);
+ case 'B':
+ new_cluster.bindir = pg_strdup(optarg);
break;
- case 'b':
- ctx->old.bindir = pg_strdup(ctx, optarg);
+ case 'c':
+ user_opts.check = true;
break;
- case 'B':
- ctx->new.bindir = pg_strdup(ctx, optarg);
+ case 'd':
+ old_cluster.pgdata = pg_strdup(optarg);
break;
- case 'c':
- ctx->check = true;
+ case 'D':
+ new_cluster.pgdata = pg_strdup(optarg);
break;
case 'g':
- pg_log(ctx, PG_REPORT, "Running in debug mode\n");
- ctx->debug = true;
+ pg_log(PG_REPORT, "Running in debug mode\n");
+ log_opts.debug = true;
break;
case 'G':
- if ((ctx->debug_fd = fopen(optarg, "w")) == NULL)
+ if ((log_opts.debug_fd = fopen(optarg, "w")) == NULL)
{
- pg_log(ctx, PG_FATAL, "cannot open debug file\n");
- exit_nicely(ctx, false);
+ pg_log(PG_FATAL, "cannot open debug file\n");
+ exit(1);
}
break;
case 'k':
- ctx->transfer_mode = TRANSFER_MODE_LINK;
+ user_opts.transfer_mode = TRANSFER_MODE_LINK;
break;
case 'l':
- ctx->logfile = pg_strdup(ctx, optarg);
+ log_opts.filename = pg_strdup(optarg);
break;
case 'p':
- if ((ctx->old.port = atoi(optarg)) <= 0)
+ if ((old_cluster.port = atoi(optarg)) <= 0)
{
- pg_log(ctx, PG_FATAL, "invalid old port number\n");
- exit_nicely(ctx, false);
+ pg_log(PG_FATAL, "invalid old port number\n");
+ exit(1);
}
break;
case 'P':
- if ((ctx->new.port = atoi(optarg)) <= 0)
+ if ((new_cluster.port = atoi(optarg)) <= 0)
{
- pg_log(ctx, PG_FATAL, "invalid new port number\n");
- exit_nicely(ctx, false);
+ pg_log(PG_FATAL, "invalid new port number\n");
+ exit(1);
}
break;
case 'u':
- pg_free(ctx->user);
- ctx->user = pg_strdup(ctx, optarg);
+ pg_free(os_info.user);
+ os_info.user = pg_strdup(optarg);
+
+ /*
+ * Push the user name into the environment so pre-9.1
+ * pg_ctl/libpq uses it.
+ */
+ pg_putenv("PGUSER", os_info.user);
break;
case 'v':
- pg_log(ctx, PG_REPORT, "Running in verbose mode\n");
- ctx->verbose = true;
+ pg_log(PG_REPORT, "Running in verbose mode\n");
+ log_opts.verbose = true;
break;
default:
- pg_log(ctx, PG_FATAL,
+ pg_log(PG_FATAL,
"Try \"%s --help\" for more information.\n",
- ctx->progname);
+ os_info.progname);
break;
}
}
- if (ctx->logfile != NULL)
+ if (log_opts.filename != NULL)
{
/*
* We must use append mode so output generated by child processes via
@@ -177,58 +187,60 @@ parseCommandLine(migratorContext *ctx, int argc, char *argv[])
* start.
*/
/* truncate */
- if ((ctx->log_fd = fopen(ctx->logfile, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Cannot write to log file %s\n", ctx->logfile);
- fclose(ctx->log_fd);
- if ((ctx->log_fd = fopen(ctx->logfile, "a")) == NULL)
- pg_log(ctx, PG_FATAL, "Cannot write to log file %s\n", ctx->logfile);
+ if ((log_opts.fd = fopen(log_opts.filename, "w")) == NULL)
+ pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename);
+ fclose(log_opts.fd);
+ if ((log_opts.fd = fopen(log_opts.filename, "a")) == NULL)
+ pg_log(PG_FATAL, "cannot write to log file %s\n", log_opts.filename);
}
else
- ctx->logfile = strdup(DEVNULL);
+ log_opts.filename = strdup(DEVNULL);
/* if no debug file name, output to the terminal */
- if (ctx->debug && !ctx->debug_fd)
+ if (log_opts.debug && !log_opts.debug_fd)
{
- ctx->debug_fd = fopen(DEVTTY, "w");
- if (!ctx->debug_fd)
- pg_log(ctx, PG_FATAL, "Cannot write to terminal\n");
+ log_opts.debug_fd = fopen(DEVTTY, "w");
+ if (!log_opts.debug_fd)
+ pg_log(PG_FATAL, "cannot write to terminal\n");
}
/* Get values from env if not already set */
- validateDirectoryOption(ctx, &ctx->old.pgdata, "OLDDATADIR", "-d",
- "old cluster data resides");
- validateDirectoryOption(ctx, &ctx->new.pgdata, "NEWDATADIR", "-D",
- "new cluster data resides");
- validateDirectoryOption(ctx, &ctx->old.bindir, "OLDBINDIR", "-b",
+ validateDirectoryOption(&old_cluster.bindir, "OLDBINDIR", "-b",
"old cluster binaries reside");
- validateDirectoryOption(ctx, &ctx->new.bindir, "NEWBINDIR", "-B",
+ validateDirectoryOption(&new_cluster.bindir, "NEWBINDIR", "-B",
"new cluster binaries reside");
+ validateDirectoryOption(&old_cluster.pgdata, "OLDDATADIR", "-d",
+ "old cluster data resides");
+ validateDirectoryOption(&new_cluster.pgdata, "NEWDATADIR", "-D",
+ "new cluster data resides");
- get_pkglibdirs(ctx);
+ get_pkglibdirs();
}
static void
-usage(migratorContext *ctx)
+usage(void)
{
- printf(_("\nUsage: pg_upgrade [OPTIONS]...\n\
+ printf(_("pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n\
+\nUsage:\n\
+ pg_upgrade [OPTIONS]...\n\
\n\
Options:\n\
- -b, --old-bindir=old_bindir old cluster executable directory\n\
- -B, --new-bindir=new_bindir new cluster executable directory\n\
- -c, --check check clusters only, don't change any data\n\
- -d, --old-datadir=old_datadir old cluster data directory\n\
- -D, --new-datadir=new_datadir new cluster data directory\n\
- -g, --debug enable debugging\n\
- -G, --debugfile=debug_filename output debugging activity to file\n\
- -k, --link link instead of copying files to new cluster\n\
- -l, --logfile=log_filename log session activity to file\n\
- -p, --old-port=old_portnum old cluster port number (default %d)\n\
- -P, --new-port=new_portnum new cluster port number (default %d)\n\
- -u, --user=username clusters superuser (default \"%s\")\n\
- -v, --verbose enable verbose output\n\
- -V, --version display version information, then exit\n\
- -h, --help show this help, then exit\n\
+ -b, --old-bindir=OLDBINDIR old cluster executable directory\n\
+ -B, --new-bindir=NEWBINDIR new cluster executable directory\n\
+ -c, --check check clusters only, don't change any data\n\
+ -d, --old-datadir=OLDDATADIR old cluster data directory\n\
+ -D, --new-datadir=NEWDATADIR new cluster data directory\n\
+ -g, --debug enable debugging\n\
+ -G, --debugfile=FILENAME output debugging activity to file\n\
+ -k, --link link instead of copying files to new cluster\n\
+ -l, --logfile=FILENAME log session activity to file\n\
+ -p, --old-port=OLDPORT old cluster port number (default %d)\n\
+ -P, --new-port=NEWPORT new cluster port number (default %d)\n\
+ -u, --user=NAME clusters superuser (default \"%s\")\n\
+ -v, --verbose enable verbose output\n\
+ -V, --version display version information, then exit\n\
+ -h, --help show this help, then exit\n\
\n\
Before running pg_upgrade you must:\n\
create a new database cluster (using the new version of initdb)\n\
@@ -238,12 +250,12 @@ Before running pg_upgrade you must:\n\
When you run pg_upgrade, you must provide the following information:\n\
the data directory for the old cluster (-d OLDDATADIR)\n\
the data directory for the new cluster (-D NEWDATADIR)\n\
- the 'bin' directory for the old version (-b OLDBINDIR)\n\
- the 'bin' directory for the new version (-B NEWBINDIR)\n\
+ the \"bin\" directory for the old version (-b OLDBINDIR)\n\
+ the \"bin\" directory for the new version (-B NEWBINDIR)\n\
\n\
For example:\n\
pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n\
-or\n"), ctx->old.port, ctx->new.port, ctx->user);
+or\n"), old_cluster.port, new_cluster.port, os_info.user);
#ifndef WIN32
printf(_("\
$ export OLDDATADIR=oldCluster/data\n\
@@ -259,10 +271,7 @@ or\n"), ctx->old.port, ctx->new.port, ctx->user);
C:\\> set NEWBINDIR=newCluster/bin\n\
C:\\> pg_upgrade\n"));
#endif
- printf(_("\n\
-You may find it useful to save the preceding 5 commands in a shell script\n\
-\n\
-Report bugs to <pg-migrator-general@lists.pgfoundry.org>\n"));
+ printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
}
@@ -279,7 +288,7 @@ Report bugs to <pg-migrator-general@lists.pgfoundry.org>\n"));
* user hasn't provided the required directory name.
*/
static void
-validateDirectoryOption(migratorContext *ctx, char **dirpath,
+validateDirectoryOption(char **dirpath,
char *envVarName, char *cmdLineOption, char *description)
{
if (*dirpath == NULL || (strlen(*dirpath) == 0))
@@ -287,10 +296,10 @@ validateDirectoryOption(migratorContext *ctx, char **dirpath,
const char *envVar;
if ((envVar = getenv(envVarName)) && strlen(envVar))
- *dirpath = pg_strdup(ctx, envVar);
+ *dirpath = pg_strdup(envVar);
else
{
- pg_log(ctx, PG_FATAL, "You must identify the directory where the %s\n"
+ pg_log(PG_FATAL, "You must identify the directory where the %s\n"
"Please use the %s command-line option or the %s environment variable\n",
description, cmdLineOption, envVarName);
}
@@ -310,15 +319,19 @@ validateDirectoryOption(migratorContext *ctx, char **dirpath,
static void
-get_pkglibdirs(migratorContext *ctx)
+get_pkglibdirs(void)
{
- ctx->old.libpath = get_pkglibdir(ctx, ctx->old.bindir);
- ctx->new.libpath = get_pkglibdir(ctx, ctx->new.bindir);
+ /*
+ * we do not need to know the libpath in the old cluster, and might not
+ * have a working pg_config to ask for it anyway.
+ */
+ old_cluster.libpath = NULL;
+ new_cluster.libpath = get_pkglibdir(new_cluster.bindir);
}
static char *
-get_pkglibdir(migratorContext *ctx, const char *bindir)
+get_pkglibdir(const char *bindir)
{
char cmd[MAXPGPATH];
char bufin[MAX_STRING];
@@ -328,7 +341,7 @@ get_pkglibdir(migratorContext *ctx, const char *bindir)
snprintf(cmd, sizeof(cmd), "\"%s/pg_config\" --pkglibdir", bindir);
if ((output = popen(cmd, "r")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not get pkglibdir data: %s\n",
+ pg_log(PG_FATAL, "Could not get pkglibdir data: %s\n",
getErrorText(errno));
fgets(bufin, sizeof(bufin), output);
@@ -342,5 +355,5 @@ get_pkglibdir(migratorContext *ctx, const char *bindir)
if (bufin[i] == '\n')
bufin[i] = '\0';
- return pg_strdup(ctx, bufin);
+ return pg_strdup(bufin);
}
diff --git a/contrib/pg_upgrade/page.c b/contrib/pg_upgrade/page.c
index de19a0023e..22a587f4b1 100644
--- a/contrib/pg_upgrade/page.c
+++ b/contrib/pg_upgrade/page.c
@@ -3,8 +3,8 @@
*
* per-page conversion operations
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/page.c,v 1.5 2010/07/03 16:33:14 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/page.c
*/
#include "pg_upgrade.h"
@@ -15,9 +15,9 @@
#ifdef PAGE_CONVERSION
-static const char *getPageVersion(migratorContext *ctx,
+static const char *getPageVersion(
uint16 *version, const char *pathName);
-static pageCnvCtx *loadConverterPlugin(migratorContext *ctx,
+static pageCnvCtx *loadConverterPlugin(
uint16 newPageVersion, uint16 oldPageVersion);
@@ -37,7 +37,7 @@ static pageCnvCtx *loadConverterPlugin(migratorContext *ctx,
* string.
*/
const char *
-setupPageConverter(migratorContext *ctx, pageCnvCtx **result)
+setupPageConverter(pageCnvCtx **result)
{
uint16 oldPageVersion;
uint16 newPageVersion;
@@ -46,15 +46,15 @@ setupPageConverter(migratorContext *ctx, pageCnvCtx **result)
char dstName[MAXPGPATH];
char srcName[MAXPGPATH];
- snprintf(dstName, sizeof(dstName), "%s/global/%u", ctx->new.pgdata,
- ctx->new.pg_database_oid);
- snprintf(srcName, sizeof(srcName), "%s/global/%u", ctx->old.pgdata,
- ctx->old.pg_database_oid);
+ snprintf(dstName, sizeof(dstName), "%s/global/%u", new_cluster.pgdata,
+ new_cluster.pg_database_oid);
+ snprintf(srcName, sizeof(srcName), "%s/global/%u", old_cluster.pgdata,
+ old_cluster.pg_database_oid);
- if ((msg = getPageVersion(ctx, &oldPageVersion, srcName)) != NULL)
+ if ((msg = getPageVersion(&oldPageVersion, srcName)) != NULL)
return msg;
- if ((msg = getPageVersion(ctx, &newPageVersion, dstName)) != NULL)
+ if ((msg = getPageVersion(&newPageVersion, dstName)) != NULL)
return msg;
/*
@@ -73,7 +73,7 @@ setupPageConverter(migratorContext *ctx, pageCnvCtx **result)
* layout.
*/
- if ((converter = loadConverterPlugin(ctx, newPageVersion, oldPageVersion)) == NULL)
+ if ((converter = loadConverterPlugin(newPageVersion, oldPageVersion)) == NULL)
return "can't find plugin to convert from old page layout to new page layout";
else
{
@@ -93,7 +93,7 @@ setupPageConverter(migratorContext *ctx, pageCnvCtx **result)
* of a null-terminated string).
*/
static const char *
-getPageVersion(migratorContext *ctx, uint16 *version, const char *pathName)
+getPageVersion(uint16 *version, const char *pathName)
{
int relfd;
PageHeaderData page;
@@ -103,7 +103,10 @@ getPageVersion(migratorContext *ctx, uint16 *version, const char *pathName)
return "can't open relation";
if ((bytesRead = read(relfd, &page, sizeof(page))) != sizeof(page))
+ {
+ close(relfd);
return "can't read page header";
+ }
*version = PageGetPageLayoutVersion(&page);
@@ -125,7 +128,7 @@ getPageVersion(migratorContext *ctx, uint16 *version, const char *pathName)
* is not found, this function returns NULL.
*/
static pageCnvCtx *
-loadConverterPlugin(migratorContext *ctx, uint16 newPageVersion, uint16 oldPageVersion)
+loadConverterPlugin(uint16 newPageVersion, uint16 oldPageVersion)
{
char pluginName[MAXPGPATH];
void *plugin;
@@ -148,7 +151,7 @@ loadConverterPlugin(migratorContext *ctx, uint16 newPageVersion, uint16 oldPageV
return NULL;
else
{
- pageCnvCtx *result = (pageCnvCtx *) pg_malloc(ctx, sizeof(*result));
+ pageCnvCtx *result = (pageCnvCtx *) pg_malloc(sizeof(*result));
result->old.PageVersion = oldPageVersion;
result->new.PageVersion = newPageVersion;
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index 695596ba60..e329dc3efe 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -3,76 +3,112 @@
*
* main source file
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/pg_upgrade.c,v 1.10 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/pg_upgrade.c
*/
+/*
+ * To simplify the upgrade process, we force certain system values to be
+ * identical between old and new clusters:
+ *
+ * We control all assignments of pg_class.oid (and relfilenode) so toast
+ * oids are the same between old and new clusters. This is important
+ * because toast oids are stored as toast pointers in user tables.
+ *
+ * FYI, while pg_class.oid and pg_class.relfilenode are intially the same
+ * in a cluster, but they can diverge due to CLUSTER, REINDEX, or VACUUM
+ * FULL. The new cluster will have matching pg_class.oid and
+ * pg_class.relfilenode values and be based on the old oid value. This can
+ * cause the old and new pg_class.relfilenode values to differ. In summary,
+ * old and new pg_class.oid and new pg_class.relfilenode will have the
+ * same value, and old pg_class.relfilenode might differ.
+ *
+ * We control all assignments of pg_type.oid because these oids are stored
+ * in user composite type values.
+ *
+ * We control all assignments of pg_enum.oid because these oids are stored
+ * in user tables as enum values.
+ *
+ * We control all assignments of pg_auth.oid because these oids are stored
+ * in pg_largeobject_metadata.
+ */
+
+
+
#include "pg_upgrade.h"
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
-static void disable_old_cluster(migratorContext *ctx);
-static void prepare_new_cluster(migratorContext *ctx);
-static void prepare_new_databases(migratorContext *ctx);
-static void create_new_objects(migratorContext *ctx);
-static void copy_clog_xlog_xid(migratorContext *ctx);
-static void set_frozenxids(migratorContext *ctx);
-static void setup(migratorContext *ctx, char *argv0, bool live_check);
-static void cleanup(migratorContext *ctx);
+static void disable_old_cluster(void);
+static void prepare_new_cluster(void);
+static void prepare_new_databases(void);
+static void create_new_objects(void);
+static void copy_clog_xlog_xid(void);
+static void set_frozenxids(void);
+static void setup(char *argv0, bool live_check);
+static void cleanup(void);
+/* This is the database used by pg_dumpall to restore global tables */
+#define GLOBAL_DUMP_DB "postgres"
+
+ClusterInfo old_cluster,
+ new_cluster;
+OSInfo os_info;
int
main(int argc, char **argv)
{
- migratorContext ctx;
char *sequence_script_file_name = NULL;
char *deletion_script_file_name = NULL;
bool live_check = false;
- memset(&ctx, 0, sizeof(ctx));
-
- parseCommandLine(&ctx, argc, argv);
+ parseCommandLine(argc, argv);
- output_check_banner(&ctx, &live_check);
+ output_check_banner(&live_check);
- setup(&ctx, argv[0], live_check);
+ setup(argv[0], live_check);
- check_cluster_versions(&ctx);
- check_cluster_compatibility(&ctx, live_check);
+ check_cluster_versions();
+ check_cluster_compatibility(live_check);
- check_old_cluster(&ctx, live_check, &sequence_script_file_name);
+ check_old_cluster(live_check, &sequence_script_file_name);
/* -- NEW -- */
- start_postmaster(&ctx, CLUSTER_NEW, false);
+ start_postmaster(&new_cluster);
- check_new_cluster(&ctx);
- report_clusters_compatible(&ctx);
+ check_new_cluster();
+ report_clusters_compatible();
- pg_log(&ctx, PG_REPORT, "\nPerforming Migration\n");
- pg_log(&ctx, PG_REPORT, "--------------------\n");
+ pg_log(PG_REPORT, "\nPerforming Upgrade\n");
+ pg_log(PG_REPORT, "------------------\n");
- disable_old_cluster(&ctx);
- prepare_new_cluster(&ctx);
+ disable_old_cluster();
+ prepare_new_cluster();
- stop_postmaster(&ctx, false, false);
+ stop_postmaster(false);
/*
* Destructive Changes to New Cluster
*/
- copy_clog_xlog_xid(&ctx);
+ copy_clog_xlog_xid();
/* New now using xids of the old system */
- prepare_new_databases(&ctx);
+ /* -- NEW -- */
+ start_postmaster(&new_cluster);
+
+ prepare_new_databases();
- create_new_objects(&ctx);
+ create_new_objects();
- transfer_all_new_dbs(&ctx, &ctx.old.dbarr, &ctx.new.dbarr,
- ctx.old.pgdata, ctx.new.pgdata);
+ stop_postmaster(false);
+
+ transfer_all_new_dbs(&old_cluster.dbarr, &new_cluster.dbarr,
+ old_cluster.pgdata, new_cluster.pgdata);
/*
* Assuming OIDs are only used in system tables, there is no need to
@@ -80,32 +116,32 @@ main(int argc, char **argv)
* the old system, but we do it anyway just in case. We do it late here
* because there is no need to have the schema load use new oids.
*/
- prep_status(&ctx, "Setting next oid for new cluster");
- exec_prog(&ctx, true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" > "
+ prep_status("Setting next oid for new cluster");
+ exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" > "
DEVNULL SYSTEMQUOTE,
- ctx.new.bindir, ctx.old.controldata.chkpnt_nxtoid, ctx.new.pgdata);
- check_ok(&ctx);
+ new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid, new_cluster.pgdata);
+ check_ok();
- create_script_for_old_cluster_deletion(&ctx, &deletion_script_file_name);
+ create_script_for_old_cluster_deletion(&deletion_script_file_name);
- issue_warnings(&ctx, sequence_script_file_name);
+ issue_warnings(sequence_script_file_name);
- pg_log(&ctx, PG_REPORT, "\nUpgrade complete\n");
- pg_log(&ctx, PG_REPORT, "----------------\n");
+ pg_log(PG_REPORT, "\nUpgrade complete\n");
+ pg_log(PG_REPORT, "----------------\n");
- output_completion_banner(&ctx, deletion_script_file_name);
+ output_completion_banner(deletion_script_file_name);
pg_free(deletion_script_file_name);
pg_free(sequence_script_file_name);
- cleanup(&ctx);
+ cleanup();
return 0;
}
static void
-setup(migratorContext *ctx, char *argv0, bool live_check)
+setup(char *argv0, bool live_check)
{
char exec_path[MAXPGPATH]; /* full path to my executable */
@@ -113,57 +149,53 @@ setup(migratorContext *ctx, char *argv0, bool live_check)
* make sure the user has a clean environment, otherwise, we may confuse
* libpq when we connect to one (or both) of the servers.
*/
- check_for_libpq_envvars(ctx);
+ check_pghost_envvar();
- verify_directories(ctx);
+ verify_directories();
/* no postmasters should be running */
- if (!live_check && is_server_running(ctx, ctx->old.pgdata))
- {
- pg_log(ctx, PG_FATAL, "There seems to be a postmaster servicing the old cluster.\n"
+ if (!live_check && is_server_running(old_cluster.pgdata))
+ pg_log(PG_FATAL, "There seems to be a postmaster servicing the old cluster.\n"
"Please shutdown that postmaster and try again.\n");
- }
/* same goes for the new postmaster */
- if (is_server_running(ctx, ctx->new.pgdata))
- {
- pg_log(ctx, PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n"
+ if (is_server_running(new_cluster.pgdata))
+ pg_log(PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n"
"Please shutdown that postmaster and try again.\n");
- }
/* get path to pg_upgrade executable */
if (find_my_exec(argv0, exec_path) < 0)
- pg_log(ctx, PG_FATAL, "Could not get pathname to pg_upgrade: %s\n", getErrorText(errno));
+ pg_log(PG_FATAL, "Could not get pathname to pg_upgrade: %s\n", getErrorText(errno));
/* Trim off program name and keep just path */
*last_dir_separator(exec_path) = '\0';
canonicalize_path(exec_path);
- ctx->exec_path = pg_strdup(ctx, exec_path);
+ os_info.exec_path = pg_strdup(exec_path);
}
static void
-disable_old_cluster(migratorContext *ctx)
+disable_old_cluster(void)
{
/* rename pg_control so old server cannot be accidentally started */
- rename_old_pg_control(ctx);
+ rename_old_pg_control();
}
static void
-prepare_new_cluster(migratorContext *ctx)
+prepare_new_cluster(void)
{
/*
* It would make more sense to freeze after loading the schema, but that
* would cause us to lose the frozenids restored by the load. We use
* --analyze so autovacuum doesn't update statistics later
*/
- prep_status(ctx, "Analyzing all rows in the new cluster");
- exec_prog(ctx, true,
+ prep_status("Analyzing all rows in the new cluster");
+ exec_prog(true,
SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
"--all --analyze >> %s 2>&1" SYSTEMQUOTE,
- ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
- check_ok(ctx);
+ new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
+ check_ok();
/*
* We do freeze after analyze so pg_statistic is also frozen. template0 is
@@ -171,118 +203,129 @@ prepare_new_cluster(migratorContext *ctx)
* datfrozenxid and relfrozenxids later to match the new xid counter
* later.
*/
- prep_status(ctx, "Freezing all rows on the new cluster");
- exec_prog(ctx, true,
+ prep_status("Freezing all rows on the new cluster");
+ exec_prog(true,
SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
"--all --freeze >> %s 2>&1" SYSTEMQUOTE,
- ctx->new.bindir, ctx->new.port, ctx->user, ctx->logfile);
- check_ok(ctx);
+ new_cluster.bindir, new_cluster.port, os_info.user, log_opts.filename);
+ check_ok();
- get_pg_database_relfilenode(ctx, CLUSTER_NEW);
+ get_pg_database_relfilenode(&new_cluster);
}
static void
-prepare_new_databases(migratorContext *ctx)
+prepare_new_databases(void)
{
- /* -- NEW -- */
- start_postmaster(ctx, CLUSTER_NEW, false);
-
/*
* We set autovacuum_freeze_max_age to its maximum value so autovacuum
* does not launch here and delete clog files, before the frozen xids are
* set.
*/
- set_frozenxids(ctx);
+ set_frozenxids();
+
+ prep_status("Creating databases in the new cluster");
+
+ /*
+ * Install support functions in the global-restore database to preserve
+ * pg_authid.oid.
+ */
+ install_support_functions_in_new_db(GLOBAL_DUMP_DB);
/*
- * We have to create the databases first so we can create the toast table
- * placeholder relfiles.
+ * We have to create the databases first so we can install support
+ * functions in all the other databases. Ideally we could create the
+ * support functions in template1 but pg_dumpall creates database using
+ * the template0 template.
*/
- prep_status(ctx, "Creating databases in the new cluster");
- exec_prog(ctx, true,
- SYSTEMQUOTE "\"%s/psql\" --port %d --username \"%s\" "
- "--set ON_ERROR_STOP=on -f \"%s/%s\" --dbname template1 >> \"%s\""
- SYSTEMQUOTE,
- ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
- GLOBALS_DUMP_FILE, ctx->logfile);
- check_ok(ctx);
-
- get_db_and_rel_infos(ctx, &ctx->new.dbarr, CLUSTER_NEW);
-
- stop_postmaster(ctx, false, false);
+ exec_prog(true,
+ SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on "
+ /* --no-psqlrc prevents AUTOCOMMIT=off */
+ "--no-psqlrc --port %d --username \"%s\" "
+ "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
+ new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
+ GLOBALS_DUMP_FILE, log_opts.filename);
+ check_ok();
+
+ /* we load this to get a current list of databases */
+ get_db_and_rel_infos(&new_cluster);
}
static void
-create_new_objects(migratorContext *ctx)
+create_new_objects(void)
{
- /* -- NEW -- */
- start_postmaster(ctx, CLUSTER_NEW, false);
+ int dbnum;
+
+ prep_status("Adding support functions to new cluster");
- install_support_functions(ctx);
+ for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
+ {
+ DbInfo *new_db = &new_cluster.dbarr.dbs[dbnum];
- prep_status(ctx, "Restoring database schema to new cluster");
- exec_prog(ctx, true,
- SYSTEMQUOTE "\"%s/psql\" --port %d --username \"%s\" "
- "--set ON_ERROR_STOP=on -f \"%s/%s\" --dbname template1 >> \"%s\""
- SYSTEMQUOTE,
- ctx->new.bindir, ctx->new.port, ctx->user, ctx->cwd,
- DB_DUMP_FILE, ctx->logfile);
- check_ok(ctx);
+ /* skip db we already installed */
+ if (strcmp(new_db->db_name, GLOBAL_DUMP_DB) != 0)
+ install_support_functions_in_new_db(new_db->db_name);
+ }
+ check_ok();
- /* regenerate now that we have db schemas */
- dbarr_free(&ctx->new.dbarr);
- get_db_and_rel_infos(ctx, &ctx->new.dbarr, CLUSTER_NEW);
+ prep_status("Restoring database schema to new cluster");
+ exec_prog(true,
+ SYSTEMQUOTE "\"%s/psql\" --set ON_ERROR_STOP=on "
+ "--no-psqlrc --port %d --username \"%s\" "
+ "-f \"%s/%s\" --dbname template1 >> \"%s\"" SYSTEMQUOTE,
+ new_cluster.bindir, new_cluster.port, os_info.user, os_info.cwd,
+ DB_DUMP_FILE, log_opts.filename);
+ check_ok();
- uninstall_support_functions(ctx);
+ /* regenerate now that we have objects in the databases */
+ get_db_and_rel_infos(&new_cluster);
- stop_postmaster(ctx, false, false);
+ uninstall_support_functions_from_new_cluster();
}
static void
-copy_clog_xlog_xid(migratorContext *ctx)
+copy_clog_xlog_xid(void)
{
char old_clog_path[MAXPGPATH];
char new_clog_path[MAXPGPATH];
/* copy old commit logs to new data dir */
- prep_status(ctx, "Deleting new commit clogs");
+ prep_status("Deleting new commit clogs");
- snprintf(old_clog_path, sizeof(old_clog_path), "%s/pg_clog", ctx->old.pgdata);
- snprintf(new_clog_path, sizeof(new_clog_path), "%s/pg_clog", ctx->new.pgdata);
- if (rmtree(new_clog_path, true) != true)
- pg_log(ctx, PG_FATAL, "Unable to delete directory %s\n", new_clog_path);
- check_ok(ctx);
+ snprintf(old_clog_path, sizeof(old_clog_path), "%s/pg_clog", old_cluster.pgdata);
+ snprintf(new_clog_path, sizeof(new_clog_path), "%s/pg_clog", new_cluster.pgdata);
+ if (!rmtree(new_clog_path, true))
+ pg_log(PG_FATAL, "unable to delete directory %s\n", new_clog_path);
+ check_ok();
- prep_status(ctx, "Copying old commit clogs to new server");
- /* libpgport's copydir() doesn't work in FRONTEND code */
+ prep_status("Copying old commit clogs to new server");
#ifndef WIN32
- exec_prog(ctx, true, SYSTEMQUOTE "%s \"%s\" \"%s\"" SYSTEMQUOTE,
+ exec_prog(true, SYSTEMQUOTE "%s \"%s\" \"%s\"" SYSTEMQUOTE,
"cp -Rf",
#else
/* flags: everything, no confirm, quiet, overwrite read-only */
- exec_prog(ctx, true, SYSTEMQUOTE "%s \"%s\" \"%s\\\"" SYSTEMQUOTE,
+ exec_prog(true, SYSTEMQUOTE "%s \"%s\" \"%s\\\"" SYSTEMQUOTE,
"xcopy /e /y /q /r",
#endif
old_clog_path, new_clog_path);
- check_ok(ctx);
+ check_ok();
/* set the next transaction id of the new cluster */
- prep_status(ctx, "Setting next transaction id for new cluster");
- exec_prog(ctx, true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -f -x %u \"%s\" > " DEVNULL SYSTEMQUOTE,
- ctx->new.bindir, ctx->old.controldata.chkpnt_nxtxid, ctx->new.pgdata);
- check_ok(ctx);
+ prep_status("Setting next transaction id for new cluster");
+ exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -f -x %u \"%s\" > " DEVNULL SYSTEMQUOTE,
+ new_cluster.bindir, old_cluster.controldata.chkpnt_nxtxid, new_cluster.pgdata);
+ check_ok();
/* now reset the wal archives in the new cluster */
- prep_status(ctx, "Resetting WAL archives");
- exec_prog(ctx, true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
- ctx->new.bindir, ctx->old.controldata.chkpnt_tli,
- ctx->old.controldata.logid, ctx->old.controldata.nxtlogseg,
- ctx->new.pgdata, ctx->logfile);
- check_ok(ctx);
+ prep_status("Resetting WAL archives");
+ exec_prog(true, SYSTEMQUOTE "\"%s/pg_resetxlog\" -l %u,%u,%u \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
+ new_cluster.bindir, old_cluster.controldata.chkpnt_tli,
+ old_cluster.controldata.logid, old_cluster.controldata.nxtlogseg,
+ new_cluster.pgdata, log_opts.filename);
+ check_ok();
}
@@ -297,7 +340,7 @@ copy_clog_xlog_xid(migratorContext *ctx)
*/
static
void
-set_frozenxids(migratorContext *ctx)
+set_frozenxids(void)
{
int dbnum;
PGconn *conn,
@@ -307,18 +350,18 @@ set_frozenxids(migratorContext *ctx)
int i_datname;
int i_datallowconn;
- prep_status(ctx, "Setting frozenxid counters in new cluster");
+ prep_status("Setting frozenxid counters in new cluster");
- conn_template1 = connectToServer(ctx, "template1", CLUSTER_NEW);
+ conn_template1 = connectToServer(&new_cluster, "template1");
/* set pg_database.datfrozenxid */
- PQclear(executeQueryOrDie(ctx, conn_template1,
+ PQclear(executeQueryOrDie(conn_template1,
"UPDATE pg_catalog.pg_database "
"SET datfrozenxid = '%u'",
- ctx->old.controldata.chkpnt_nxtxid));
+ old_cluster.controldata.chkpnt_nxtxid));
/* get database names */
- dbres = executeQueryOrDie(ctx, conn_template1,
+ dbres = executeQueryOrDie(conn_template1,
"SELECT datname, datallowconn "
"FROM pg_catalog.pg_database");
@@ -339,25 +382,25 @@ set_frozenxids(migratorContext *ctx)
* change datallowconn.
*/
if (strcmp(datallowconn, "f") == 0)
- PQclear(executeQueryOrDie(ctx, conn_template1,
+ PQclear(executeQueryOrDie(conn_template1,
"UPDATE pg_catalog.pg_database "
"SET datallowconn = true "
"WHERE datname = '%s'", datname));
- conn = connectToServer(ctx, datname, CLUSTER_NEW);
+ conn = connectToServer(&new_cluster, datname);
/* set pg_class.relfrozenxid */
- PQclear(executeQueryOrDie(ctx, conn,
+ PQclear(executeQueryOrDie(conn,
"UPDATE pg_catalog.pg_class "
"SET relfrozenxid = '%u' "
/* only heap and TOAST are vacuumed */
"WHERE relkind IN ('r', 't')",
- ctx->old.controldata.chkpnt_nxtxid));
+ old_cluster.controldata.chkpnt_nxtxid));
PQfinish(conn);
/* Reset datallowconn flag */
if (strcmp(datallowconn, "f") == 0)
- PQclear(executeQueryOrDie(ctx, conn_template1,
+ PQclear(executeQueryOrDie(conn_template1,
"UPDATE pg_catalog.pg_database "
"SET datallowconn = false "
"WHERE datname = '%s'", datname));
@@ -367,48 +410,25 @@ set_frozenxids(migratorContext *ctx)
PQfinish(conn_template1);
- check_ok(ctx);
+ check_ok();
}
static void
-cleanup(migratorContext *ctx)
+cleanup(void)
{
- int tblnum;
char filename[MAXPGPATH];
- for (tblnum = 0; tblnum < ctx->num_tablespaces; tblnum++)
- pg_free(ctx->tablespaces[tblnum]);
- pg_free(ctx->tablespaces);
-
- dbarr_free(&ctx->old.dbarr);
- dbarr_free(&ctx->new.dbarr);
- pg_free(ctx->logfile);
- pg_free(ctx->user);
- pg_free(ctx->old.major_version_str);
- pg_free(ctx->new.major_version_str);
- pg_free(ctx->old.controldata.lc_collate);
- pg_free(ctx->new.controldata.lc_collate);
- pg_free(ctx->old.controldata.lc_ctype);
- pg_free(ctx->new.controldata.lc_ctype);
- pg_free(ctx->old.controldata.encoding);
- pg_free(ctx->new.controldata.encoding);
- pg_free(ctx->old.tablespace_suffix);
- pg_free(ctx->new.tablespace_suffix);
-
- if (ctx->log_fd != NULL)
- {
- fclose(ctx->log_fd);
- ctx->log_fd = NULL;
- }
+ if (log_opts.fd)
+ fclose(log_opts.fd);
- if (ctx->debug_fd)
- fclose(ctx->debug_fd);
+ if (log_opts.debug_fd)
+ fclose(log_opts.debug_fd);
- snprintf(filename, sizeof(filename), "%s/%s", ctx->cwd, ALL_DUMP_FILE);
+ snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, ALL_DUMP_FILE);
unlink(filename);
- snprintf(filename, sizeof(filename), "%s/%s", ctx->cwd, GLOBALS_DUMP_FILE);
+ snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, GLOBALS_DUMP_FILE);
unlink(filename);
- snprintf(filename, sizeof(filename), "%s/%s", ctx->cwd, DB_DUMP_FILE);
+ snprintf(filename, sizeof(filename), "%s/%s", os_info.cwd, DB_DUMP_FILE);
unlink(filename);
}
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index b80f32778d..a3a0856309 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -1,8 +1,8 @@
/*
* pg_upgrade.h
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/pg_upgrade.h,v 1.15 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/pg_upgrade.h
*/
#include "postgres.h"
@@ -38,22 +38,29 @@
#define pg_copy_file copy_file
#define pg_mv_file rename
#define pg_link_file link
+#define RM_CMD "rm -f"
#define RMDIR_CMD "rm -rf"
-#define EXEC_EXT "sh"
+#define SCRIPT_EXT "sh"
#else
#define pg_copy_file CopyFile
#define pg_mv_file pgrename
#define pg_link_file win32_pghardlink
#define sleep(x) Sleep(x * 1000)
+#define RM_CMD "DEL /q"
#define RMDIR_CMD "RMDIR /s/q"
-#define EXEC_EXT "bat"
+#define SCRIPT_EXT "bat"
#define EXE_EXT ".exe"
#endif
-#define CLUSTERNAME(cluster) ((cluster) == CLUSTER_OLD ? "old" : "new")
+#define CLUSTER_NAME(cluster) ((cluster) == &old_cluster ? "old" : \
+ (cluster) == &new_cluster ? "new" : "none")
+
+#define atooid(x) ((Oid) strtoul((x), NULL, 10))
/* OID system catalog preservation added during PG 9.0 development */
-#define TABLE_SPACE_SUBDIRS 201001111
+#define TABLE_SPACE_SUBDIRS_CAT_VER 201001111
+/* postmaster/postgres -b (binary_upgrade) flag added during PG 9.1 development */
+#define BINARY_UPGRADE_SERVER_FLAG_CAT_VER 201104251
/*
* Each relation is represented by a relinfo structure.
@@ -62,9 +69,8 @@ typedef struct
{
char nspname[NAMEDATALEN]; /* namespace name */
char relname[NAMEDATALEN]; /* relation name */
- Oid reloid; /* relation oid */
- Oid relfilenode; /* relation relfile node */
- Oid toastrelid; /* oid of the toast relation */
+ Oid reloid; /* relation oid */
+ Oid relfilenode; /* relation relfile node */
char tablespace[MAXPGPATH]; /* relations tablespace path */
} RelInfo;
@@ -79,14 +85,18 @@ typedef struct
*/
typedef struct
{
- Oid old; /* Relfilenode of the old relation */
- Oid new; /* Relfilenode of the new relation */
- char old_file[MAXPGPATH];
- char new_file[MAXPGPATH];
- char old_nspname[NAMEDATALEN]; /* old name of the namespace */
- char old_relname[NAMEDATALEN]; /* old name of the relation */
- char new_nspname[NAMEDATALEN]; /* new name of the namespace */
- char new_relname[NAMEDATALEN]; /* new name of the relation */
+ char old_dir[MAXPGPATH];
+ char new_dir[MAXPGPATH];
+
+ /*
+ * old/new relfilenodes might differ for pg_largeobject(_metadata) indexes
+ * due to VACUUM FULL or REINDEX. Other relfilenodes are preserved.
+ */
+ Oid old_relfilenode;
+ Oid new_relfilenode;
+ /* the rest are used only for logging and error reporting */
+ char nspname[NAMEDATALEN]; /* namespaces */
+ char relname[NAMEDATALEN];
} FileNameMap;
/*
@@ -156,15 +166,6 @@ typedef enum
PG_DEBUG
} eLogType;
-/*
- * Enumeration to distinguish between old cluster and new cluster
- */
-typedef enum
-{
- NONE = 0, /* used for no running servers */
- CLUSTER_OLD,
- CLUSTER_NEW
-} Cluster;
typedef long pgpid_t;
@@ -182,7 +183,7 @@ typedef struct
char *bindir; /* pathname for cluster's executable directory */
unsigned short port; /* port number where postmaster is waiting */
uint32 major_version; /* PG_VERSION of cluster */
- char *major_version_str; /* string PG_VERSION of cluster */
+ char major_version_str[64]; /* string PG_VERSION of cluster */
Oid pg_database_oid; /* OID of pg_database relation */
char *libpath; /* pathname for cluster's pkglibdir */
char *tablespace_suffix; /* directory specification */
@@ -190,15 +191,34 @@ typedef struct
/*
- * migratorContext
- *
- * We create a migratorContext object to store all of the information
- * that we need to migrate a single cluster.
+ * LogOpts
+*/
+typedef struct
+{
+ char *filename; /* name of log file (may be /dev/null) */
+ FILE *fd; /* log FILE */
+ bool debug; /* TRUE -> log more information */
+ FILE *debug_fd; /* debug-level log FILE */
+ bool verbose; /* TRUE -> be verbose in messages */
+} LogOpts;
+
+
+/*
+ * UserOpts
+*/
+typedef struct
+{
+ bool check; /* TRUE -> ask user for permission to make
+ * changes */
+ transferMode transfer_mode; /* copy files or link them? */
+} UserOpts;
+
+
+/*
+ * OSInfo
*/
typedef struct
{
- ClusterInfo old,
- new; /* old and new cluster information */
const char *progname; /* complete pathname for this program */
char *exec_path; /* full path to my executable */
char *user; /* username for clusters */
@@ -207,63 +227,55 @@ typedef struct
int num_tablespaces;
char **libraries; /* loadable libraries */
int num_libraries;
- pgpid_t postmasterPID; /* PID of currently running postmaster */
- Cluster running_cluster;
-
- char *logfile; /* name of log file (may be /dev/null) */
- FILE *log_fd; /* log FILE */
- FILE *debug_fd; /* debug-level log FILE */
- bool check; /* TRUE -> ask user for permission to make
- * changes */
- bool verbose; /* TRUE -> be verbose in messages */
- bool debug; /* TRUE -> log more information */
- transferMode transfer_mode; /* copy files or link them? */
-} migratorContext;
+ ClusterInfo *running_cluster;
+} OSInfo;
/*
* Global variables
*/
+extern LogOpts log_opts;
+extern UserOpts user_opts;
+extern ClusterInfo old_cluster,
+ new_cluster;
+extern OSInfo os_info;
extern char scandir_file_pattern[];
/* check.c */
-void output_check_banner(migratorContext *ctx, bool *live_check);
-void check_old_cluster(migratorContext *ctx, bool live_check,
+void output_check_banner(bool *live_check);
+void check_old_cluster(bool live_check,
char **sequence_script_file_name);
-void check_new_cluster(migratorContext *ctx);
-void report_clusters_compatible(migratorContext *ctx);
-void issue_warnings(migratorContext *ctx,
- char *sequence_script_file_name);
-void output_completion_banner(migratorContext *ctx,
- char *deletion_script_file_name);
-void check_cluster_versions(migratorContext *ctx);
-void check_cluster_compatibility(migratorContext *ctx, bool live_check);
-void create_script_for_old_cluster_deletion(migratorContext *ctx,
- char **deletion_script_file_name);
+void check_new_cluster(void);
+void report_clusters_compatible(void);
+void issue_warnings(char *sequence_script_file_name);
+void output_completion_banner(char *deletion_script_file_name);
+void check_cluster_versions(void);
+void check_cluster_compatibility(bool live_check);
+void create_script_for_old_cluster_deletion(char **deletion_script_file_name);
/* controldata.c */
-void get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check);
-void check_control_data(migratorContext *ctx, ControlData *oldctrl,
+void get_control_data(ClusterInfo *cluster, bool live_check);
+void check_control_data(ControlData *oldctrl,
ControlData *newctrl);
/* dump.c */
-void generate_old_dump(migratorContext *ctx);
-void split_old_dump(migratorContext *ctx);
+void generate_old_dump(void);
+void split_old_dump(void);
/* exec.c */
-int exec_prog(migratorContext *ctx, bool throw_error,
+int exec_prog(bool throw_error,
const char *cmd,...);
-void verify_directories(migratorContext *ctx);
-bool is_server_running(migratorContext *ctx, const char *datadir);
-void rename_old_pg_control(migratorContext *ctx);
+void verify_directories(void);
+bool is_server_running(const char *datadir);
+void rename_old_pg_control(void);
/* file.c */
@@ -292,109 +304,94 @@ typedef struct
pluginShutdown shutdown; /* Pointer to plugin's shutdown function */
} pageCnvCtx;
-const char *setupPageConverter(migratorContext *ctx, pageCnvCtx **result);
+const char *setupPageConverter(pageCnvCtx **result);
#else
/* dummy */
typedef void *pageCnvCtx;
#endif
int dir_matching_filenames(const struct dirent * scan_ent);
-int pg_scandir(migratorContext *ctx, const char *dirname,
- struct dirent *** namelist,
+int pg_scandir(const char *dirname, struct dirent *** namelist,
int (*selector) (const struct dirent *));
-const char *copyAndUpdateFile(migratorContext *ctx,
- pageCnvCtx *pageConverter, const char *src,
+const char *copyAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
const char *dst, bool force);
-const char *linkAndUpdateFile(migratorContext *ctx,
- pageCnvCtx *pageConverter, const char *src, const char *dst);
+const char *linkAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
+ const char *dst);
-void check_hard_link(migratorContext *ctx);
+void check_hard_link(void);
/* function.c */
-void install_support_functions(migratorContext *ctx);
-void uninstall_support_functions(migratorContext *ctx);
-void get_loadable_libraries(migratorContext *ctx);
-void check_loadable_libraries(migratorContext *ctx);
+void install_support_functions_in_new_db(const char *db_name);
+void uninstall_support_functions_from_new_cluster(void);
+void get_loadable_libraries(void);
+void check_loadable_libraries(void);
/* info.c */
-FileNameMap *gen_db_file_maps(migratorContext *ctx, DbInfo *old_db,
+FileNameMap *gen_db_file_maps(DbInfo *old_db,
DbInfo *new_db, int *nmaps, const char *old_pgdata,
const char *new_pgdata);
-void get_db_and_rel_infos(migratorContext *ctx, DbInfoArr *db_arr,
- Cluster whichCluster);
-DbInfo *dbarr_lookup_db(DbInfoArr *db_arr, const char *db_name);
-void dbarr_free(DbInfoArr *db_arr);
-void print_maps(migratorContext *ctx, FileNameMap *maps, int n,
- const char *dbName);
+void get_db_and_rel_infos(ClusterInfo *cluster);
+void free_db_and_rel_infos(DbInfoArr *db_arr);
+void print_maps(FileNameMap *maps, int n,
+ const char *db_name);
/* option.c */
-void parseCommandLine(migratorContext *ctx, int argc, char *argv[]);
+void parseCommandLine(int argc, char *argv[]);
/* relfilenode.c */
-void get_pg_database_relfilenode(migratorContext *ctx, Cluster whichCluster);
-const char *transfer_all_new_dbs(migratorContext *ctx, DbInfoArr *olddb_arr,
+void get_pg_database_relfilenode(ClusterInfo *cluster);
+const char *transfer_all_new_dbs(DbInfoArr *olddb_arr,
DbInfoArr *newdb_arr, char *old_pgdata, char *new_pgdata);
/* tablespace.c */
-void init_tablespaces(migratorContext *ctx);
+void init_tablespaces(void);
/* server.c */
-PGconn *connectToServer(migratorContext *ctx, const char *db_name,
- Cluster whichCluster);
-PGresult *executeQueryOrDie(migratorContext *ctx, PGconn *conn,
- const char *fmt,...);
+PGconn *connectToServer(ClusterInfo *cluster, const char *db_name);
+PGresult *executeQueryOrDie(PGconn *conn, const char *fmt,...);
-void start_postmaster(migratorContext *ctx, Cluster whichCluster, bool quiet);
-void stop_postmaster(migratorContext *ctx, bool fast, bool quiet);
-uint32 get_major_server_version(migratorContext *ctx, char **verstr,
- Cluster whichCluster);
-void check_for_libpq_envvars(migratorContext *ctx);
+void start_postmaster(ClusterInfo *cluster);
+void stop_postmaster(bool fast);
+uint32 get_major_server_version(ClusterInfo *cluster);
+void check_pghost_envvar(void);
/* util.c */
-void exit_nicely(migratorContext *ctx, bool need_cleanup);
-void *pg_malloc(migratorContext *ctx, int n);
-void pg_free(void *p);
-char *pg_strdup(migratorContext *ctx, const char *s);
-char *quote_identifier(migratorContext *ctx, const char *s);
-int get_user_info(migratorContext *ctx, char **user_name);
-void check_ok(migratorContext *ctx);
-void report_status(migratorContext *ctx, eLogType type, const char *fmt,...);
-void pg_log(migratorContext *ctx, eLogType type, char *fmt,...);
-void prep_status(migratorContext *ctx, const char *fmt,...);
-void check_ok(migratorContext *ctx);
-char *pg_strdup(migratorContext *ctx, const char *s);
-void *pg_malloc(migratorContext *ctx, int size);
+char *quote_identifier(const char *s);
+int get_user_info(char **user_name);
+void check_ok(void);
+void report_status(eLogType type, const char *fmt,...);
+void pg_log(eLogType type, char *fmt,...);
+void prep_status(const char *fmt,...);
+void check_ok(void);
+char *pg_strdup(const char *s);
+void *pg_malloc(int size);
void pg_free(void *ptr);
const char *getErrorText(int errNum);
+unsigned int str2uint(const char *str);
+void pg_putenv(const char *var, const char *val);
+
/* version.c */
-void new_9_0_populate_pg_largeobject_metadata(migratorContext *ctx,
- bool check_mode, Cluster whichCluster);
+void new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster,
+ bool check_mode);
/* version_old_8_3.c */
-void old_8_3_check_for_name_data_type_usage(migratorContext *ctx,
- Cluster whichCluster);
-void old_8_3_check_for_tsquery_usage(migratorContext *ctx,
- Cluster whichCluster);
-void old_8_3_check_for_isn_and_int8_passing_mismatch(migratorContext *ctx,
- Cluster whichCluster);
-void old_8_3_rebuild_tsvector_tables(migratorContext *ctx,
- bool check_mode, Cluster whichCluster);
-void old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx,
- bool check_mode, Cluster whichCluster);
-void old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx,
- bool check_mode, Cluster whichCluster);
-char *old_8_3_create_sequence_script(migratorContext *ctx,
- Cluster whichCluster);
+void old_8_3_check_for_name_data_type_usage(ClusterInfo *cluster);
+void old_8_3_check_for_tsquery_usage(ClusterInfo *cluster);
+void old_8_3_rebuild_tsvector_tables(ClusterInfo *cluster, bool check_mode);
+void old_8_3_invalidate_hash_gin_indexes(ClusterInfo *cluster, bool check_mode);
+void old_8_3_invalidate_bpchar_pattern_ops_indexes(ClusterInfo *cluster,
+ bool check_mode);
+char *old_8_3_create_sequence_script(ClusterInfo *cluster);
diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c
index 1ef176a041..9a0a3ac18d 100644
--- a/contrib/pg_upgrade/relfilenode.c
+++ b/contrib/pg_upgrade/relfilenode.c
@@ -3,8 +3,8 @@
*
* relfilenode functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/relfilenode.c,v 1.8 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/relfilenode.c
*/
#include "pg_upgrade.h"
@@ -13,12 +13,11 @@
#include "access/transam.h"
-static void transfer_single_new_db(migratorContext *ctx, pageCnvCtx *pageConverter,
+static void transfer_single_new_db(pageCnvCtx *pageConverter,
FileNameMap *maps, int size);
-static void transfer_relfile(migratorContext *ctx, pageCnvCtx *pageConverter,
+static void transfer_relfile(pageCnvCtx *pageConverter,
const char *fromfile, const char *tofile,
- const char *oldnspname, const char *oldrelname,
- const char *newnspname, const char *newrelname);
+ const char *nspname, const char *relname);
/* used by scandir(), must be global */
char scandir_file_pattern[MAXPGPATH];
@@ -30,41 +29,48 @@ char scandir_file_pattern[MAXPGPATH];
* physically link the databases.
*/
const char *
-transfer_all_new_dbs(migratorContext *ctx, DbInfoArr *olddb_arr,
- DbInfoArr *newdb_arr, char *old_pgdata, char *new_pgdata)
+transfer_all_new_dbs(DbInfoArr *old_db_arr,
+ DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
{
int dbnum;
const char *msg = NULL;
- prep_status(ctx, "Restoring user relation files\n");
+ prep_status("Restoring user relation files\n");
- for (dbnum = 0; dbnum < newdb_arr->ndbs; dbnum++)
+ if (old_db_arr->ndbs != new_db_arr->ndbs)
+ pg_log(PG_FATAL, "old and new clusters have a different number of databases\n");
+
+ for (dbnum = 0; dbnum < old_db_arr->ndbs; dbnum++)
{
- DbInfo *new_db = &newdb_arr->dbs[dbnum];
- DbInfo *old_db = dbarr_lookup_db(olddb_arr, new_db->db_name);
+ DbInfo *old_db = &old_db_arr->dbs[dbnum];
+ DbInfo *new_db = &new_db_arr->dbs[dbnum];
FileNameMap *mappings;
int n_maps;
pageCnvCtx *pageConverter = NULL;
+ if (strcmp(old_db->db_name, new_db->db_name) != 0)
+ pg_log(PG_FATAL, "old and new databases have different names: old \"%s\", new \"%s\"\n",
+ old_db->db_name, new_db->db_name);
+
n_maps = 0;
- mappings = gen_db_file_maps(ctx, old_db, new_db, &n_maps, old_pgdata,
+ mappings = gen_db_file_maps(old_db, new_db, &n_maps, old_pgdata,
new_pgdata);
if (n_maps)
{
- print_maps(ctx, mappings, n_maps, new_db->db_name);
+ print_maps(mappings, n_maps, new_db->db_name);
#ifdef PAGE_CONVERSION
- msg = setupPageConverter(ctx, &pageConverter);
+ msg = setupPageConverter(&pageConverter);
#endif
- transfer_single_new_db(ctx, pageConverter, mappings, n_maps);
+ transfer_single_new_db(pageConverter, mappings, n_maps);
pg_free(mappings);
}
}
- prep_status(ctx, ""); /* in case nothing printed */
- check_ok(ctx);
+ prep_status(""); /* in case nothing printed */
+ check_ok();
return msg;
}
@@ -77,13 +83,13 @@ transfer_all_new_dbs(migratorContext *ctx, DbInfoArr *olddb_arr,
* relfilenodes later in the upgrade process.
*/
void
-get_pg_database_relfilenode(migratorContext *ctx, Cluster whichCluster)
+get_pg_database_relfilenode(ClusterInfo *cluster)
{
- PGconn *conn = connectToServer(ctx, "template1", whichCluster);
+ PGconn *conn = connectToServer(cluster, "template1");
PGresult *res;
int i_relfile;
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT c.relname, c.relfilenode "
"FROM pg_catalog.pg_class c, "
" pg_catalog.pg_namespace n "
@@ -93,10 +99,7 @@ get_pg_database_relfilenode(migratorContext *ctx, Cluster whichCluster)
"ORDER BY c.relname");
i_relfile = PQfnumber(res, "relfilenode");
- if (whichCluster == CLUSTER_OLD)
- ctx->old.pg_database_oid = atol(PQgetvalue(res, 0, i_relfile));
- else
- ctx->new.pg_database_oid = atol(PQgetvalue(res, 0, i_relfile));
+ cluster->pg_database_oid = atooid(PQgetvalue(res, 0, i_relfile));
PQclear(res);
PQfinish(conn);
@@ -109,57 +112,75 @@ get_pg_database_relfilenode(migratorContext *ctx, Cluster whichCluster)
* create links for mappings stored in "maps" array.
*/
static void
-transfer_single_new_db(migratorContext *ctx, pageCnvCtx *pageConverter,
+transfer_single_new_db(pageCnvCtx *pageConverter,
FileNameMap *maps, int size)
{
+ char old_dir[MAXPGPATH];
+ struct dirent **namelist = NULL;
+ int numFiles = 0;
int mapnum;
+ int fileno;
+
+ old_dir[0] = '\0';
for (mapnum = 0; mapnum < size; mapnum++)
{
char old_file[MAXPGPATH];
char new_file[MAXPGPATH];
- struct dirent **namelist = NULL;
- int numFiles;
+
+ /* Changed tablespaces? Need a new directory scan? */
+ if (strcmp(maps[mapnum].old_dir, old_dir) != 0)
+ {
+ if (numFiles > 0)
+ {
+ for (fileno = 0; fileno < numFiles; fileno++)
+ pg_free(namelist[fileno]);
+ pg_free(namelist);
+ }
+
+ snprintf(old_dir, sizeof(old_dir), "%s", maps[mapnum].old_dir);
+ numFiles = pg_scandir(old_dir, &namelist, NULL);
+ }
/* Copying files might take some time, so give feedback. */
- snprintf(old_file, sizeof(old_file), "%s/%u", maps[mapnum].old_file, maps[mapnum].old);
- snprintf(new_file, sizeof(new_file), "%s/%u", maps[mapnum].new_file, maps[mapnum].new);
- pg_log(ctx, PG_REPORT, OVERWRITE_MESSAGE, old_file);
+ snprintf(old_file, sizeof(old_file), "%s/%u", maps[mapnum].old_dir,
+ maps[mapnum].old_relfilenode);
+ snprintf(new_file, sizeof(new_file), "%s/%u", maps[mapnum].new_dir,
+ maps[mapnum].new_relfilenode);
+ pg_log(PG_REPORT, OVERWRITE_MESSAGE, old_file);
/*
* Copy/link the relation file to the new cluster
*/
unlink(new_file);
- transfer_relfile(ctx, pageConverter, old_file, new_file,
- maps[mapnum].old_nspname, maps[mapnum].old_relname,
- maps[mapnum].new_nspname, maps[mapnum].new_relname);
+ transfer_relfile(pageConverter, old_file, new_file,
+ maps[mapnum].nspname, maps[mapnum].relname);
/* fsm/vm files added in PG 8.4 */
- if (GET_MAJOR_VERSION(ctx->old.major_version) >= 804)
+ if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
{
/*
- * Now copy/link any fsm and vm files, if they exist
+ * Copy/link any fsm and vm files, if they exist
*/
- snprintf(scandir_file_pattern, sizeof(scandir_file_pattern), "%u_", maps[mapnum].old);
- numFiles = pg_scandir(ctx, maps[mapnum].old_file, &namelist, dir_matching_filenames);
+ snprintf(scandir_file_pattern, sizeof(scandir_file_pattern), "%u_",
+ maps[mapnum].old_relfilenode);
- while (numFiles--)
+ for (fileno = 0; fileno < numFiles; fileno++)
{
- snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_file,
- namelist[numFiles]->d_name);
- snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_file,
- maps[mapnum].new, strchr(namelist[numFiles]->d_name, '_'));
-
- unlink(new_file);
- transfer_relfile(ctx, pageConverter, old_file, new_file,
- maps[mapnum].old_nspname, maps[mapnum].old_relname,
- maps[mapnum].new_nspname, maps[mapnum].new_relname);
-
- pg_free(namelist[numFiles]);
+ if (strncmp(namelist[fileno]->d_name, scandir_file_pattern,
+ strlen(scandir_file_pattern)) == 0)
+ {
+ snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_dir,
+ namelist[fileno]->d_name);
+ snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_dir,
+ maps[mapnum].new_relfilenode, strchr(namelist[fileno]->d_name, '_'));
+
+ unlink(new_file);
+ transfer_relfile(pageConverter, old_file, new_file,
+ maps[mapnum].nspname, maps[mapnum].relname);
+ }
}
-
- pg_free(namelist);
}
/*
@@ -169,24 +190,31 @@ transfer_single_new_db(migratorContext *ctx, pageCnvCtx *pageConverter,
* relfilenode.3, ... 'fsm' and 'vm' files use underscores so are not
* copied.
*/
- snprintf(scandir_file_pattern, sizeof(scandir_file_pattern), "%u.", maps[mapnum].old);
- numFiles = pg_scandir(ctx, maps[mapnum].old_file, &namelist, dir_matching_filenames);
+ snprintf(scandir_file_pattern, sizeof(scandir_file_pattern), "%u.",
+ maps[mapnum].old_relfilenode);
- while (numFiles--)
+ for (fileno = 0; fileno < numFiles; fileno++)
{
- snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_file,
- namelist[numFiles]->d_name);
- snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_file,
- maps[mapnum].new, strchr(namelist[numFiles]->d_name, '.'));
-
- unlink(new_file);
- transfer_relfile(ctx, pageConverter, old_file, new_file,
- maps[mapnum].old_nspname, maps[mapnum].old_relname,
- maps[mapnum].new_nspname, maps[mapnum].new_relname);
+ if (strncmp(namelist[fileno]->d_name, scandir_file_pattern,
+ strlen(scandir_file_pattern)) == 0)
+ {
+ snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_dir,
+ namelist[fileno]->d_name);
+ snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_dir,
+ maps[mapnum].new_relfilenode, strchr(namelist[fileno]->d_name, '.'));
- pg_free(namelist[numFiles]);
+ unlink(new_file);
+ transfer_relfile(pageConverter, old_file, new_file,
+ maps[mapnum].nspname, maps[mapnum].relname);
+ }
}
+ }
+
+ if (numFiles > 0)
+ {
+ for (fileno = 0; fileno < numFiles; fileno++)
+ pg_free(namelist[fileno]);
pg_free(namelist);
}
}
@@ -198,33 +226,31 @@ transfer_single_new_db(migratorContext *ctx, pageCnvCtx *pageConverter,
* Copy or link file from old cluster to new one.
*/
static void
-transfer_relfile(migratorContext *ctx, pageCnvCtx *pageConverter, const char *oldfile,
- const char *newfile, const char *oldnspname, const char *oldrelname,
- const char *newnspname, const char *newrelname)
+transfer_relfile(pageCnvCtx *pageConverter, const char *old_file,
+ const char *new_file, const char *nspname, const char *relname)
{
const char *msg;
- if ((ctx->transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
- pg_log(ctx, PG_FATAL, "this migration requires page-by-page conversion, "
+ if ((user_opts.transfer_mode == TRANSFER_MODE_LINK) && (pageConverter != NULL))
+ pg_log(PG_FATAL, "this upgrade requires page-by-page conversion, "
"you must use copy-mode instead of link-mode\n");
- if (ctx->transfer_mode == TRANSFER_MODE_COPY)
+ if (user_opts.transfer_mode == TRANSFER_MODE_COPY)
{
- pg_log(ctx, PG_INFO, "copying %s to %s\n", oldfile, newfile);
+ pg_log(PG_INFO, "copying %s to %s\n", old_file, new_file);
- if ((msg = copyAndUpdateFile(ctx, pageConverter, oldfile, newfile, true)) != NULL)
- pg_log(ctx, PG_FATAL, "error while copying %s.%s(%s) to %s.%s(%s): %s\n",
- oldnspname, oldrelname, oldfile, newnspname, newrelname, newfile, msg);
+ if ((msg = copyAndUpdateFile(pageConverter, old_file, new_file, true)) != NULL)
+ pg_log(PG_FATAL, "error while copying %s.%s (%s to %s): %s\n",
+ nspname, relname, old_file, new_file, msg);
}
else
{
- pg_log(ctx, PG_INFO, "linking %s to %s\n", newfile, oldfile);
+ pg_log(PG_INFO, "linking %s to %s\n", old_file, new_file);
- if ((msg = linkAndUpdateFile(ctx, pageConverter, oldfile, newfile)) != NULL)
- pg_log(ctx, PG_FATAL,
- "error while creating link from %s.%s(%s) to %s.%s(%s): %s\n",
- oldnspname, oldrelname, oldfile, newnspname, newrelname,
- newfile, msg);
+ if ((msg = linkAndUpdateFile(pageConverter, old_file, new_file)) != NULL)
+ pg_log(PG_FATAL,
+ "error while creating link from %s.%s (%s to %s): %s\n",
+ nspname, relname, old_file, new_file, msg);
}
return;
}
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
index a9243ab75a..58c1234a94 100644
--- a/contrib/pg_upgrade/server.c
+++ b/contrib/pg_upgrade/server.c
@@ -3,20 +3,14 @@
*
* database server functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/server.c,v 1.8 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/server.c
*/
#include "pg_upgrade.h"
-#define POSTMASTER_UPTIME 20
-#define STARTUP_WARNING_TRIES 2
-
-
-static pgpid_t get_postmaster_pid(migratorContext *ctx, const char *datadir);
-static bool test_server_conn(migratorContext *ctx, int timeout,
- Cluster whichCluster);
+static PGconn *get_db_conn(ClusterInfo *cluster, const char *db_name);
/*
@@ -24,31 +18,23 @@ static bool test_server_conn(migratorContext *ctx, int timeout,
*
* Connects to the desired database on the designated server.
* If the connection attempt fails, this function logs an error
- * message and calls exit_nicely() to kill the program.
+ * message and calls exit() to kill the program.
*/
PGconn *
-connectToServer(migratorContext *ctx, const char *db_name,
- Cluster whichCluster)
+connectToServer(ClusterInfo *cluster, const char *db_name)
{
- char connectString[MAXPGPATH];
- unsigned short port = (whichCluster == CLUSTER_OLD) ?
- ctx->old.port : ctx->new.port;
- PGconn *conn;
-
- snprintf(connectString, sizeof(connectString),
- "dbname = '%s' user = '%s' port = %d", db_name, ctx->user, port);
-
- conn = PQconnectdb(connectString);
+ PGconn *conn = get_db_conn(cluster, db_name);
if (conn == NULL || PQstatus(conn) != CONNECTION_OK)
{
- pg_log(ctx, PG_REPORT, "Connection to database failed: %s\n",
+ pg_log(PG_REPORT, "connection to database failed: %s\n",
PQerrorMessage(conn));
if (conn)
PQfinish(conn);
- exit_nicely(ctx, true);
+ printf("Failure, exiting\n");
+ exit(1);
}
return conn;
@@ -56,14 +42,32 @@ connectToServer(migratorContext *ctx, const char *db_name,
/*
+ * get_db_conn()
+ *
+ * get database connection
+ */
+static PGconn *
+get_db_conn(ClusterInfo *cluster, const char *db_name)
+{
+ char conn_opts[MAXPGPATH];
+
+ snprintf(conn_opts, sizeof(conn_opts),
+ "dbname = '%s' user = '%s' port = %d", db_name, os_info.user,
+ cluster->port);
+
+ return PQconnectdb(conn_opts);
+}
+
+
+/*
* executeQueryOrDie()
*
* Formats a query string from the given arguments and executes the
* resulting query. If the query fails, this function logs an error
- * message and calls exit_nicely() to kill the program.
+ * message and calls exit() to kill the program.
*/
PGresult *
-executeQueryOrDie(migratorContext *ctx, PGconn *conn, const char *fmt,...)
+executeQueryOrDie(PGconn *conn, const char *fmt,...)
{
static char command[8192];
va_list args;
@@ -74,18 +78,18 @@ executeQueryOrDie(migratorContext *ctx, PGconn *conn, const char *fmt,...)
vsnprintf(command, sizeof(command), fmt, args);
va_end(args);
- pg_log(ctx, PG_DEBUG, "executing: %s\n", command);
+ pg_log(PG_DEBUG, "executing: %s\n", command);
result = PQexec(conn, command);
status = PQresultStatus(result);
if ((status != PGRES_TUPLES_OK) && (status != PGRES_COMMAND_OK))
{
- pg_log(ctx, PG_REPORT, "DB command failed\n%s\n%s\n", command,
+ pg_log(PG_REPORT, "DB command failed\n%s\n%s\n", command,
PQerrorMessage(conn));
PQclear(result);
PQfinish(conn);
- exit_nicely(ctx, true);
- return NULL; /* Never get here, but keeps compiler happy */
+ printf("Failure, exiting\n");
+ exit(1);
}
else
return result;
@@ -93,38 +97,6 @@ executeQueryOrDie(migratorContext *ctx, PGconn *conn, const char *fmt,...)
/*
- * get_postmaster_pid()
- *
- * Returns the pid of the postmaster running on datadir. pid is retrieved
- * from the postmaster.pid file
- */
-static pgpid_t
-get_postmaster_pid(migratorContext *ctx, const char *datadir)
-{
- FILE *pidf;
- long pid;
- char pid_file[MAXPGPATH];
-
- snprintf(pid_file, sizeof(pid_file), "%s/postmaster.pid", datadir);
- pidf = fopen(pid_file, "r");
-
- if (pidf == NULL)
- return (pgpid_t) 0;
-
- if (fscanf(pidf, "%ld", &pid) != 1)
- {
- fclose(pidf);
- pg_log(ctx, PG_FATAL, "%s: invalid data in PID file \"%s\"\n",
- ctx->progname, pid_file);
- }
-
- fclose(pidf);
-
- return (pgpid_t) pid;
-}
-
-
-/*
* get_major_server_version()
*
* gets the version (in unsigned int form) for the given "datadir". Assumes
@@ -132,208 +104,187 @@ get_postmaster_pid(migratorContext *ctx, const char *datadir)
* is retrieved by reading the PG_VERSION file.
*/
uint32
-get_major_server_version(migratorContext *ctx, char **verstr, Cluster whichCluster)
+get_major_server_version(ClusterInfo *cluster)
{
- const char *datadir = whichCluster == CLUSTER_OLD ?
- ctx->old.pgdata : ctx->new.pgdata;
+ const char *datadir = cluster->pgdata;
FILE *version_fd;
- char ver_file[MAXPGPATH];
+ char ver_filename[MAXPGPATH];
int integer_version = 0;
int fractional_version = 0;
- *verstr = pg_malloc(ctx, 64);
-
- snprintf(ver_file, sizeof(ver_file), "%s/PG_VERSION", datadir);
- if ((version_fd = fopen(ver_file, "r")) == NULL)
+ snprintf(ver_filename, sizeof(ver_filename), "%s/PG_VERSION", datadir);
+ if ((version_fd = fopen(ver_filename, "r")) == NULL)
return 0;
- if (fscanf(version_fd, "%63s", *verstr) == 0 ||
- sscanf(*verstr, "%d.%d", &integer_version, &fractional_version) != 2)
- {
- pg_log(ctx, PG_FATAL, "could not get version from %s\n", datadir);
- fclose(version_fd);
- return 0;
- }
+ if (fscanf(version_fd, "%63s", cluster->major_version_str) == 0 ||
+ sscanf(cluster->major_version_str, "%d.%d", &integer_version,
+ &fractional_version) != 2)
+ pg_log(PG_FATAL, "could not get version from %s\n", datadir);
+
+ fclose(version_fd);
return (100 * integer_version + fractional_version) * 100;
}
+static void
+#ifdef HAVE_ATEXIT
+stop_postmaster_atexit(void)
+#else
+stop_postmaster_on_exit(int exitstatus, void *arg)
+#endif
+{
+ stop_postmaster(true);
+
+}
+
+
void
-start_postmaster(migratorContext *ctx, Cluster whichCluster, bool quiet)
+start_postmaster(ClusterInfo *cluster)
{
char cmd[MAXPGPATH];
- const char *bindir;
- const char *datadir;
- unsigned short port;
+ PGconn *conn;
+ bool exit_hook_registered = false;
+ int pg_ctl_return = 0;
- if (whichCluster == CLUSTER_OLD)
- {
- bindir = ctx->old.bindir;
- datadir = ctx->old.pgdata;
- port = ctx->old.port;
- }
- else
- {
- bindir = ctx->new.bindir;
- datadir = ctx->new.pgdata;
- port = ctx->new.port;
- }
+#ifndef WIN32
+ char *output_filename = log_opts.filename;
+#else
/*
- * On Win32, we can't send both server output and pg_ctl output to the
+ * On Win32, we can't send both pg_upgrade output and pg_ctl output to the
* same file because we get the error: "The process cannot access the file
- * because it is being used by another process." so we have to send pg_ctl
- * output to 'nul'.
+ * because it is being used by another process." so we have to send all
+ * other output to 'nul'.
*/
- snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -l \"%s\" -D \"%s\" "
- "-o \"-p %d -c autovacuum=off "
- "-c autovacuum_freeze_max_age=2000000000\" "
- "start >> \"%s\" 2>&1" SYSTEMQUOTE,
- bindir, ctx->logfile, datadir, port,
-#ifndef WIN32
- ctx->logfile);
+ char *output_filename = DEVNULL;
+#endif
+
+ if (!exit_hook_registered)
+ {
+#ifdef HAVE_ATEXIT
+ atexit(stop_postmaster_atexit);
#else
- DEVNULL);
+ on_exit(stop_postmaster_on_exit);
#endif
- exec_prog(ctx, true, "%s", cmd);
+ exit_hook_registered = true;
+ }
- /* wait for the server to start properly */
+ /*
+ * Using autovacuum=off disables cleanup vacuum and analyze, but freeze
+ * vacuums can still happen, so we set autovacuum_freeze_max_age to its
+ * maximum. We assume all datfrozenxid and relfrozen values are less than
+ * a gap of 2000000000 from the current xid counter, so autovacuum will
+ * not touch them.
+ */
+ snprintf(cmd, sizeof(cmd),
+ SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" "
+ "-o \"-p %d %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE,
+ cluster->bindir, output_filename, cluster->pgdata, cluster->port,
+ (cluster->controldata.cat_ver >=
+ BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" :
+ "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
+ log_opts.filename);
- if (test_server_conn(ctx, POSTMASTER_UPTIME, whichCluster) == false)
- pg_log(ctx, PG_FATAL, " Unable to start %s postmaster with the command: %s\nPerhaps pg_hba.conf was not set to \"trust\".",
- CLUSTERNAME(whichCluster), cmd);
+ /*
+ * Don't throw an error right away, let connecting throw the error because
+ * it might supply a reason for the failure.
+ */
+ pg_ctl_return = exec_prog(false, "%s", cmd);
- if ((ctx->postmasterPID = get_postmaster_pid(ctx, datadir)) == 0)
- pg_log(ctx, PG_FATAL, " Unable to get postmaster pid\n");
- ctx->running_cluster = whichCluster;
+ /* Check to see if we can connect to the server; if not, report it. */
+ if ((conn = get_db_conn(cluster, "template1")) == NULL ||
+ PQstatus(conn) != CONNECTION_OK)
+ {
+ pg_log(PG_REPORT, "\nconnection to database failed: %s\n",
+ PQerrorMessage(conn));
+ if (conn)
+ PQfinish(conn);
+ pg_log(PG_FATAL, "unable to connect to %s postmaster started with the command: %s\n",
+ CLUSTER_NAME(cluster), cmd);
+ }
+ PQfinish(conn);
+
+ /* If the connection didn't fail, fail now */
+ if (pg_ctl_return != 0)
+ pg_log(PG_FATAL, "pg_ctl failed to start the %s server\n",
+ CLUSTER_NAME(cluster));
+
+ os_info.running_cluster = cluster;
}
void
-stop_postmaster(migratorContext *ctx, bool fast, bool quiet)
+stop_postmaster(bool fast)
{
char cmd[MAXPGPATH];
const char *bindir;
const char *datadir;
- if (ctx->running_cluster == CLUSTER_OLD)
+#ifndef WIN32
+ char *output_filename = log_opts.filename;
+#else
+ /* See comment in start_postmaster() about why win32 output is ignored. */
+ char *output_filename = DEVNULL;
+#endif
+
+ if (os_info.running_cluster == &old_cluster)
{
- bindir = ctx->old.bindir;
- datadir = ctx->old.pgdata;
+ bindir = old_cluster.bindir;
+ datadir = old_cluster.pgdata;
}
- else if (ctx->running_cluster == CLUSTER_NEW)
+ else if (os_info.running_cluster == &new_cluster)
{
- bindir = ctx->new.bindir;
- datadir = ctx->new.pgdata;
+ bindir = new_cluster.bindir;
+ datadir = new_cluster.pgdata;
}
else
return; /* no cluster running */
- /* See comment in start_postmaster() about why win32 output is ignored. */
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s/pg_ctl\" -l \"%s\" -D \"%s\" %s stop >> "
+ SYSTEMQUOTE "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" %s stop >> "
"\"%s\" 2>&1" SYSTEMQUOTE,
- bindir, ctx->logfile, datadir, fast ? "-m fast" : "",
-#ifndef WIN32
- ctx->logfile);
-#else
- DEVNULL);
-#endif
- exec_prog(ctx, fast ? false : true, "%s", cmd);
-
- ctx->postmasterPID = 0;
- ctx->running_cluster = NONE;
-}
-
-
-/*
- * test_server_conn()
- *
- * tests whether postmaster is running or not by trying to connect
- * to it. If connection is unsuccessfull we do a sleep of 1 sec and then
- * try the connection again. This process continues "timeout" times.
- *
- * Returns true if the connection attempt was successfull, false otherwise.
- */
-static bool
-test_server_conn(migratorContext *ctx, int timeout, Cluster whichCluster)
-{
- PGconn *conn = NULL;
- char con_opts[MAX_STRING];
- int tries;
- unsigned short port = (whichCluster == CLUSTER_OLD) ?
- ctx->old.port : ctx->new.port;
- bool ret = false;
-
- snprintf(con_opts, sizeof(con_opts),
- "dbname = 'template1' user = '%s' port = %d ", ctx->user, port);
+ bindir, output_filename, datadir, fast ? "-m fast" : "",
+ output_filename);
- for (tries = 0; tries < timeout; tries++)
- {
- sleep(1);
- if ((conn = PQconnectdb(con_opts)) != NULL &&
- PQstatus(conn) == CONNECTION_OK)
- {
- PQfinish(conn);
- ret = true;
- break;
- }
-
- if (tries == STARTUP_WARNING_TRIES)
- prep_status(ctx, "Trying to start %s server ",
- CLUSTERNAME(whichCluster));
- else if (tries > STARTUP_WARNING_TRIES)
- pg_log(ctx, PG_REPORT, ".");
- }
+ exec_prog(fast ? false : true, "%s", cmd);
- if (tries > STARTUP_WARNING_TRIES)
- check_ok(ctx);
-
- return ret;
+ os_info.running_cluster = NULL;
}
/*
- * check_for_libpq_envvars()
- *
- * tests whether any libpq environment variables are set.
- * Since pg_upgrade connects to both the old and the new server,
- * it is potentially dangerous to have any of these set.
+ * check_pghost_envvar()
*
- * If any are found, will log them and cancel.
+ * Tests that PGHOST does not point to a non-local server
*/
void
-check_for_libpq_envvars(migratorContext *ctx)
+check_pghost_envvar(void)
{
PQconninfoOption *option;
PQconninfoOption *start;
- bool found = false;
/* Get valid libpq env vars from the PQconndefaults function */
- start = option = PQconndefaults();
+ start = PQconndefaults();
- while (option->keyword != NULL)
+ for (option = start; option->keyword != NULL; option++)
{
- const char *value;
-
- if (option->envvar && (value = getenv(option->envvar)) && strlen(value) > 0)
+ if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
+ strcmp(option->envvar, "PGHOSTADDR") == 0))
{
- found = true;
-
- pg_log(ctx, PG_WARNING,
- "libpq env var %-20s is currently set to: %s\n", option->envvar, value);
+ const char *value = getenv(option->envvar);
+
+ if (value && strlen(value) > 0 &&
+ /* check for 'local' host values */
+ (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
+ strcmp(value, "::1") != 0 && value[0] != '/'))
+ pg_log(PG_FATAL,
+ "libpq environment variable %s has a non-local server value: %s\n",
+ option->envvar, value);
}
-
- option++;
}
/* Free the memory that libpq allocated on our behalf */
PQconninfoFree(start);
-
- if (found)
- pg_log(ctx, PG_FATAL,
- "libpq env vars have been found and listed above, please unset them for pg_upgrade\n");
}
diff --git a/contrib/pg_upgrade/tablespace.c b/contrib/pg_upgrade/tablespace.c
index 11caaa3e89..6cdae51cf1 100644
--- a/contrib/pg_upgrade/tablespace.c
+++ b/contrib/pg_upgrade/tablespace.c
@@ -3,29 +3,28 @@
*
* tablespace functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/tablespace.c,v 1.6 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/tablespace.c
*/
#include "pg_upgrade.h"
-static void get_tablespace_paths(migratorContext *ctx);
-static void set_tablespace_directory_suffix(migratorContext *ctx,
- Cluster whichCluster);
+static void get_tablespace_paths(void);
+static void set_tablespace_directory_suffix(ClusterInfo *cluster);
void
-init_tablespaces(migratorContext *ctx)
+init_tablespaces(void)
{
- get_tablespace_paths(ctx);
+ get_tablespace_paths();
- set_tablespace_directory_suffix(ctx, CLUSTER_OLD);
- set_tablespace_directory_suffix(ctx, CLUSTER_NEW);
+ set_tablespace_directory_suffix(&old_cluster);
+ set_tablespace_directory_suffix(&new_cluster);
- if (ctx->num_tablespaces > 0 &&
- strcmp(ctx->old.tablespace_suffix, ctx->new.tablespace_suffix) == 0)
- pg_log(ctx, PG_FATAL,
- "Cannot migrate to/from the same system catalog version when\n"
+ if (os_info.num_tablespaces > 0 &&
+ strcmp(old_cluster.tablespace_suffix, new_cluster.tablespace_suffix) == 0)
+ pg_log(PG_FATAL,
+ "Cannot upgrade to/from the same system catalog version when\n"
"using tablespaces.\n");
}
@@ -37,29 +36,29 @@ init_tablespaces(migratorContext *ctx)
* paths. Its the caller's responsibility to free the array.
*/
static void
-get_tablespace_paths(migratorContext *ctx)
+get_tablespace_paths(void)
{
- PGconn *conn = connectToServer(ctx, "template1", CLUSTER_OLD);
+ PGconn *conn = connectToServer(&old_cluster, "template1");
PGresult *res;
int tblnum;
int i_spclocation;
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT spclocation "
"FROM pg_catalog.pg_tablespace "
"WHERE spcname != 'pg_default' AND "
" spcname != 'pg_global'");
- if ((ctx->num_tablespaces = PQntuples(res)) != 0)
- ctx->tablespaces = (char **) pg_malloc(ctx,
- ctx->num_tablespaces * sizeof(char *));
+ if ((os_info.num_tablespaces = PQntuples(res)) != 0)
+ os_info.tablespaces = (char **) pg_malloc(
+ os_info.num_tablespaces * sizeof(char *));
else
- ctx->tablespaces = NULL;
+ os_info.tablespaces = NULL;
i_spclocation = PQfnumber(res, "spclocation");
- for (tblnum = 0; tblnum < ctx->num_tablespaces; tblnum++)
- ctx->tablespaces[tblnum] = pg_strdup(ctx,
+ for (tblnum = 0; tblnum < os_info.num_tablespaces; tblnum++)
+ os_info.tablespaces[tblnum] = pg_strdup(
PQgetvalue(res, tblnum, i_spclocation));
PQclear(res);
@@ -71,16 +70,15 @@ get_tablespace_paths(migratorContext *ctx)
static void
-set_tablespace_directory_suffix(migratorContext *ctx, Cluster whichCluster)
+set_tablespace_directory_suffix(ClusterInfo *cluster)
{
- ClusterInfo *cluster = (whichCluster == CLUSTER_OLD) ? &ctx->old : &ctx->new;
-
if (GET_MAJOR_VERSION(cluster->major_version) <= 804)
- cluster->tablespace_suffix = pg_strdup(ctx, "");
+ cluster->tablespace_suffix = pg_strdup("");
else
{
/* This cluster has a version-specific subdirectory */
- cluster->tablespace_suffix = pg_malloc(ctx, 4 + strlen(cluster->major_version_str) +
+ cluster->tablespace_suffix = pg_malloc(4 +
+ strlen(cluster->major_version_str) +
10 /* OIDCHARS */ + 1);
/* The leading slash is needed to start a new directory. */
diff --git a/contrib/pg_upgrade/util.c b/contrib/pg_upgrade/util.c
index 24fc08ef70..f6582f5e38 100644
--- a/contrib/pg_upgrade/util.c
+++ b/contrib/pg_upgrade/util.c
@@ -3,8 +3,8 @@
*
* utility functions
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/util.c,v 1.5 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/util.c
*/
#include "pg_upgrade.h"
@@ -12,13 +12,15 @@
#include <signal.h>
+LogOpts log_opts;
+
/*
* report_status()
*
* Displays the result of an operation (ok, failed, error message,...)
*/
void
-report_status(migratorContext *ctx, eLogType type, const char *fmt,...)
+report_status(eLogType type, const char *fmt,...)
{
va_list args;
char message[MAX_STRING];
@@ -27,27 +29,27 @@ report_status(migratorContext *ctx, eLogType type, const char *fmt,...)
vsnprintf(message, sizeof(message), fmt, args);
va_end(args);
- pg_log(ctx, type, "%s\n", message);
+ pg_log(type, "%s\n", message);
}
/*
- * prep_status(&ctx, )
+ * prep_status
*
* Displays a message that describes an operation we are about to begin.
* We pad the message out to MESSAGE_WIDTH characters so that all of the "ok" and
* "failed" indicators line up nicely.
*
* A typical sequence would look like this:
- * prep_status(&ctx, "about to flarb the next %d files", fileCount );
+ * prep_status("about to flarb the next %d files", fileCount );
*
* if(( message = flarbFiles(fileCount)) == NULL)
- * report_status(ctx, PG_REPORT, "ok" );
+ * report_status(PG_REPORT, "ok" );
* else
- * pg_log(ctx, PG_FATAL, "failed - %s", message );
+ * pg_log(PG_FATAL, "failed - %s\n", message );
*/
void
-prep_status(migratorContext *ctx, const char *fmt,...)
+prep_status(const char *fmt,...)
{
va_list args;
char message[MAX_STRING];
@@ -57,14 +59,14 @@ prep_status(migratorContext *ctx, const char *fmt,...)
va_end(args);
if (strlen(message) > 0 && message[strlen(message) - 1] == '\n')
- pg_log(ctx, PG_REPORT, "%s", message);
+ pg_log(PG_REPORT, "%s", message);
else
- pg_log(ctx, PG_REPORT, "%-" MESSAGE_WIDTH "s", message);
+ pg_log(PG_REPORT, "%-" MESSAGE_WIDTH "s", message);
}
void
-pg_log(migratorContext *ctx, eLogType type, char *fmt,...)
+pg_log(eLogType type, char *fmt,...)
{
va_list args;
char message[MAX_STRING];
@@ -73,19 +75,19 @@ pg_log(migratorContext *ctx, eLogType type, char *fmt,...)
vsnprintf(message, sizeof(message), fmt, args);
va_end(args);
- if (ctx->log_fd != NULL)
+ if (log_opts.fd != NULL)
{
- fwrite(message, strlen(message), 1, ctx->log_fd);
+ fwrite(message, strlen(message), 1, log_opts.fd);
/* if we are using OVERWRITE_MESSAGE, add newline */
if (strchr(message, '\r') != NULL)
- fwrite("\n", 1, 1, ctx->log_fd);
- fflush(ctx->log_fd);
+ fwrite("\n", 1, 1, log_opts.fd);
+ fflush(log_opts.fd);
}
switch (type)
{
case PG_INFO:
- if (ctx->verbose)
+ if (log_opts.verbose)
printf("%s", _(message));
break;
@@ -95,14 +97,14 @@ pg_log(migratorContext *ctx, eLogType type, char *fmt,...)
break;
case PG_FATAL:
- printf("%s", "\n");
- printf("%s", _(message));
- exit_nicely(ctx, true);
+ printf("\n%s", _(message));
+ printf("Failure, exiting\n");
+ exit(1);
break;
case PG_DEBUG:
- if (ctx->debug)
- fprintf(ctx->debug_fd, "%s\n", _(message));
+ if (log_opts.debug)
+ fprintf(log_opts.debug_fd, "%s\n", _(message));
break;
default:
@@ -113,10 +115,10 @@ pg_log(migratorContext *ctx, eLogType type, char *fmt,...)
void
-check_ok(migratorContext *ctx)
+check_ok(void)
{
/* all seems well */
- report_status(ctx, PG_REPORT, "ok");
+ report_status(PG_REPORT, "ok");
fflush(stdout);
}
@@ -129,9 +131,9 @@ check_ok(migratorContext *ctx)
* memory leakage is not a big deal in this program.
*/
char *
-quote_identifier(migratorContext *ctx, const char *s)
+quote_identifier(const char *s)
{
- char *result = pg_malloc(ctx, strlen(s) * 2 + 3);
+ char *result = pg_malloc(strlen(s) * 2 + 3);
char *r = result;
*r++ = '"';
@@ -154,7 +156,7 @@ quote_identifier(migratorContext *ctx, const char *s)
* (copied from initdb.c) find the current user
*/
int
-get_user_info(migratorContext *ctx, char **user_name)
+get_user_info(char **user_name)
{
int user_id;
@@ -176,48 +178,19 @@ get_user_info(migratorContext *ctx, char **user_name)
user_id = 1;
#endif
- *user_name = pg_strdup(ctx, pw->pw_name);
+ *user_name = pg_strdup(pw->pw_name);
return user_id;
}
-void
-exit_nicely(migratorContext *ctx, bool need_cleanup)
-{
- stop_postmaster(ctx, true, true);
-
- pg_free(ctx->logfile);
-
- if (ctx->log_fd)
- fclose(ctx->log_fd);
-
- if (ctx->debug_fd)
- fclose(ctx->debug_fd);
-
- /* terminate any running instance of postmaster */
- if (ctx->postmasterPID != 0)
- kill(ctx->postmasterPID, SIGTERM);
-
- if (need_cleanup)
- {
- /*
- * FIXME must delete intermediate files
- */
- exit(1);
- }
- else
- exit(0);
-}
-
-
void *
-pg_malloc(migratorContext *ctx, int n)
+pg_malloc(int n)
{
void *p = malloc(n);
if (p == NULL)
- pg_log(ctx, PG_FATAL, "%s: out of memory\n", ctx->progname);
+ pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
return p;
}
@@ -232,12 +205,12 @@ pg_free(void *p)
char *
-pg_strdup(migratorContext *ctx, const char *s)
+pg_strdup(const char *s)
{
char *result = strdup(s);
if (result == NULL)
- pg_log(ctx, PG_FATAL, "%s: out of memory\n", ctx->progname);
+ pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
return result;
}
@@ -259,3 +232,52 @@ getErrorText(int errNum)
#endif
return strdup(strerror(errNum));
}
+
+
+/*
+ * str2uint()
+ *
+ * convert string to oid
+ */
+unsigned int
+str2uint(const char *str)
+{
+ return strtoul(str, NULL, 10);
+}
+
+
+/*
+ * pg_putenv()
+ *
+ * This is like putenv(), but takes two arguments.
+ * It also does unsetenv() if val is NULL.
+ */
+void
+pg_putenv(const char *var, const char *val)
+{
+ if (val)
+ {
+#ifndef WIN32
+ char *envstr = (char *) pg_malloc(strlen(var) +
+ strlen(val) + 2);
+
+ sprintf(envstr, "%s=%s", var, val);
+ putenv(envstr);
+
+ /*
+ * Do not free envstr because it becomes part of the environment on
+ * some operating systems. See port/unsetenv.c::unsetenv.
+ */
+#else
+ SetEnvironmentVariableA(var, val);
+#endif
+ }
+ else
+ {
+#ifndef WIN32
+ unsetenv(var);
+#else
+ SetEnvironmentVariableA(var, "");
+#endif
+ }
+}
diff --git a/contrib/pg_upgrade/version.c b/contrib/pg_upgrade/version.c
index 59e61767fc..958bcbb80f 100644
--- a/contrib/pg_upgrade/version.c
+++ b/contrib/pg_upgrade/version.c
@@ -3,8 +3,8 @@
*
* Postgres-version-specific routines
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/version.c,v 1.5 2010/07/03 16:33:14 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/version.c
*/
#include "pg_upgrade.h"
@@ -18,30 +18,27 @@
* 9.0 has a new pg_largeobject permission table
*/
void
-new_9_0_populate_pg_largeobject_metadata(migratorContext *ctx, bool check_mode,
- Cluster whichCluster)
+new_9_0_populate_pg_largeobject_metadata(ClusterInfo *cluster, bool check_mode)
{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
int dbnum;
FILE *script = NULL;
bool found = false;
char output_path[MAXPGPATH];
- prep_status(ctx, "Checking for large objects");
+ prep_status("Checking for large objects");
snprintf(output_path, sizeof(output_path), "%s/pg_largeobject.sql",
- ctx->cwd);
+ os_info.cwd);
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
{
PGresult *res;
int i_count;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
/* find if there are any large objects */
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT count(*) "
"FROM pg_catalog.pg_largeobject ");
@@ -52,9 +49,9 @@ new_9_0_populate_pg_largeobject_metadata(migratorContext *ctx, bool check_mode,
if (!check_mode)
{
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ pg_log(PG_FATAL, "could not create necessary file: %s\n", output_path);
fprintf(script, "\\connect %s\n",
- quote_identifier(ctx, active_db->db_name));
+ quote_identifier(active_db->db_name));
fprintf(script,
"SELECT pg_catalog.lo_create(t.loid)\n"
"FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) AS t;\n");
@@ -65,20 +62,21 @@ new_9_0_populate_pg_largeobject_metadata(migratorContext *ctx, bool check_mode,
PQfinish(conn);
}
+ if (script)
+ fclose(script);
+
if (found)
{
- if (!check_mode)
- fclose(script);
- report_status(ctx, PG_WARNING, "warning");
+ report_status(PG_WARNING, "warning");
if (check_mode)
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains large objects.\n"
"| The new database has an additional large object\n"
- "| permission table. After migration, you will be\n"
+ "| permission table. After upgrading, you will be\n"
"| given a command to populate the pg_largeobject\n"
"| permission table with default permissions.\n\n");
else
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains large objects.\n"
"| The new database has an additional large object\n"
"| permission table so default permissions must be\n"
@@ -89,5 +87,5 @@ new_9_0_populate_pg_largeobject_metadata(migratorContext *ctx, bool check_mode,
output_path);
}
else
- check_ok(ctx);
+ check_ok();
}
diff --git a/contrib/pg_upgrade/version_old_8_3.c b/contrib/pg_upgrade/version_old_8_3.c
index 824c968054..1a31f8d683 100644
--- a/contrib/pg_upgrade/version_old_8_3.c
+++ b/contrib/pg_upgrade/version_old_8_3.c
@@ -3,8 +3,8 @@
*
* Postgres-version-specific routines
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade/version_old_8_3.c,v 1.6 2010/07/03 16:33:14 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade/version_old_8_3.c
*/
#include "pg_upgrade.h"
@@ -19,21 +19,19 @@
* checks tables and indexes.
*/
void
-old_8_3_check_for_name_data_type_usage(migratorContext *ctx, Cluster whichCluster)
+old_8_3_check_for_name_data_type_usage(ClusterInfo *cluster)
{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
int dbnum;
FILE *script = NULL;
bool found = false;
char output_path[MAXPGPATH];
- prep_status(ctx, "Checking for invalid 'name' user columns");
+ prep_status("Checking for invalid 'name' user columns");
snprintf(output_path, sizeof(output_path), "%s/tables_using_name.txt",
- ctx->cwd);
+ os_info.cwd);
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
{
PGresult *res;
bool db_used = false;
@@ -42,8 +40,8 @@ old_8_3_check_for_name_data_type_usage(migratorContext *ctx, Cluster whichCluste
int i_nspname,
i_relname,
i_attname;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
/*
* With a smaller alignment in 8.4, 'name' cannot be used in a
@@ -51,7 +49,7 @@ old_8_3_check_for_name_data_type_usage(migratorContext *ctx, Cluster whichCluste
* that condition with enough analysis, but it seems not worth the
* trouble.)
*/
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT n.nspname, c.relname, a.attname "
"FROM pg_catalog.pg_class c, "
" pg_catalog.pg_namespace n, "
@@ -72,7 +70,7 @@ old_8_3_check_for_name_data_type_usage(migratorContext *ctx, Cluster whichCluste
{
found = true;
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ pg_log(PG_FATAL, "could not create necessary file: %s\n", output_path);
if (!db_used)
{
fprintf(script, "Database: %s\n", active_db->db_name);
@@ -89,21 +87,23 @@ old_8_3_check_for_name_data_type_usage(migratorContext *ctx, Cluster whichCluste
PQfinish(conn);
}
+ if (script)
+ fclose(script);
+
if (found)
{
- fclose(script);
- pg_log(ctx, PG_REPORT, "fatal\n");
- pg_log(ctx, PG_FATAL,
- "| Your installation uses the \"name\" data type in\n"
+ pg_log(PG_REPORT, "fatal\n");
+ pg_log(PG_FATAL,
+ "| Your installation contains the \"name\" data type in\n"
"| user tables. This data type changed its internal\n"
"| alignment between your old and new clusters so this\n"
"| cluster cannot currently be upgraded. You can\n"
- "| remove the problem tables and restart the migration.\n"
+ "| remove the problem tables and restart the upgrade.\n"
"| A list of the problem columns is in the file:\n"
"| \t%s\n\n", output_path);
}
else
- check_ok(ctx);
+ check_ok();
}
@@ -111,24 +111,22 @@ old_8_3_check_for_name_data_type_usage(migratorContext *ctx, Cluster whichCluste
* old_8_3_check_for_tsquery_usage()
* 8.3 -> 8.4
* A new 'prefix' field was added to the 'tsquery' data type in 8.4
- * so migration of such fields is impossible.
+ * so upgrading of such fields is impossible.
*/
void
-old_8_3_check_for_tsquery_usage(migratorContext *ctx, Cluster whichCluster)
+old_8_3_check_for_tsquery_usage(ClusterInfo *cluster)
{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
int dbnum;
FILE *script = NULL;
bool found = false;
char output_path[MAXPGPATH];
- prep_status(ctx, "Checking for tsquery user columns");
+ prep_status("Checking for tsquery user columns");
snprintf(output_path, sizeof(output_path), "%s/tables_using_tsquery.txt",
- ctx->cwd);
+ os_info.cwd);
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
{
PGresult *res;
bool db_used = false;
@@ -137,11 +135,11 @@ old_8_3_check_for_tsquery_usage(migratorContext *ctx, Cluster whichCluster)
int i_nspname,
i_relname,
i_attname;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
/* Find any user-defined tsquery columns */
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT n.nspname, c.relname, a.attname "
"FROM pg_catalog.pg_class c, "
" pg_catalog.pg_namespace n, "
@@ -162,7 +160,7 @@ old_8_3_check_for_tsquery_usage(migratorContext *ctx, Cluster whichCluster)
{
found = true;
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ pg_log(PG_FATAL, "could not create necessary file: %s\n", output_path);
if (!db_used)
{
fprintf(script, "Database: %s\n", active_db->db_name);
@@ -179,113 +177,23 @@ old_8_3_check_for_tsquery_usage(migratorContext *ctx, Cluster whichCluster)
PQfinish(conn);
}
+ if (script)
+ fclose(script);
+
if (found)
{
- fclose(script);
- pg_log(ctx, PG_REPORT, "fatal\n");
- pg_log(ctx, PG_FATAL,
- "| Your installation uses the \"tsquery\" data type.\n"
+ pg_log(PG_REPORT, "fatal\n");
+ pg_log(PG_FATAL,
+ "| Your installation contains the \"tsquery\" data type.\n"
"| This data type added a new internal field between\n"
"| your old and new clusters so this cluster cannot\n"
"| currently be upgraded. You can remove the problem\n"
- "| columns and restart the migration. A list of the\n"
+ "| columns and restart the upgrade. A list of the\n"
"| problem columns is in the file:\n"
"| \t%s\n\n", output_path);
}
else
- check_ok(ctx);
-}
-
-
-/*
- * old_8_3_check_for_isn_and_int8_passing_mismatch()
- * 8.3 -> 8.4
- * /contrib/isn relies on data type int8, and in 8.4 int8 is now passed
- * by value. The schema dumps the CREATE TYPE PASSEDBYVALUE setting so
- * it must match for the old and new servers.
- */
-void
-old_8_3_check_for_isn_and_int8_passing_mismatch(migratorContext *ctx, Cluster whichCluster)
-{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
- int dbnum;
- FILE *script = NULL;
- bool found = false;
- char output_path[MAXPGPATH];
-
- prep_status(ctx, "Checking for /contrib/isn with bigint-passing mismatch");
-
- if (ctx->old.controldata.float8_pass_by_value ==
- ctx->new.controldata.float8_pass_by_value)
- {
- /* no mismatch */
- check_ok(ctx);
- return;
- }
-
- snprintf(output_path, sizeof(output_path), "%s/contrib_isn_and_int8_pass_by_value.txt",
- ctx->cwd);
-
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
- {
- PGresult *res;
- bool db_used = false;
- int ntups;
- int rowno;
- int i_nspname,
- i_proname;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
-
- /* Find any functions coming from contrib/isn */
- res = executeQueryOrDie(ctx, conn,
- "SELECT n.nspname, p.proname "
- "FROM pg_catalog.pg_proc p, "
- " pg_catalog.pg_namespace n "
- "WHERE p.pronamespace = n.oid AND "
- " p.probin = '$libdir/isn'");
-
- ntups = PQntuples(res);
- i_nspname = PQfnumber(res, "nspname");
- i_proname = PQfnumber(res, "proname");
- for (rowno = 0; rowno < ntups; rowno++)
- {
- found = true;
- if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
- if (!db_used)
- {
- fprintf(script, "Database: %s\n", active_db->db_name);
- db_used = true;
- }
- fprintf(script, " %s.%s\n",
- PQgetvalue(res, rowno, i_nspname),
- PQgetvalue(res, rowno, i_proname));
- }
-
- PQclear(res);
-
- PQfinish(conn);
- }
-
- if (found)
- {
- fclose(script);
- pg_log(ctx, PG_REPORT, "fatal\n");
- pg_log(ctx, PG_FATAL,
- "| Your installation uses \"/contrib/isn\" functions\n"
- "| which rely on the bigint data type. Your old and\n"
- "| new clusters pass bigint values differently so this\n"
- "| cluster cannot currently be upgraded. You can\n"
- "| manually migrate data that use \"/contrib/isn\"\n"
- "| facilities and remove \"/contrib/isn\" from the\n"
- "| old cluster and restart the migration. A list\n"
- "| of the problem functions is in the file:\n"
- "| \t%s\n\n", output_path);
- }
- else
- check_ok(ctx);
+ check_ok();
}
@@ -302,37 +210,34 @@ old_8_3_check_for_isn_and_int8_passing_mismatch(migratorContext *ctx, Cluster wh
* 'c' 'bb' 'aaa' -- 8.3
*/
void
-old_8_3_rebuild_tsvector_tables(migratorContext *ctx, bool check_mode,
- Cluster whichCluster)
+old_8_3_rebuild_tsvector_tables(ClusterInfo *cluster, bool check_mode)
{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
int dbnum;
FILE *script = NULL;
bool found = false;
char output_path[MAXPGPATH];
- prep_status(ctx, "Checking for tsvector user columns");
+ prep_status("Checking for tsvector user columns");
snprintf(output_path, sizeof(output_path), "%s/rebuild_tsvector_tables.sql",
- ctx->cwd);
+ os_info.cwd);
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
{
PGresult *res;
bool db_used = false;
- char old_nspname[NAMEDATALEN] = "",
- old_relname[NAMEDATALEN] = "";
+ char nspname[NAMEDATALEN] = "",
+ relname[NAMEDATALEN] = "";
int ntups;
int rowno;
int i_nspname,
i_relname,
i_attname;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
/* Find any user-defined tsvector columns */
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT n.nspname, c.relname, a.attname "
"FROM pg_catalog.pg_class c, "
" pg_catalog.pg_namespace n, "
@@ -373,37 +278,37 @@ old_8_3_rebuild_tsvector_tables(migratorContext *ctx, bool check_mode,
if (!check_mode)
{
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ pg_log(PG_FATAL, "could not create necessary file: %s\n", output_path);
if (!db_used)
{
fprintf(script, "\\connect %s\n\n",
- quote_identifier(ctx, active_db->db_name));
+ quote_identifier(active_db->db_name));
db_used = true;
}
/* Rebuild all tsvector collumns with one ALTER TABLE command */
- if (strcmp(PQgetvalue(res, rowno, i_nspname), old_nspname) != 0 ||
- strcmp(PQgetvalue(res, rowno, i_relname), old_relname) != 0)
+ if (strcmp(PQgetvalue(res, rowno, i_nspname), nspname) != 0 ||
+ strcmp(PQgetvalue(res, rowno, i_relname), relname) != 0)
{
- if (strlen(old_nspname) != 0 || strlen(old_relname) != 0)
+ if (strlen(nspname) != 0 || strlen(relname) != 0)
fprintf(script, ";\n\n");
fprintf(script, "ALTER TABLE %s.%s\n",
- quote_identifier(ctx, PQgetvalue(res, rowno, i_nspname)),
- quote_identifier(ctx, PQgetvalue(res, rowno, i_relname)));
+ quote_identifier(PQgetvalue(res, rowno, i_nspname)),
+ quote_identifier(PQgetvalue(res, rowno, i_relname)));
}
else
fprintf(script, ",\n");
- strlcpy(old_nspname, PQgetvalue(res, rowno, i_nspname), sizeof(old_nspname));
- strlcpy(old_relname, PQgetvalue(res, rowno, i_relname), sizeof(old_relname));
+ strlcpy(nspname, PQgetvalue(res, rowno, i_nspname), sizeof(nspname));
+ strlcpy(relname, PQgetvalue(res, rowno, i_relname), sizeof(relname));
fprintf(script, "ALTER COLUMN %s "
/* This could have been a custom conversion function call. */
"TYPE pg_catalog.tsvector USING %s::pg_catalog.text::pg_catalog.tsvector",
- quote_identifier(ctx, PQgetvalue(res, rowno, i_attname)),
- quote_identifier(ctx, PQgetvalue(res, rowno, i_attname)));
+ quote_identifier(PQgetvalue(res, rowno, i_attname)),
+ quote_identifier(PQgetvalue(res, rowno, i_attname)));
}
}
- if (strlen(old_nspname) != 0 || strlen(old_relname) != 0)
+ if (strlen(nspname) != 0 || strlen(relname) != 0)
fprintf(script, ";\n\n");
PQclear(res);
@@ -413,20 +318,21 @@ old_8_3_rebuild_tsvector_tables(migratorContext *ctx, bool check_mode,
PQfinish(conn);
}
+ if (script)
+ fclose(script);
+
if (found)
{
- if (!check_mode)
- fclose(script);
- report_status(ctx, PG_WARNING, "warning");
+ report_status(PG_WARNING, "warning");
if (check_mode)
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains tsvector columns.\n"
"| The tsvector internal storage format changed\n"
"| between your old and new clusters so the tables\n"
- "| must be rebuilt. After migration, you will be\n"
+ "| must be rebuilt. After upgrading, you will be\n"
"| given instructions.\n\n");
else
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains tsvector columns.\n"
"| The tsvector internal storage format changed\n"
"| between your old and new clusters so the tables\n"
@@ -437,7 +343,7 @@ old_8_3_rebuild_tsvector_tables(migratorContext *ctx, bool check_mode,
output_path);
}
else
- check_ok(ctx);
+ check_ok();
}
@@ -447,22 +353,19 @@ old_8_3_rebuild_tsvector_tables(migratorContext *ctx, bool check_mode,
* Hash, Gin, and GiST index binary format has changes from 8.3->8.4
*/
void
-old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx, bool check_mode,
- Cluster whichCluster)
+old_8_3_invalidate_hash_gin_indexes(ClusterInfo *cluster, bool check_mode)
{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
int dbnum;
FILE *script = NULL;
bool found = false;
char output_path[MAXPGPATH];
- prep_status(ctx, "Checking for hash and gin indexes");
+ prep_status("Checking for hash and gin indexes");
snprintf(output_path, sizeof(output_path), "%s/reindex_hash_and_gin.sql",
- ctx->cwd);
+ os_info.cwd);
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
{
PGresult *res;
bool db_used = false;
@@ -470,11 +373,11 @@ old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx, bool check_mode,
int rowno;
int i_nspname,
i_relname;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
/* find hash and gin indexes */
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT n.nspname, c.relname "
"FROM pg_catalog.pg_class c, "
" pg_catalog.pg_index i, "
@@ -495,16 +398,16 @@ old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx, bool check_mode,
if (!check_mode)
{
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ pg_log(PG_FATAL, "could not create necessary file: %s\n", output_path);
if (!db_used)
{
fprintf(script, "\\connect %s\n",
- quote_identifier(ctx, active_db->db_name));
+ quote_identifier(active_db->db_name));
db_used = true;
}
fprintf(script, "REINDEX INDEX %s.%s;\n",
- quote_identifier(ctx, PQgetvalue(res, rowno, i_nspname)),
- quote_identifier(ctx, PQgetvalue(res, rowno, i_relname)));
+ quote_identifier(PQgetvalue(res, rowno, i_nspname)),
+ quote_identifier(PQgetvalue(res, rowno, i_relname)));
}
}
@@ -512,7 +415,7 @@ old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx, bool check_mode,
if (!check_mode && found)
/* mark hash and gin indexes as invalid */
- PQclear(executeQueryOrDie(ctx, conn,
+ PQclear(executeQueryOrDie(conn,
"UPDATE pg_catalog.pg_index i "
"SET indisvalid = false "
"FROM pg_catalog.pg_class c, "
@@ -526,21 +429,22 @@ old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx, bool check_mode,
PQfinish(conn);
}
+ if (script)
+ fclose(script);
+
if (found)
{
- if (!check_mode)
- fclose(script);
- report_status(ctx, PG_WARNING, "warning");
+ report_status(PG_WARNING, "warning");
if (check_mode)
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains hash and/or gin\n"
"| indexes. These indexes have different\n"
"| internal formats between your old and new\n"
"| clusters so they must be reindexed with the\n"
- "| REINDEX command. After migration, you will\n"
+ "| REINDEX command. After upgrading, you will\n"
"| be given REINDEX instructions.\n\n");
else
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains hash and/or gin\n"
"| indexes. These indexes have different internal\n"
"| formats between your old and new clusters so\n"
@@ -553,7 +457,7 @@ old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx, bool check_mode,
output_path);
}
else
- check_ok(ctx);
+ check_ok();
}
@@ -563,22 +467,20 @@ old_8_3_invalidate_hash_gin_indexes(migratorContext *ctx, bool check_mode,
* 8.4 bpchar_pattern_ops no longer sorts based on trailing spaces
*/
void
-old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_mode,
- Cluster whichCluster)
+old_8_3_invalidate_bpchar_pattern_ops_indexes(ClusterInfo *cluster,
+ bool check_mode)
{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
int dbnum;
FILE *script = NULL;
bool found = false;
char output_path[MAXPGPATH];
- prep_status(ctx, "Checking for bpchar_pattern_ops indexes");
+ prep_status("Checking for bpchar_pattern_ops indexes");
snprintf(output_path, sizeof(output_path), "%s/reindex_bpchar_ops.sql",
- ctx->cwd);
+ os_info.cwd);
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
{
PGresult *res;
bool db_used = false;
@@ -586,8 +488,8 @@ old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_m
int rowno;
int i_nspname,
i_relname;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
/* find bpchar_pattern_ops indexes */
@@ -595,7 +497,7 @@ old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_m
* Do only non-hash, non-gin indexees; we already invalidated them
* above; no need to reindex twice
*/
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT n.nspname, c.relname "
"FROM pg_catalog.pg_index i, "
" pg_catalog.pg_class c, "
@@ -621,16 +523,16 @@ old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_m
if (!check_mode)
{
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ pg_log(PG_FATAL, "could not create necessary file: %s\n", output_path);
if (!db_used)
{
fprintf(script, "\\connect %s\n",
- quote_identifier(ctx, active_db->db_name));
+ quote_identifier(active_db->db_name));
db_used = true;
}
fprintf(script, "REINDEX INDEX %s.%s;\n",
- quote_identifier(ctx, PQgetvalue(res, rowno, i_nspname)),
- quote_identifier(ctx, PQgetvalue(res, rowno, i_relname)));
+ quote_identifier(PQgetvalue(res, rowno, i_nspname)),
+ quote_identifier(PQgetvalue(res, rowno, i_relname)));
}
}
@@ -638,7 +540,7 @@ old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_m
if (!check_mode && found)
/* mark bpchar_pattern_ops indexes as invalid */
- PQclear(executeQueryOrDie(ctx, conn,
+ PQclear(executeQueryOrDie(conn,
"UPDATE pg_catalog.pg_index i "
"SET indisvalid = false "
"FROM pg_catalog.pg_class c, "
@@ -657,21 +559,22 @@ old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_m
PQfinish(conn);
}
+ if (script)
+ fclose(script);
+
if (found)
{
- if (!check_mode)
- fclose(script);
- report_status(ctx, PG_WARNING, "warning");
+ report_status(PG_WARNING, "warning");
if (check_mode)
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains indexes using\n"
"| \"bpchar_pattern_ops\". These indexes have\n"
"| different internal formats between your old and\n"
"| new clusters so they must be reindexed with the\n"
- "| REINDEX command. After migration, you will be\n"
+ "| REINDEX command. After upgrading, you will be\n"
"| given REINDEX instructions.\n\n");
else
- pg_log(ctx, PG_WARNING, "\n"
+ pg_log(PG_WARNING, "\n"
"| Your installation contains indexes using\n"
"| \"bpchar_pattern_ops\". These indexes have\n"
"| different internal formats between your old and\n"
@@ -684,7 +587,7 @@ old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_m
output_path);
}
else
- check_ok(ctx);
+ check_ok();
}
@@ -699,20 +602,18 @@ old_8_3_invalidate_bpchar_pattern_ops_indexes(migratorContext *ctx, bool check_m
* server, even in link mode.
*/
char *
-old_8_3_create_sequence_script(migratorContext *ctx, Cluster whichCluster)
+old_8_3_create_sequence_script(ClusterInfo *cluster)
{
- ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ?
- &ctx->old : &ctx->new;
int dbnum;
FILE *script = NULL;
bool found = false;
- char *output_path = pg_malloc(ctx, MAXPGPATH);
+ char *output_path = pg_malloc(MAXPGPATH);
- snprintf(output_path, MAXPGPATH, "%s/adjust_sequences.sql", ctx->cwd);
+ snprintf(output_path, MAXPGPATH, "%s/adjust_sequences.sql", os_info.cwd);
- prep_status(ctx, "Creating script to adjust sequences");
+ prep_status("Creating script to adjust sequences");
- for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++)
+ for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
{
PGresult *res;
bool db_used = false;
@@ -720,11 +621,11 @@ old_8_3_create_sequence_script(migratorContext *ctx, Cluster whichCluster)
int rowno;
int i_nspname,
i_relname;
- DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum];
- PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster);
+ DbInfo *active_db = &cluster->dbarr.dbs[dbnum];
+ PGconn *conn = connectToServer(cluster, active_db->db_name);
/* Find any sequences */
- res = executeQueryOrDie(ctx, conn,
+ res = executeQueryOrDie(conn,
"SELECT n.nspname, c.relname "
"FROM pg_catalog.pg_class c, "
" pg_catalog.pg_namespace n "
@@ -747,27 +648,27 @@ old_8_3_create_sequence_script(migratorContext *ctx, Cluster whichCluster)
found = true;
if (script == NULL && (script = fopen(output_path, "w")) == NULL)
- pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path);
+ pg_log(PG_FATAL, "could not create necessary file: %s\n", output_path);
if (!db_used)
{
fprintf(script, "\\connect %s\n\n",
- quote_identifier(ctx, active_db->db_name));
+ quote_identifier(active_db->db_name));
db_used = true;
}
/* Find the desired sequence */
- seq_res = executeQueryOrDie(ctx, conn,
+ seq_res = executeQueryOrDie(conn,
"SELECT s.last_value, s.is_called "
"FROM %s.%s s",
- quote_identifier(ctx, nspname),
- quote_identifier(ctx, relname));
+ quote_identifier(nspname),
+ quote_identifier(relname));
assert(PQntuples(seq_res) == 1);
i_last_value = PQfnumber(seq_res, "last_value");
i_is_called = PQfnumber(seq_res, "is_called");
fprintf(script, "SELECT setval('%s.%s', %s, '%s');\n",
- quote_identifier(ctx, nspname), quote_identifier(ctx, relname),
+ quote_identifier(nspname), quote_identifier(relname),
PQgetvalue(seq_res, 0, i_last_value), PQgetvalue(seq_res, 0, i_is_called));
PQclear(seq_res);
}
@@ -778,10 +679,11 @@ old_8_3_create_sequence_script(migratorContext *ctx, Cluster whichCluster)
PQfinish(conn);
}
- if (found)
+
+ if (script)
fclose(script);
- check_ok(ctx);
+ check_ok();
if (found)
return output_path;
diff --git a/contrib/pg_upgrade_support/Makefile b/contrib/pg_upgrade_support/Makefile
index bd43c5093e..f7def160c3 100644
--- a/contrib/pg_upgrade_support/Makefile
+++ b/contrib/pg_upgrade_support/Makefile
@@ -1,7 +1,4 @@
-#
-# Makefile for pg_upgrade_support
-#
-# $PostgreSQL: pgsql/contrib/pg_upgrade_support/Makefile,v 1.3 2010/07/03 14:23:14 momjian Exp $
+# contrib/pg_upgrade_support/Makefile
PGFILEDESC = "pg_upgrade_support - server-side functions for pg_upgrade"
diff --git a/contrib/pg_upgrade_support/pg_upgrade_support.c b/contrib/pg_upgrade_support/pg_upgrade_support.c
index 08050ac6e8..2c23cbab9d 100644
--- a/contrib/pg_upgrade_support/pg_upgrade_support.c
+++ b/contrib/pg_upgrade_support/pg_upgrade_support.c
@@ -1,54 +1,69 @@
/*
- * pg_upgrade_sysoids.c
+ * pg_upgrade_support.c
*
* server-side functions to set backend global variables
- * to control oid and relfilenode assignment
+ * to control oid and relfilenode assignment, and do other special
+ * hacks needed for pg_upgrade.
*
- * Copyright (c) 2010, PostgreSQL Global Development Group
- * $PostgreSQL: pgsql/contrib/pg_upgrade_support/pg_upgrade_support.c,v 1.5 2010/07/06 19:18:55 momjian Exp $
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ * contrib/pg_upgrade_support/pg_upgrade_support.c
*/
#include "postgres.h"
#include "fmgr.h"
#include "catalog/dependency.h"
+#include "catalog/namespace.h"
#include "catalog/pg_class.h"
+#include "catalog/pg_type.h"
+#include "commands/extension.h"
+#include "miscadmin.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
/* THIS IS USED ONLY FOR PG >= 9.0 */
-/*
- * Cannot include "catalog/pg_enum.h" here because we might
- * not be compiling against PG 9.0.
- */
-extern void EnumValuesCreate(Oid enumTypeOid, List *vals,
- Oid binary_upgrade_next_pg_enum_oid);
-
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_oid;
-extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_array_oid;
-extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_toast_oid;
-extern PGDLLIMPORT Oid binary_upgrade_next_heap_relfilenode;
-extern PGDLLIMPORT Oid binary_upgrade_next_toast_relfilenode;
-extern PGDLLIMPORT Oid binary_upgrade_next_index_relfilenode;
+extern PGDLLIMPORT Oid binary_upgrade_next_array_pg_type_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_type_oid;
+
+extern PGDLLIMPORT Oid binary_upgrade_next_heap_pg_class_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_index_pg_class_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_class_oid;
+
+extern PGDLLIMPORT Oid binary_upgrade_next_pg_enum_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_pg_authid_oid;
Datum set_next_pg_type_oid(PG_FUNCTION_ARGS);
-Datum set_next_pg_type_array_oid(PG_FUNCTION_ARGS);
-Datum set_next_pg_type_toast_oid(PG_FUNCTION_ARGS);
-Datum set_next_heap_relfilenode(PG_FUNCTION_ARGS);
-Datum set_next_toast_relfilenode(PG_FUNCTION_ARGS);
-Datum set_next_index_relfilenode(PG_FUNCTION_ARGS);
-Datum add_pg_enum_label(PG_FUNCTION_ARGS);
+Datum set_next_array_pg_type_oid(PG_FUNCTION_ARGS);
+Datum set_next_toast_pg_type_oid(PG_FUNCTION_ARGS);
+
+Datum set_next_heap_pg_class_oid(PG_FUNCTION_ARGS);
+Datum set_next_index_pg_class_oid(PG_FUNCTION_ARGS);
+Datum set_next_toast_pg_class_oid(PG_FUNCTION_ARGS);
+
+Datum set_next_pg_enum_oid(PG_FUNCTION_ARGS);
+Datum set_next_pg_authid_oid(PG_FUNCTION_ARGS);
+
+Datum create_empty_extension(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(set_next_pg_type_oid);
-PG_FUNCTION_INFO_V1(set_next_pg_type_array_oid);
-PG_FUNCTION_INFO_V1(set_next_pg_type_toast_oid);
-PG_FUNCTION_INFO_V1(set_next_heap_relfilenode);
-PG_FUNCTION_INFO_V1(set_next_toast_relfilenode);
-PG_FUNCTION_INFO_V1(set_next_index_relfilenode);
-PG_FUNCTION_INFO_V1(add_pg_enum_label);
+PG_FUNCTION_INFO_V1(set_next_array_pg_type_oid);
+PG_FUNCTION_INFO_V1(set_next_toast_pg_type_oid);
+
+PG_FUNCTION_INFO_V1(set_next_heap_pg_class_oid);
+PG_FUNCTION_INFO_V1(set_next_index_pg_class_oid);
+PG_FUNCTION_INFO_V1(set_next_toast_pg_class_oid);
+
+PG_FUNCTION_INFO_V1(set_next_pg_enum_oid);
+PG_FUNCTION_INFO_V1(set_next_pg_authid_oid);
+
+PG_FUNCTION_INFO_V1(create_empty_extension);
+
Datum
set_next_pg_type_oid(PG_FUNCTION_ARGS)
@@ -61,64 +76,124 @@ set_next_pg_type_oid(PG_FUNCTION_ARGS)
}
Datum
-set_next_pg_type_array_oid(PG_FUNCTION_ARGS)
+set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
{
Oid typoid = PG_GETARG_OID(0);
- binary_upgrade_next_pg_type_array_oid = typoid;
+ binary_upgrade_next_array_pg_type_oid = typoid;
PG_RETURN_VOID();
}
Datum
-set_next_pg_type_toast_oid(PG_FUNCTION_ARGS)
+set_next_toast_pg_type_oid(PG_FUNCTION_ARGS)
{
Oid typoid = PG_GETARG_OID(0);
- binary_upgrade_next_pg_type_toast_oid = typoid;
+ binary_upgrade_next_toast_pg_type_oid = typoid;
PG_RETURN_VOID();
}
Datum
-set_next_heap_relfilenode(PG_FUNCTION_ARGS)
+set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
{
- Oid relfilenode = PG_GETARG_OID(0);
+ Oid reloid = PG_GETARG_OID(0);
- binary_upgrade_next_heap_relfilenode = relfilenode;
+ binary_upgrade_next_heap_pg_class_oid = reloid;
PG_RETURN_VOID();
}
Datum
-set_next_toast_relfilenode(PG_FUNCTION_ARGS)
+set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
{
- Oid relfilenode = PG_GETARG_OID(0);
+ Oid reloid = PG_GETARG_OID(0);
- binary_upgrade_next_toast_relfilenode = relfilenode;
+ binary_upgrade_next_index_pg_class_oid = reloid;
PG_RETURN_VOID();
}
Datum
-set_next_index_relfilenode(PG_FUNCTION_ARGS)
+set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
{
- Oid relfilenode = PG_GETARG_OID(0);
+ Oid reloid = PG_GETARG_OID(0);
- binary_upgrade_next_index_relfilenode = relfilenode;
+ binary_upgrade_next_toast_pg_class_oid = reloid;
PG_RETURN_VOID();
}
Datum
-add_pg_enum_label(PG_FUNCTION_ARGS)
+set_next_pg_enum_oid(PG_FUNCTION_ARGS)
{
Oid enumoid = PG_GETARG_OID(0);
- Oid typoid = PG_GETARG_OID(1);
- Name label = PG_GETARG_NAME(2);
- EnumValuesCreate(typoid, list_make1(makeString(NameStr(*label))),
- enumoid);
+ binary_upgrade_next_pg_enum_oid = enumoid;
+
+ PG_RETURN_VOID();
+}
+
+Datum
+set_next_pg_authid_oid(PG_FUNCTION_ARGS)
+{
+ Oid authoid = PG_GETARG_OID(0);
+
+ binary_upgrade_next_pg_authid_oid = authoid;
+ PG_RETURN_VOID();
+}
+
+Datum
+create_empty_extension(PG_FUNCTION_ARGS)
+{
+ text *extName = PG_GETARG_TEXT_PP(0);
+ text *schemaName = PG_GETARG_TEXT_PP(1);
+ bool relocatable = PG_GETARG_BOOL(2);
+ text *extVersion = PG_GETARG_TEXT_PP(3);
+ Datum extConfig;
+ Datum extCondition;
+ List *requiredExtensions;
+
+ if (PG_ARGISNULL(4))
+ extConfig = PointerGetDatum(NULL);
+ else
+ extConfig = PG_GETARG_DATUM(4);
+
+ if (PG_ARGISNULL(5))
+ extCondition = PointerGetDatum(NULL);
+ else
+ extCondition = PG_GETARG_DATUM(5);
+
+ requiredExtensions = NIL;
+ if (!PG_ARGISNULL(6))
+ {
+ ArrayType *textArray = PG_GETARG_ARRAYTYPE_P(6);
+ Datum *textDatums;
+ int ndatums;
+ int i;
+
+ deconstruct_array(textArray,
+ TEXTOID, -1, false, 'i',
+ &textDatums, NULL, &ndatums);
+ for (i = 0; i < ndatums; i++)
+ {
+ text *txtname = DatumGetTextPP(textDatums[i]);
+ char *extName = text_to_cstring(txtname);
+ Oid extOid = get_extension_oid(extName, false);
+
+ requiredExtensions = lappend_oid(requiredExtensions, extOid);
+ }
+ }
+
+ InsertExtensionTuple(text_to_cstring(extName),
+ GetUserId(),
+ get_namespace_oid(text_to_cstring(schemaName), false),
+ relocatable,
+ text_to_cstring(extVersion),
+ extConfig,
+ extCondition,
+ requiredExtensions);
PG_RETURN_VOID();
}
diff --git a/contrib/pgbench/.gitignore b/contrib/pgbench/.gitignore
new file mode 100644
index 0000000000..489a2d62d0
--- /dev/null
+++ b/contrib/pgbench/.gitignore
@@ -0,0 +1 @@
+/pgbench
diff --git a/contrib/pgbench/Makefile b/contrib/pgbench/Makefile
index 786ba10fd9..b8f5fb467f 100644
--- a/contrib/pgbench/Makefile
+++ b/contrib/pgbench/Makefile
@@ -1,7 +1,7 @@
-# $PostgreSQL: pgsql/contrib/pgbench/Makefile,v 1.18 2010/05/12 11:33:08 momjian Exp $
+# contrib/pgbench/Makefile
PGFILEDESC = "pgbench - a simple program for running benchmark tests"
-PGAPPICON=win32
+PGAPPICON = win32
PROGRAM = pgbench
OBJS = pgbench.o
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index 1ca58d4c2f..e424af4cf3 100644
--- a/contrib/pgbench/pgbench.c
+++ b/contrib/pgbench/pgbench.c
@@ -4,8 +4,8 @@
* A simple benchmark program for PostgreSQL
* Originally written by Tatsuo Ishii and enhanced by many contributors.
*
- * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.99 2010/07/06 19:18:55 momjian Exp $
- * Copyright (c) 2000-2010, PostgreSQL Global Development Group
+ * contrib/pgbench/pgbench.c
+ * Copyright (c) 2000-2011, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
* Permission to use, copy, modify, and distribute this software and its
@@ -69,7 +69,7 @@
typedef struct win32_pthread *pthread_t;
typedef int pthread_attr_t;
-static int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
+static int pthread_create(pthread_t *thread, pthread_attr_t * attr, void *(*start_routine) (void *), void *arg);
static int pthread_join(pthread_t th, void **thread_return);
#elif defined(ENABLE_THREAD_SAFETY)
/* Use platform-dependent pthread capability */
@@ -87,7 +87,7 @@ static int pthread_join(pthread_t th, void **thread_return);
typedef struct fork_pthread *pthread_t;
typedef int pthread_attr_t;
-static int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
+static int pthread_create(pthread_t *thread, pthread_attr_t * attr, void *(*start_routine) (void *), void *arg);
static int pthread_join(pthread_t th, void **thread_return);
#endif
@@ -136,6 +136,7 @@ bool use_branch = true; /* use branch id in DDL and DML */
#endif
bool use_log; /* log transaction latencies to a file */
bool is_connect; /* establish connection for each transaction */
+bool is_latencies; /* report per-command latencies */
int main_pid; /* main process id used in log filename */
char *pghost = "";
@@ -174,7 +175,8 @@ typedef struct
int64 until; /* napping until (usec) */
Variable *variables; /* array of variable definitions */
int nvariables;
- instr_time txn_begin; /* used for measuring latencies */
+ instr_time txn_begin; /* used for measuring transaction latencies */
+ instr_time stmt_begin; /* used for measuring statement latencies */
int use_file; /* index in sql_files for this client */
bool prepared[MAX_FILES];
} CState;
@@ -189,6 +191,8 @@ typedef struct
CState *state; /* array of CState */
int nstate; /* length of state[] */
instr_time start_time; /* thread start time */
+ instr_time *exec_elapsed; /* time spent executing cmds (per Command) */
+ int *exec_count; /* number of cmd executions (per Command) */
} TState;
#define INVALID_THREAD ((pthread_t) 0)
@@ -219,13 +223,16 @@ static const char *QUERYMODE[] = {"simple", "extended", "prepared"};
typedef struct
{
+ char *line; /* full text of command line */
+ int command_num; /* unique index of this Command struct */
int type; /* command type (SQL_COMMAND or META_COMMAND) */
- int argc; /* number of commands */
- char *argv[MAX_ARGS]; /* command list */
+ int argc; /* number of command words */
+ char *argv[MAX_ARGS]; /* command word list */
} Command;
static Command **sql_files[MAX_FILES]; /* SQL script files */
static int num_files; /* number of script files */
+static int num_commands = 0; /* total number of Command structs */
static int debug = 0; /* debug flag */
/* default scenario */
@@ -310,6 +317,53 @@ static char *select_only = {
static void setalarm(int seconds);
static void *threadRun(void *arg);
+
+/*
+ * routines to check mem allocations and fail noisily.
+ */
+static void *
+xmalloc(size_t size)
+{
+ void *result;
+
+ result = malloc(size);
+ if (!result)
+ {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ return result;
+}
+
+static void *
+xrealloc(void *ptr, size_t size)
+{
+ void *result;
+
+ result = realloc(ptr, size);
+ if (!result)
+ {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ return result;
+}
+
+static char *
+xstrdup(const char *s)
+{
+ char *result;
+
+ result = strdup(s);
+ if (!result)
+ {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ return result;
+}
+
+
static void
usage(const char *progname)
{
@@ -338,6 +392,7 @@ usage(const char *progname)
" protocol for submitting queries to server (default: simple)\n"
" -n do not run VACUUM before tests\n"
" -N do not update tables \"pgbench_tellers\" and \"pgbench_branches\"\n"
+ " -r report average latency per command\n"
" -s NUM report this scale factor in output\n"
" -S perform SELECT-only transactions\n"
" -t NUM number of transactions each client runs (default: 10)\n"
@@ -518,28 +573,17 @@ putVariable(CState *st, const char *context, char *name, char *value)
}
if (st->variables)
- newvars = (Variable *) realloc(st->variables,
+ newvars = (Variable *) xrealloc(st->variables,
(st->nvariables + 1) * sizeof(Variable));
else
- newvars = (Variable *) malloc(sizeof(Variable));
-
- if (newvars == NULL)
- goto out_of_memory;
+ newvars = (Variable *) xmalloc(sizeof(Variable));
st->variables = newvars;
var = &newvars[st->nvariables];
- var->name = NULL;
- var->value = NULL;
-
- if ((var->name = strdup(name)) == NULL ||
- (var->value = strdup(value)) == NULL)
- {
- free(var->name);
- free(var->value);
- return false;
- }
+ var->name = xstrdup(name);
+ var->value = xstrdup(value);
st->nvariables++;
@@ -550,18 +594,14 @@ putVariable(CState *st, const char *context, char *name, char *value)
{
char *val;
- if ((val = strdup(value)) == NULL)
- return false;
+ /* dup then free, in case value is pointing at this variable */
+ val = xstrdup(value);
free(var->value);
var->value = val;
}
return true;
-
-out_of_memory:
- fprintf(stderr, "%s: out of memory for variable '%s'\n", context, name);
- return false;
}
static char *
@@ -577,9 +617,7 @@ parseVariable(const char *sql, int *eaten)
if (i == 1)
return NULL;
- name = malloc(i);
- if (name == NULL)
- return NULL;
+ name = xmalloc(i);
memcpy(name, &sql[1], i - 1);
name[i - 1] = '\0';
@@ -594,16 +632,9 @@ replaceVariable(char **sql, char *param, int len, char *value)
if (valueln > len)
{
- char *tmp;
size_t offset = param - *sql;
- tmp = realloc(*sql, strlen(*sql) - len + valueln + 1);
- if (tmp == NULL)
- {
- free(*sql);
- return NULL;
- }
- *sql = tmp;
+ *sql = xrealloc(*sql, strlen(*sql) - len + valueln + 1);
param = *sql + offset;
}
@@ -644,8 +675,7 @@ assignVariables(CState *st, char *sql)
continue;
}
- if ((p = replaceVariable(&sql, p, eaten, val)) == NULL)
- return NULL;
+ p = replaceVariable(&sql, p, eaten, val);
}
return sql;
@@ -675,11 +705,13 @@ runShellCommand(CState *st, char *variable, char **argv, int argc)
char *endptr;
int retval;
- /*
- * Join arguments with whilespace separaters. Arguments starting with
- * exactly one colon are treated as variables: name - append a string
- * "name" :var - append a variable named 'var'. ::name - append a string
- * ":name"
+ /*----------
+ * Join arguments with whitespace separators. Arguments starting with
+ * exactly one colon are treated as variables:
+ * name - append a string "name"
+ * :var - append a variable named 'var'
+ * ::name - append a string ":name"
+ *----------
*/
for (i = 0; i < argc; i++)
{
@@ -786,7 +818,7 @@ clientDone(CState *st, bool ok)
/* return false iff client should be disconnected */
static bool
-doCustom(CState *st, instr_time *conn_time, FILE *logfile)
+doCustom(TState *thread, CState *st, instr_time *conn_time, FILE *logfile)
{
PGresult *res;
Command **commands;
@@ -821,7 +853,22 @@ top:
}
/*
- * transaction finished: record the time it took in the log
+ * command finished: accumulate per-command execution times in
+ * thread-local data structure, if per-command latencies are requested
+ */
+ if (is_latencies)
+ {
+ instr_time now;
+ int cnum = commands[st->state]->command_num;
+
+ INSTR_TIME_SET_CURRENT(now);
+ INSTR_TIME_ACCUM_DIFF(thread->exec_elapsed[cnum],
+ now, st->stmt_begin);
+ thread->exec_count[cnum]++;
+ }
+
+ /*
+ * if transaction finished, record the time it took in the log
*/
if (logfile && commands[st->state + 1] == NULL)
{
@@ -848,6 +895,10 @@ top:
if (commands[st->state]->type == SQL_COMMAND)
{
+ /*
+ * Read and discard the query result; note this is not included in
+ * the statement latency numbers.
+ */
res = PQgetResult(st->con);
switch (PQresultStatus(res))
{
@@ -902,9 +953,14 @@ top:
INSTR_TIME_ACCUM_DIFF(*conn_time, end, start);
}
+ /* Record transaction start time if logging is enabled */
if (logfile && st->state == 0)
INSTR_TIME_SET_CURRENT(st->txn_begin);
+ /* Record statement start time if per-command latencies are requested */
+ if (is_latencies)
+ INSTR_TIME_SET_CURRENT(st->stmt_begin);
+
if (commands[st->state]->type == SQL_COMMAND)
{
const Command *command = commands[st->state];
@@ -914,13 +970,8 @@ top:
{
char *sql;
- if ((sql = strdup(command->argv[0])) == NULL
- || (sql = assignVariables(st, sql)) == NULL)
- {
- fprintf(stderr, "out of memory\n");
- st->ecnt++;
- return true;
- }
+ sql = xstrdup(command->argv[0]);
+ sql = assignVariables(st, sql);
if (debug)
fprintf(stderr, "client %d sending %s\n", st->id, sql);
@@ -1433,9 +1484,7 @@ parseQuery(Command *cmd, const char *raw_sql)
char *sql,
*p;
- sql = strdup(raw_sql);
- if (sql == NULL)
- return false;
+ sql = xstrdup(raw_sql);
cmd->argc = 1;
p = sql;
@@ -1462,8 +1511,7 @@ parseQuery(Command *cmd, const char *raw_sql)
}
sprintf(var, "$%d", cmd->argc);
- if ((p = replaceVariable(&sql, p, eaten, var)) == NULL)
- return false;
+ p = replaceVariable(&sql, p, eaten, var);
cmd->argv[cmd->argc] = name;
cmd->argc++;
@@ -1473,6 +1521,7 @@ parseQuery(Command *cmd, const char *raw_sql)
return true;
}
+/* Parse a command; return a Command struct, or NULL if it's a comment */
static Command *
process_commands(char *buf)
{
@@ -1483,24 +1532,24 @@ process_commands(char *buf)
char *p,
*tok;
+ /* Make the string buf end at the next newline */
if ((p = strchr(buf, '\n')) != NULL)
*p = '\0';
+ /* Skip leading whitespace */
p = buf;
while (isspace((unsigned char) *p))
p++;
+ /* If the line is empty or actually a comment, we're done */
if (*p == '\0' || strncmp(p, "--", 2) == 0)
- {
return NULL;
- }
-
- my_commands = (Command *) malloc(sizeof(Command));
- if (my_commands == NULL)
- {
- return NULL;
- }
+ /* Allocate and initialize Command structure */
+ my_commands = (Command *) xmalloc(sizeof(Command));
+ my_commands->line = xstrdup(buf);
+ my_commands->command_num = num_commands++;
+ my_commands->type = 0; /* until set */
my_commands->argc = 0;
if (*p == '\\')
@@ -1512,12 +1561,8 @@ process_commands(char *buf)
while (tok != NULL)
{
- if ((my_commands->argv[j] = strdup(tok)) == NULL)
- return NULL;
-
+ my_commands->argv[j++] = xstrdup(tok);
my_commands->argc++;
-
- j++;
tok = strtok(NULL, delim);
}
@@ -1526,7 +1571,7 @@ process_commands(char *buf)
if (my_commands->argc < 4)
{
fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
- return NULL;
+ exit(1);
}
for (j = 4; j < my_commands->argc; j++)
@@ -1538,7 +1583,7 @@ process_commands(char *buf)
if (my_commands->argc < 3)
{
fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
- return NULL;
+ exit(1);
}
for (j = my_commands->argc < 5 ? 3 : 5; j < my_commands->argc; j++)
@@ -1550,7 +1595,7 @@ process_commands(char *buf)
if (my_commands->argc < 2)
{
fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
- return NULL;
+ exit(1);
}
/*
@@ -1581,7 +1626,7 @@ process_commands(char *buf)
{
fprintf(stderr, "%s: unknown time unit '%s' - must be us, ms or s\n",
my_commands->argv[0], my_commands->argv[2]);
- return NULL;
+ exit(1);
}
}
@@ -1594,7 +1639,7 @@ process_commands(char *buf)
if (my_commands->argc < 3)
{
fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
- return NULL;
+ exit(1);
}
}
else if (pg_strcasecmp(my_commands->argv[0], "shell") == 0)
@@ -1602,13 +1647,13 @@ process_commands(char *buf)
if (my_commands->argc < 1)
{
fprintf(stderr, "%s: missing command\n", my_commands->argv[0]);
- return NULL;
+ exit(1);
}
}
else
{
fprintf(stderr, "Invalid command %s\n", my_commands->argv[0]);
- return NULL;
+ exit(1);
}
}
else
@@ -1618,17 +1663,16 @@ process_commands(char *buf)
switch (querymode)
{
case QUERY_SIMPLE:
- if ((my_commands->argv[0] = strdup(p)) == NULL)
- return NULL;
+ my_commands->argv[0] = xstrdup(p);
my_commands->argc++;
break;
case QUERY_EXTENDED:
case QUERY_PREPARED:
if (!parseQuery(my_commands, p))
- return NULL;
+ exit(1);
break;
default:
- return NULL;
+ exit(1);
}
}
@@ -1653,9 +1697,7 @@ process_file(char *filename)
}
alloc_num = COMMANDS_ALLOC_NUM;
- my_commands = (Command **) malloc(sizeof(Command *) * alloc_num);
- if (my_commands == NULL)
- return false;
+ my_commands = (Command **) xmalloc(sizeof(Command *) * alloc_num);
if (strcmp(filename, "-") == 0)
fd = stdin;
@@ -1669,37 +1711,19 @@ process_file(char *filename)
while (fgets(buf, sizeof(buf), fd) != NULL)
{
- Command *commands;
- int i;
+ Command *command;
- i = 0;
- while (isspace((unsigned char) buf[i]))
- i++;
-
- if (buf[i] != '\0' && strncmp(&buf[i], "--", 2) != 0)
- {
- commands = process_commands(&buf[i]);
- if (commands == NULL)
- {
- fclose(fd);
- return false;
- }
- }
- else
+ command = process_commands(buf);
+ if (command == NULL)
continue;
- my_commands[lineno] = commands;
+ my_commands[lineno] = command;
lineno++;
if (lineno >= alloc_num)
{
alloc_num += COMMANDS_ALLOC_NUM;
- my_commands = realloc(my_commands, sizeof(Command *) * alloc_num);
- if (my_commands == NULL)
- {
- fclose(fd);
- return false;
- }
+ my_commands = xrealloc(my_commands, sizeof(Command *) * alloc_num);
}
}
fclose(fd);
@@ -1721,20 +1745,15 @@ process_builtin(char *tb)
char buf[BUFSIZ];
int alloc_num;
- if (*tb == '\0')
- return NULL;
-
alloc_num = COMMANDS_ALLOC_NUM;
- my_commands = (Command **) malloc(sizeof(Command *) * alloc_num);
- if (my_commands == NULL)
- return NULL;
+ my_commands = (Command **) xmalloc(sizeof(Command *) * alloc_num);
lineno = 0;
for (;;)
{
char *p;
- Command *commands;
+ Command *command;
p = buf;
while (*tb && *tb != '\n')
@@ -1748,23 +1767,17 @@ process_builtin(char *tb)
*p = '\0';
- commands = process_commands(buf);
- if (commands == NULL)
- {
- return NULL;
- }
+ command = process_commands(buf);
+ if (command == NULL)
+ continue;
- my_commands[lineno] = commands;
+ my_commands[lineno] = command;
lineno++;
if (lineno >= alloc_num)
{
alloc_num += COMMANDS_ALLOC_NUM;
- my_commands = realloc(my_commands, sizeof(Command *) * alloc_num);
- if (my_commands == NULL)
- {
- return NULL;
- }
+ my_commands = xrealloc(my_commands, sizeof(Command *) * alloc_num);
}
}
@@ -1775,7 +1788,8 @@ process_builtin(char *tb)
/* print out results */
static void
-printResults(int ttype, int normal_xacts, int nclients, int nthreads,
+printResults(int ttype, int normal_xacts, int nclients,
+ TState *threads, int nthreads,
instr_time total_time, instr_time conn_total_time)
{
double time_include,
@@ -1816,6 +1830,51 @@ printResults(int ttype, int normal_xacts, int nclients, int nthreads,
}
printf("tps = %f (including connections establishing)\n", tps_include);
printf("tps = %f (excluding connections establishing)\n", tps_exclude);
+
+ /* Report per-command latencies */
+ if (is_latencies)
+ {
+ int i;
+
+ for (i = 0; i < num_files; i++)
+ {
+ Command **commands;
+
+ if (num_files > 1)
+ printf("statement latencies in milliseconds, file %d:\n", i + 1);
+ else
+ printf("statement latencies in milliseconds:\n");
+
+ for (commands = sql_files[i]; *commands != NULL; commands++)
+ {
+ Command *command = *commands;
+ int cnum = command->command_num;
+ double total_time;
+ instr_time total_exec_elapsed;
+ int total_exec_count;
+ int t;
+
+ /* Accumulate per-thread data for command */
+ INSTR_TIME_SET_ZERO(total_exec_elapsed);
+ total_exec_count = 0;
+ for (t = 0; t < nthreads; t++)
+ {
+ TState *thread = &threads[t];
+
+ INSTR_TIME_ADD(total_exec_elapsed,
+ thread->exec_elapsed[cnum]);
+ total_exec_count += thread->exec_count[cnum];
+ }
+
+ if (total_exec_count > 0)
+ total_time = INSTR_TIME_GET_MILLISEC(total_exec_elapsed) / (double) total_exec_count;
+ else
+ total_time = 0.0;
+
+ printf("\t%f\t%s\n", total_time, command->line);
+ }
+ }
+ }
}
@@ -1883,19 +1942,13 @@ main(int argc, char **argv)
else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
login = env;
- state = (CState *) malloc(sizeof(CState));
- if (state == NULL)
- {
- fprintf(stderr, "Couldn't allocate memory for state\n");
- exit(1);
- }
-
- memset(state, 0, sizeof(*state));
+ state = (CState *) xmalloc(sizeof(CState));
+ memset(state, 0, sizeof(CState));
#ifdef PGXC
- while ((c = getopt(argc, argv, "ih:knvp:dSNc:Cs:t:T:U:lf:D:F:M:j:")) != -1)
+ while ((c = getopt(argc, argv, "ih:knvp:dSNc:j:Crs:t:T:U:lf:D:F:M:")) != -1)
#else
- while ((c = getopt(argc, argv, "ih:nvp:dSNc:Cs:t:T:U:lf:D:F:M:j:")) != -1)
+ while ((c = getopt(argc, argv, "ih:nvp:dSNc:j:Crs:t:T:U:lf:D:F:M:")) != -1)
#endif
{
switch (c)
@@ -1965,6 +2018,9 @@ main(int argc, char **argv)
case 'C':
is_connect = true;
break;
+ case 'r':
+ is_latencies = true;
+ break;
case 's':
scale_given = true;
scale = atoi(optarg);
@@ -2086,6 +2142,22 @@ main(int argc, char **argv)
}
/*
+ * is_latencies only works with multiple threads in thread-based
+ * implementations, not fork-based ones, because it supposes that the
+ * parent can see changes made to the per-thread execution stats by child
+ * threads. It seems useful enough to accept despite this limitation, but
+ * perhaps we should FIXME someday (by passing the stats data back up
+ * through the parent-to-child pipes).
+ */
+#ifndef ENABLE_THREAD_SAFETY
+ if (is_latencies && nthreads > 1)
+ {
+ fprintf(stderr, "-r does not work with -j larger than 1 on this platform.\n");
+ exit(1);
+ }
+#endif
+
+ /*
* save main process id in the global variable because process id will be
* changed after fork.
*/
@@ -2093,14 +2165,8 @@ main(int argc, char **argv)
if (nclients > 1)
{
- state = (CState *) realloc(state, sizeof(CState) * nclients);
- if (state == NULL)
- {
- fprintf(stderr, "Couldn't allocate memory for state\n");
- exit(1);
- }
-
- memset(state + 1, 0, sizeof(*state) * (nclients - 1));
+ state = (CState *) xrealloc(state, sizeof(CState) * nclients);
+ memset(state + 1, 0, sizeof(CState) * (nclients - 1));
/* copy any -D switch values to all clients */
for (i = 1; i < nclients; i++)
@@ -2235,6 +2301,39 @@ main(int argc, char **argv)
break;
}
+ /* set up thread data structures */
+ threads = (TState *) xmalloc(sizeof(TState) * nthreads);
+ for (i = 0; i < nthreads; i++)
+ {
+ TState *thread = &threads[i];
+
+ thread->tid = i;
+ thread->state = &state[nclients / nthreads * i];
+ thread->nstate = nclients / nthreads;
+
+ if (is_latencies)
+ {
+ /* Reserve memory for the thread to store per-command latencies */
+ int t;
+
+ thread->exec_elapsed = (instr_time *)
+ xmalloc(sizeof(instr_time) * num_commands);
+ thread->exec_count = (int *)
+ xmalloc(sizeof(int) * num_commands);
+
+ for (t = 0; t < num_commands; t++)
+ {
+ INSTR_TIME_SET_ZERO(thread->exec_elapsed[t]);
+ thread->exec_count[t] = 0;
+ }
+ }
+ else
+ {
+ thread->exec_elapsed = NULL;
+ thread->exec_count = NULL;
+ }
+ }
+
/* get start up time */
INSTR_TIME_SET_CURRENT(start_time);
@@ -2243,20 +2342,18 @@ main(int argc, char **argv)
setalarm(duration);
/* start threads */
- threads = (TState *) malloc(sizeof(TState) * nthreads);
for (i = 0; i < nthreads; i++)
{
- threads[i].tid = i;
- threads[i].state = &state[nclients / nthreads * i];
- threads[i].nstate = nclients / nthreads;
- INSTR_TIME_SET_CURRENT(threads[i].start_time);
+ TState *thread = &threads[i];
+
+ INSTR_TIME_SET_CURRENT(thread->start_time);
/* the first thread (i = 0) is executed by main thread */
if (i > 0)
{
- int err = pthread_create(&threads[i].thread, NULL, threadRun, &threads[i]);
+ int err = pthread_create(&thread->thread, NULL, threadRun, thread);
- if (err != 0 || threads[i].thread == INVALID_THREAD)
+ if (err != 0 || thread->thread == INVALID_THREAD)
{
fprintf(stderr, "cannot create thread: %s\n", strerror(err));
exit(1);
@@ -2264,7 +2361,7 @@ main(int argc, char **argv)
}
else
{
- threads[i].thread = INVALID_THREAD;
+ thread->thread = INVALID_THREAD;
}
}
@@ -2294,7 +2391,8 @@ main(int argc, char **argv)
/* get end time */
INSTR_TIME_SET_CURRENT(total_time);
INSTR_TIME_SUBTRACT(total_time, start_time);
- printResults(ttype, total_xacts, nclients, nthreads, total_time, conn_total_time);
+ printResults(ttype, total_xacts, nclients, threads, nthreads,
+ total_time, conn_total_time);
return 0;
}
@@ -2312,7 +2410,7 @@ threadRun(void *arg)
int remains = nstate; /* number of remaining clients */
int i;
- result = malloc(sizeof(TResult));
+ result = xmalloc(sizeof(TResult));
INSTR_TIME_SET_ZERO(result->conn_time);
/* open log file if requested */
@@ -2355,7 +2453,7 @@ threadRun(void *arg)
int prev_ecnt = st->ecnt;
st->use_file = getrand(0, num_files - 1);
- if (!doCustom(st, &result->conn_time, logfile))
+ if (!doCustom(thread, st, &result->conn_time, logfile))
remains--; /* I've aborted */
if (st->ecnt > prev_ecnt && commands[st->state]->type == META_COMMAND)
@@ -2457,7 +2555,7 @@ threadRun(void *arg)
if (st->con && (FD_ISSET(PQsocket(st->con), &input_mask)
|| commands[st->state]->type == META_COMMAND))
{
- if (!doCustom(st, &result->conn_time, logfile))
+ if (!doCustom(thread, st, &result->conn_time, logfile))
remains--; /* I've aborted */
}
@@ -2518,7 +2616,7 @@ typedef struct fork_pthread
static int
pthread_create(pthread_t *thread,
- pthread_attr_t *attr,
+ pthread_attr_t * attr,
void *(*start_routine) (void *),
void *arg)
{
@@ -2526,8 +2624,12 @@ pthread_create(pthread_t *thread,
void *ret;
instr_time start_time;
- th = (fork_pthread *) malloc(sizeof(fork_pthread));
- pipe(th->pipes);
+ th = (fork_pthread *) xmalloc(sizeof(fork_pthread));
+ if (pipe(th->pipes) < 0)
+ {
+ free(th);
+ return errno;
+ }
th->pid = fork();
if (th->pid == -1) /* error */
@@ -2581,7 +2683,7 @@ pthread_join(pthread_t th, void **thread_return)
if (thread_return != NULL)
{
/* assume result is TResult */
- *thread_return = malloc(sizeof(TResult));
+ *thread_return = xmalloc(sizeof(TResult));
if (read(th->pipes[0], *thread_return, sizeof(TResult)) != sizeof(TResult))
{
free(*thread_return);
@@ -2628,7 +2730,7 @@ typedef struct win32_pthread
void *(*routine) (void *);
void *arg;
void *result;
-} win32_pthread;
+} win32_pthread;
static unsigned __stdcall
win32_pthread_run(void *arg)
@@ -2642,14 +2744,14 @@ win32_pthread_run(void *arg)
static int
pthread_create(pthread_t *thread,
- pthread_attr_t *attr,
+ pthread_attr_t * attr,
void *(*start_routine) (void *),
void *arg)
{
int save_errno;
win32_pthread *th;
- th = (win32_pthread *) malloc(sizeof(win32_pthread));
+ th = (win32_pthread *) xmalloc(sizeof(win32_pthread));
th->routine = start_routine;
th->arg = arg;
th->result = NULL;
diff --git a/contrib/pgcrypto/.gitignore b/contrib/pgcrypto/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/pgcrypto/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index cfb586ba49..dadec953c2 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -1,6 +1,4 @@
-#
-# $PostgreSQL: pgsql/contrib/pgcrypto/Makefile,v 1.27 2007/11/10 23:59:51 momjian Exp $
-#
+# contrib/pgcrypto/Makefile
INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \
fortuna.c random.c pgp-mpi-internal.c imath.c
@@ -26,9 +24,9 @@ SRCS = pgcrypto.c px.c px-hmac.c px-crypt.c \
MODULE_big = pgcrypto
OBJS = $(SRCS:.c=.o)
-DATA_built = pgcrypto.sql
-DATA = uninstall_pgcrypto.sql
-EXTRA_CLEAN = gen-rtab
+
+EXTENSION = pgcrypto
+DATA = pgcrypto--1.0.sql pgcrypto--unpackaged--1.0.sql
REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
$(CF_TESTS) \
@@ -36,6 +34,7 @@ REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
pgp-armor pgp-decrypt pgp-encrypt $(CF_PGP_TESTS) \
pgp-pubkey-decrypt pgp-pubkey-encrypt pgp-info
+EXTRA_CLEAN = gen-rtab
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/pgcrypto/blf.c b/contrib/pgcrypto/blf.c
index e03c542c0d..f8a2c63c9f 100644
--- a/contrib/pgcrypto/blf.c
+++ b/contrib/pgcrypto/blf.c
@@ -1,7 +1,7 @@
/*
* Butchered version of sshblowf.c from putty-0.59.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/blf.c,v 1.10 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/blf.c
*/
/*
diff --git a/contrib/pgcrypto/blf.h b/contrib/pgcrypto/blf.h
index 507d7f9055..84aba37ba8 100644
--- a/contrib/pgcrypto/blf.h
+++ b/contrib/pgcrypto/blf.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/pgcrypto/blf.h,v 1.8 2009/06/11 14:48:52 momjian Exp $ */
+/* contrib/pgcrypto/blf.h */
/*
* PuTTY is copyright 1997-2007 Simon Tatham.
*
diff --git a/contrib/pgcrypto/crypt-blowfish.c b/contrib/pgcrypto/crypt-blowfish.c
index 9c1d2d4706..a7b7e758ff 100644
--- a/contrib/pgcrypto/crypt-blowfish.c
+++ b/contrib/pgcrypto/crypt-blowfish.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pgcrypto/crypt-blowfish.c,v 1.14 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/crypt-blowfish.c
*
* This code comes from John the Ripper password cracker, with reentrant
* and crypt(3) interfaces added, but optimizations specific to password
diff --git a/contrib/pgcrypto/crypt-des.c b/contrib/pgcrypto/crypt-des.c
index a907626d39..1f497432da 100644
--- a/contrib/pgcrypto/crypt-des.c
+++ b/contrib/pgcrypto/crypt-des.c
@@ -1,7 +1,7 @@
/*
* FreeSec: libcrypt for NetBSD
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/crypt-des.c,v 1.15 2006/07/13 04:15:24 neilc Exp $
+ * contrib/pgcrypto/crypt-des.c
*
* Copyright (c) 1994 David Burren
* All rights reserved.
diff --git a/contrib/pgcrypto/crypt-gensalt.c b/contrib/pgcrypto/crypt-gensalt.c
index b2ec3da828..84bf27bedb 100644
--- a/contrib/pgcrypto/crypt-gensalt.c
+++ b/contrib/pgcrypto/crypt-gensalt.c
@@ -2,7 +2,7 @@
* Written by Solar Designer and placed in the public domain.
* See crypt_blowfish.c for more information.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/crypt-gensalt.c,v 1.11 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/crypt-gensalt.c
*
* This file contains salt generation functions for the traditional and
* other common crypt(3) algorithms, except for bcrypt which is defined
diff --git a/contrib/pgcrypto/crypt-md5.c b/contrib/pgcrypto/crypt-md5.c
index d70fc341af..30eb8bf5a2 100644
--- a/contrib/pgcrypto/crypt-md5.c
+++ b/contrib/pgcrypto/crypt-md5.c
@@ -3,7 +3,7 @@
*
* $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/crypt-md5.c,v 1.9 2009/04/15 18:58:24 mha Exp $
+ * contrib/pgcrypto/crypt-md5.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/expected/blowfish.out b/contrib/pgcrypto/expected/blowfish.out
index 86c3244cec..72557ea161 100644
--- a/contrib/pgcrypto/expected/blowfish.out
+++ b/contrib/pgcrypto/expected/blowfish.out
@@ -108,7 +108,7 @@ decode('37363534333231204e6f77206973207468652074696d6520666f722000', 'hex'),
3ea6357a0ee7fad6d0c4b63464f2aafa40c2e91b4b7e1bba8114932fd92b5c8f111e7e50e7b2e541
(1 row)
--- blowfish-448
+-- blowfish-448
SELECT encode(encrypt(
decode('fedcba9876543210', 'hex'),
decode('f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455667704689104c2fd3b2f584023641aba61761f1f1f1f0e0e0e0effffffffffffffff', 'hex'),
@@ -120,21 +120,21 @@ decode('f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455667704689104c2fd3b2f58402364
-- result: c04504012e4e1f53
-- empty data
-select encode( encrypt('', 'foo', 'bf'), 'hex');
+select encode(encrypt('', 'foo', 'bf'), 'hex');
encode
------------------
1871949bb2311c8e
(1 row)
-- 10 bytes key
-select encode( encrypt('foo', '0123456789', 'bf'), 'hex');
+select encode(encrypt('foo', '0123456789', 'bf'), 'hex');
encode
------------------
42f58af3b2c03f46
(1 row)
-- 22 bytes key
-select encode( encrypt('foo', '0123456789012345678901', 'bf'), 'hex');
+select encode(encrypt('foo', '0123456789012345678901', 'bf'), 'hex');
encode
------------------
86ab6f0bc72b5f22
diff --git a/contrib/pgcrypto/expected/crypt-blowfish.out b/contrib/pgcrypto/expected/crypt-blowfish.out
index 8a8b007181..329d78f625 100644
--- a/contrib/pgcrypto/expected/crypt-blowfish.out
+++ b/contrib/pgcrypto/expected/crypt-blowfish.out
@@ -17,7 +17,7 @@ CREATE TABLE ctest (data text, res text, salt text);
INSERT INTO ctest VALUES ('password', '', '');
UPDATE ctest SET salt = gen_salt('bf', 8);
UPDATE ctest SET res = crypt(data, salt);
-SELECT res = crypt(data, res) AS "worked"
+SELECT res = crypt(data, res) AS "worked"
FROM ctest;
worked
--------
diff --git a/contrib/pgcrypto/expected/init.out b/contrib/pgcrypto/expected/init.out
index 4cb1081997..bd8f8e1380 100644
--- a/contrib/pgcrypto/expected/init.out
+++ b/contrib/pgcrypto/expected/init.out
@@ -1,13 +1,7 @@
--
-- init pgcrypto
--
---
--- first, define the functions. Turn off echoing so that expected file
--- does not depend on contents of pgcrypto.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION pgcrypto;
-- ensure consistent test output regardless of the default bytea format
SET bytea_output TO escape;
-- check for encoding fn's
diff --git a/contrib/pgcrypto/expected/rijndael.out b/contrib/pgcrypto/expected/rijndael.out
index 106181ef22..14b2650c32 100644
--- a/contrib/pgcrypto/expected/rijndael.out
+++ b/contrib/pgcrypto/expected/rijndael.out
@@ -70,21 +70,21 @@ decode('000102030405060708090a0b0c0d0e0f101112131415161718191a1b', 'hex'),
(1 row)
-- empty data
-select encode( encrypt('', 'foo', 'aes'), 'hex');
+select encode(encrypt('', 'foo', 'aes'), 'hex');
encode
----------------------------------
b48cc3338a2eb293b6007ef72c360d48
(1 row)
-- 10 bytes key
-select encode( encrypt('foo', '0123456789', 'aes'), 'hex');
+select encode(encrypt('foo', '0123456789', 'aes'), 'hex');
encode
----------------------------------
f397f03d2819b7172b68d0706fda4693
(1 row)
-- 22 bytes key
-select encode( encrypt('foo', '0123456789012345678901', 'aes'), 'hex');
+select encode(encrypt('foo', '0123456789012345678901', 'aes'), 'hex');
encode
----------------------------------
5c9db77af02b4678117bcd8a71ae7f53
@@ -105,7 +105,7 @@ select encode(encrypt_iv('foo', '0123456', 'abcd', 'aes'), 'hex');
(1 row)
select decrypt_iv(decode('2c24cb7da91d6d5699801268b0f5adad', 'hex'),
- '0123456', 'abcd', 'aes');
+ '0123456', 'abcd', 'aes');
decrypt_iv
------------
foo
diff --git a/contrib/pgcrypto/fortuna.c b/contrib/pgcrypto/fortuna.c
index 4e97946ab3..1228fb4ad0 100644
--- a/contrib/pgcrypto/fortuna.c
+++ b/contrib/pgcrypto/fortuna.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.9 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/fortuna.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/fortuna.h b/contrib/pgcrypto/fortuna.h
index b4d7064dec..2e49f8aab8 100644
--- a/contrib/pgcrypto/fortuna.h
+++ b/contrib/pgcrypto/fortuna.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.h,v 1.3 2005/10/15 02:49:06 momjian Exp $
+ * contrib/pgcrypto/fortuna.h
*/
#ifndef __FORTUNA_H
diff --git a/contrib/pgcrypto/imath.c b/contrib/pgcrypto/imath.c
index 51f1f00e30..de24076322 100644
--- a/contrib/pgcrypto/imath.c
+++ b/contrib/pgcrypto/imath.c
@@ -27,7 +27,7 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
-/* $PostgreSQL: pgsql/contrib/pgcrypto/imath.c,v 1.9 2010/04/02 15:21:20 mha Exp $ */
+/* contrib/pgcrypto/imath.c */
#include "postgres.h"
#include "px.h"
diff --git a/contrib/pgcrypto/imath.h b/contrib/pgcrypto/imath.h
index c7b29cf3a5..f2b02d0cd7 100644
--- a/contrib/pgcrypto/imath.h
+++ b/contrib/pgcrypto/imath.h
@@ -26,7 +26,7 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
-/* $PostgreSQL: pgsql/contrib/pgcrypto/imath.h,v 1.8 2010/04/02 15:21:20 mha Exp $ */
+/* contrib/pgcrypto/imath.h */
#ifndef IMATH_H_
#define IMATH_H_
diff --git a/contrib/pgcrypto/internal-sha2.c b/contrib/pgcrypto/internal-sha2.c
index 1e36a369e0..f86b47816b 100644
--- a/contrib/pgcrypto/internal-sha2.c
+++ b/contrib/pgcrypto/internal-sha2.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/internal-sha2.c,v 1.3 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/internal-sha2.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/internal.c b/contrib/pgcrypto/internal.c
index 84bda624a4..fedfe2dd03 100644
--- a/contrib/pgcrypto/internal.c
+++ b/contrib/pgcrypto/internal.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.29 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/internal.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/mbuf.c b/contrib/pgcrypto/mbuf.c
index d3eee2ee4f..6246900c7a 100644
--- a/contrib/pgcrypto/mbuf.c
+++ b/contrib/pgcrypto/mbuf.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/mbuf.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/mbuf.h b/contrib/pgcrypto/mbuf.h
index aa2b5596ee..37d2db5337 100644
--- a/contrib/pgcrypto/mbuf.h
+++ b/contrib/pgcrypto/mbuf.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/mbuf.h,v 1.3 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/mbuf.h
*/
#ifndef __PX_MBUF_H
diff --git a/contrib/pgcrypto/md5.c b/contrib/pgcrypto/md5.c
index 8083d1f280..b5071fba43 100644
--- a/contrib/pgcrypto/md5.c
+++ b/contrib/pgcrypto/md5.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/md5.c,v 1.15 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/md5.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/md5.h b/contrib/pgcrypto/md5.h
index eb7c620b48..03b9ab58ba 100644
--- a/contrib/pgcrypto/md5.h
+++ b/contrib/pgcrypto/md5.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/pgcrypto/md5.h,v 1.10 2009/06/11 14:48:52 momjian Exp $ */
+/* contrib/pgcrypto/md5.h */
/* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */
/*
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index bb0b4eefd3..dc25acea5d 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.33 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/openssl.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgcrypto.sql.in b/contrib/pgcrypto/pgcrypto--1.0.sql
index 8388e8620e..52be0950ce 100644
--- a/contrib/pgcrypto/pgcrypto.sql.in
+++ b/contrib/pgcrypto/pgcrypto--1.0.sql
@@ -1,64 +1,61 @@
-/* $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.sql.in,v 1.15 2007/11/13 04:24:28 momjian Exp $ */
+/* contrib/pgcrypto/pgcrypto--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION digest(text, text)
+CREATE FUNCTION digest(text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_digest'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION digest(bytea, text)
+CREATE FUNCTION digest(bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_digest'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION hmac(text, text, text)
+CREATE FUNCTION hmac(text, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_hmac'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION hmac(bytea, bytea, text)
+CREATE FUNCTION hmac(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_hmac'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION crypt(text, text)
+CREATE FUNCTION crypt(text, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_crypt'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gen_salt(text)
+CREATE FUNCTION gen_salt(text)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_gen_salt'
LANGUAGE C VOLATILE STRICT;
-CREATE OR REPLACE FUNCTION gen_salt(text, int4)
+CREATE FUNCTION gen_salt(text, int4)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_gen_salt_rounds'
LANGUAGE C VOLATILE STRICT;
-CREATE OR REPLACE FUNCTION encrypt(bytea, bytea, text)
+CREATE FUNCTION encrypt(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_encrypt'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION decrypt(bytea, bytea, text)
+CREATE FUNCTION decrypt(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_decrypt'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION encrypt_iv(bytea, bytea, bytea, text)
+CREATE FUNCTION encrypt_iv(bytea, bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_encrypt_iv'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION decrypt_iv(bytea, bytea, bytea, text)
+CREATE FUNCTION decrypt_iv(bytea, bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_decrypt_iv'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gen_random_bytes(int4)
+CREATE FUNCTION gen_random_bytes(int4)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_random_bytes'
LANGUAGE 'C' VOLATILE STRICT;
@@ -66,12 +63,12 @@ LANGUAGE 'C' VOLATILE STRICT;
--
-- pgp_sym_encrypt(data, key)
--
-CREATE OR REPLACE FUNCTION pgp_sym_encrypt(text, text)
+CREATE FUNCTION pgp_sym_encrypt(text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_text'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pgp_sym_encrypt_bytea(bytea, text)
+CREATE FUNCTION pgp_sym_encrypt_bytea(bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_bytea'
LANGUAGE C STRICT;
@@ -79,12 +76,12 @@ LANGUAGE C STRICT;
--
-- pgp_sym_encrypt(data, key, args)
--
-CREATE OR REPLACE FUNCTION pgp_sym_encrypt(text, text, text)
+CREATE FUNCTION pgp_sym_encrypt(text, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_text'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pgp_sym_encrypt_bytea(bytea, text, text)
+CREATE FUNCTION pgp_sym_encrypt_bytea(bytea, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_bytea'
LANGUAGE C STRICT;
@@ -92,12 +89,12 @@ LANGUAGE C STRICT;
--
-- pgp_sym_decrypt(data, key)
--
-CREATE OR REPLACE FUNCTION pgp_sym_decrypt(bytea, text)
+CREATE FUNCTION pgp_sym_decrypt(bytea, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_text'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION pgp_sym_decrypt_bytea(bytea, text)
+CREATE FUNCTION pgp_sym_decrypt_bytea(bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_bytea'
LANGUAGE C IMMUTABLE STRICT;
@@ -105,12 +102,12 @@ LANGUAGE C IMMUTABLE STRICT;
--
-- pgp_sym_decrypt(data, key, args)
--
-CREATE OR REPLACE FUNCTION pgp_sym_decrypt(bytea, text, text)
+CREATE FUNCTION pgp_sym_decrypt(bytea, text, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_text'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION pgp_sym_decrypt_bytea(bytea, text, text)
+CREATE FUNCTION pgp_sym_decrypt_bytea(bytea, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_bytea'
LANGUAGE C IMMUTABLE STRICT;
@@ -118,12 +115,12 @@ LANGUAGE C IMMUTABLE STRICT;
--
-- pgp_pub_encrypt(data, key)
--
-CREATE OR REPLACE FUNCTION pgp_pub_encrypt(text, bytea)
+CREATE FUNCTION pgp_pub_encrypt(text, bytea)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_text'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea)
+CREATE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_bytea'
LANGUAGE C STRICT;
@@ -131,12 +128,12 @@ LANGUAGE C STRICT;
--
-- pgp_pub_encrypt(data, key, args)
--
-CREATE OR REPLACE FUNCTION pgp_pub_encrypt(text, bytea, text)
+CREATE FUNCTION pgp_pub_encrypt(text, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_text'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text)
+CREATE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_bytea'
LANGUAGE C STRICT;
@@ -144,12 +141,12 @@ LANGUAGE C STRICT;
--
-- pgp_pub_decrypt(data, key)
--
-CREATE OR REPLACE FUNCTION pgp_pub_decrypt(bytea, bytea)
+CREATE FUNCTION pgp_pub_decrypt(bytea, bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea)
+CREATE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
LANGUAGE C IMMUTABLE STRICT;
@@ -157,12 +154,12 @@ LANGUAGE C IMMUTABLE STRICT;
--
-- pgp_pub_decrypt(data, key, psw)
--
-CREATE OR REPLACE FUNCTION pgp_pub_decrypt(bytea, bytea, text)
+CREATE FUNCTION pgp_pub_decrypt(bytea, bytea, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text)
+CREATE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
LANGUAGE C IMMUTABLE STRICT;
@@ -170,12 +167,12 @@ LANGUAGE C IMMUTABLE STRICT;
--
-- pgp_pub_decrypt(data, key, psw, arg)
--
-CREATE OR REPLACE FUNCTION pgp_pub_decrypt(bytea, bytea, text, text)
+CREATE FUNCTION pgp_pub_decrypt(bytea, bytea, text, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text)
+CREATE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
LANGUAGE C IMMUTABLE STRICT;
@@ -183,7 +180,7 @@ LANGUAGE C IMMUTABLE STRICT;
--
-- PGP key ID
--
-CREATE OR REPLACE FUNCTION pgp_key_id(bytea)
+CREATE FUNCTION pgp_key_id(bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_key_id_w'
LANGUAGE C IMMUTABLE STRICT;
@@ -191,13 +188,12 @@ LANGUAGE C IMMUTABLE STRICT;
--
-- pgp armor
--
-CREATE OR REPLACE FUNCTION armor(bytea)
+CREATE FUNCTION armor(bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_armor'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION dearmor(text)
+CREATE FUNCTION dearmor(text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_dearmor'
LANGUAGE C IMMUTABLE STRICT;
-
diff --git a/contrib/pgcrypto/pgcrypto--unpackaged--1.0.sql b/contrib/pgcrypto/pgcrypto--unpackaged--1.0.sql
new file mode 100644
index 0000000000..64f0cdf23a
--- /dev/null
+++ b/contrib/pgcrypto/pgcrypto--unpackaged--1.0.sql
@@ -0,0 +1,35 @@
+/* contrib/pgcrypto/pgcrypto--unpackaged--1.0.sql */
+
+ALTER EXTENSION pgcrypto ADD function digest(text,text);
+ALTER EXTENSION pgcrypto ADD function digest(bytea,text);
+ALTER EXTENSION pgcrypto ADD function hmac(text,text,text);
+ALTER EXTENSION pgcrypto ADD function hmac(bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function crypt(text,text);
+ALTER EXTENSION pgcrypto ADD function gen_salt(text);
+ALTER EXTENSION pgcrypto ADD function gen_salt(text,integer);
+ALTER EXTENSION pgcrypto ADD function encrypt(bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function decrypt(bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function encrypt_iv(bytea,bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function decrypt_iv(bytea,bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function gen_random_bytes(integer);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_encrypt(text,text);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_encrypt_bytea(bytea,text);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_encrypt(text,text,text);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_encrypt_bytea(bytea,text,text);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_decrypt(bytea,text);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_decrypt_bytea(bytea,text);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_decrypt(bytea,text,text);
+ALTER EXTENSION pgcrypto ADD function pgp_sym_decrypt_bytea(bytea,text,text);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_encrypt(text,bytea);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_encrypt_bytea(bytea,bytea);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_encrypt(text,bytea,text);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_encrypt_bytea(bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_decrypt(bytea,bytea);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_decrypt_bytea(bytea,bytea);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_decrypt(bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_decrypt_bytea(bytea,bytea,text);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_decrypt(bytea,bytea,text,text);
+ALTER EXTENSION pgcrypto ADD function pgp_pub_decrypt_bytea(bytea,bytea,text,text);
+ALTER EXTENSION pgcrypto ADD function pgp_key_id(bytea);
+ALTER EXTENSION pgcrypto ADD function armor(bytea);
+ALTER EXTENSION pgcrypto ADD function dearmor(text);
diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c
index 04c90d8672..d271ddc302 100644
--- a/contrib/pgcrypto/pgcrypto.c
+++ b/contrib/pgcrypto/pgcrypto.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.27 2008/03/25 22:42:41 tgl Exp $
+ * contrib/pgcrypto/pgcrypto.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgcrypto.control b/contrib/pgcrypto/pgcrypto.control
new file mode 100644
index 0000000000..8375cf9e7b
--- /dev/null
+++ b/contrib/pgcrypto/pgcrypto.control
@@ -0,0 +1,5 @@
+# pgcrypto extension
+comment = 'cryptographic functions'
+default_version = '1.0'
+module_pathname = '$libdir/pgcrypto'
+relocatable = true
diff --git a/contrib/pgcrypto/pgcrypto.h b/contrib/pgcrypto/pgcrypto.h
index b011b06062..6284ba2406 100644
--- a/contrib/pgcrypto/pgcrypto.h
+++ b/contrib/pgcrypto/pgcrypto.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.h,v 1.11 2006/09/05 21:26:48 tgl Exp $
+ * contrib/pgcrypto/pgcrypto.h
*/
#ifndef _PG_CRYPTO_H
diff --git a/contrib/pgcrypto/pgp-armor.c b/contrib/pgcrypto/pgp-armor.c
index 7963ccc329..87adf91125 100644
--- a/contrib/pgcrypto/pgp-armor.c
+++ b/contrib/pgcrypto/pgp-armor.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-armor.c,v 1.3 2005/10/15 02:49:06 momjian Exp $
+ * contrib/pgcrypto/pgp-armor.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-cfb.c b/contrib/pgcrypto/pgp-cfb.c
index bd05ccc94e..7cf9bf0b8c 100644
--- a/contrib/pgcrypto/pgp-cfb.c
+++ b/contrib/pgcrypto/pgp-cfb.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-cfb.c,v 1.4 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-cfb.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-compress.c b/contrib/pgcrypto/pgp-compress.c
index 41f5855247..7a9516b070 100644
--- a/contrib/pgcrypto/pgp-compress.c
+++ b/contrib/pgcrypto/pgp-compress.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-compress.c,v 1.8 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-compress.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-decrypt.c b/contrib/pgcrypto/pgp-decrypt.c
index 9df5c717f2..c9aa6cd66a 100644
--- a/contrib/pgcrypto/pgp-decrypt.c
+++ b/contrib/pgcrypto/pgp-decrypt.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-decrypt.c,v 1.8 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-decrypt.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-encrypt.c b/contrib/pgcrypto/pgp-encrypt.c
index 48f2f01f62..3b9b5d20ed 100644
--- a/contrib/pgcrypto/pgp-encrypt.c
+++ b/contrib/pgcrypto/pgp-encrypt.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-encrypt.c,v 1.4 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-encrypt.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-info.c b/contrib/pgcrypto/pgp-info.c
index a51a553236..b75266f18c 100644
--- a/contrib/pgcrypto/pgp-info.c
+++ b/contrib/pgcrypto/pgp-info.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-info.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-info.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-mpi-internal.c b/contrib/pgcrypto/pgp-mpi-internal.c
index 283946b17d..d0e5830fe0 100644
--- a/contrib/pgcrypto/pgp-mpi-internal.c
+++ b/contrib/pgcrypto/pgp-mpi-internal.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.8 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-mpi-internal.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-mpi-openssl.c b/contrib/pgcrypto/pgp-mpi-openssl.c
index f2b25de090..ed41e1151c 100644
--- a/contrib/pgcrypto/pgp-mpi-openssl.c
+++ b/contrib/pgcrypto/pgp-mpi-openssl.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-openssl.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-mpi-openssl.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-mpi.c b/contrib/pgcrypto/pgp-mpi.c
index 3f2ec0f5c7..c8765b6d14 100644
--- a/contrib/pgcrypto/pgp-mpi.c
+++ b/contrib/pgcrypto/pgp-mpi.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-mpi.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c
index 530a3d38d8..f1f09cd83b 100644
--- a/contrib/pgcrypto/pgp-pgsql.c
+++ b/contrib/pgcrypto/pgp-pgsql.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pgsql.c,v 1.11 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-pgsql.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-pubdec.c b/contrib/pgcrypto/pgp-pubdec.c
index cb32708fee..fe5fae0c42 100644
--- a/contrib/pgcrypto/pgp-pubdec.c
+++ b/contrib/pgcrypto/pgp-pubdec.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubdec.c,v 1.6 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-pubdec.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-pubenc.c b/contrib/pgcrypto/pgp-pubenc.c
index 0e9ebb4285..943d2e49f5 100644
--- a/contrib/pgcrypto/pgp-pubenc.c
+++ b/contrib/pgcrypto/pgp-pubenc.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubenc.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-pubenc.c
*/
#include "postgres.h"
@@ -199,7 +199,7 @@ pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
PGP_PubKey *pk = ctx->pub_key;
uint8 ver = 3;
PushFilter *pkt = NULL;
- uint8 algo = pk->algo;
+ uint8 algo;
if (pk == NULL)
{
@@ -207,6 +207,8 @@ pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
return PXE_BUG;
}
+ algo = pk->algo;
+
/*
* now write packet
*/
diff --git a/contrib/pgcrypto/pgp-pubkey.c b/contrib/pgcrypto/pgp-pubkey.c
index 62b6e1ab0e..283e0ec17e 100644
--- a/contrib/pgcrypto/pgp-pubkey.c
+++ b/contrib/pgcrypto/pgp-pubkey.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubkey.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-pubkey.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp-s2k.c b/contrib/pgcrypto/pgp-s2k.c
index 326b1bbf31..349234e243 100644
--- a/contrib/pgcrypto/pgp-s2k.c
+++ b/contrib/pgcrypto/pgp-s2k.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-s2k.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp-s2k.c
*/
#include "postgres.h"
@@ -39,14 +39,12 @@ static int
calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
unsigned key_len)
{
- unsigned md_bs,
- md_rlen;
+ unsigned md_rlen;
uint8 buf[PGP_MAX_DIGEST];
unsigned preload;
unsigned remain;
uint8 *dst = s2k->key;
- md_bs = px_md_block_size(md);
md_rlen = px_md_result_size(md);
remain = s2k->key_len;
@@ -83,14 +81,12 @@ calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
static int
calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
{
- unsigned md_bs,
- md_rlen;
+ unsigned md_rlen;
uint8 buf[PGP_MAX_DIGEST];
unsigned preload = 0;
uint8 *dst;
unsigned remain;
- md_bs = px_md_block_size(md);
md_rlen = px_md_result_size(md);
dst = s2k->key;
@@ -129,8 +125,7 @@ static int
calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
unsigned key_len)
{
- unsigned md_bs,
- md_rlen;
+ unsigned md_rlen;
uint8 buf[PGP_MAX_DIGEST];
uint8 *dst;
unsigned preload = 0;
@@ -143,7 +138,6 @@ calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
cval = s2k->iter;
count = ((unsigned) 16 + (cval & 15)) << ((cval >> 4) + 6);
- md_bs = px_md_block_size(md);
md_rlen = px_md_result_size(md);
remain = s2k->key_len;
diff --git a/contrib/pgcrypto/pgp.c b/contrib/pgcrypto/pgp.c
index ce6f199a9e..b8a6bc49b4 100644
--- a/contrib/pgcrypto/pgp.c
+++ b/contrib/pgcrypto/pgp.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp.c,v 1.4 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/pgp.h b/contrib/pgcrypto/pgp.h
index 7860d830c4..7ae01ccc4d 100644
--- a/contrib/pgcrypto/pgp.h
+++ b/contrib/pgcrypto/pgp.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp.h,v 1.6 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/pgp.h
*/
enum PGP_S2K_TYPE
diff --git a/contrib/pgcrypto/px-crypt.c b/contrib/pgcrypto/px-crypt.c
index e21acb73c6..ab12e2a6e7 100644
--- a/contrib/pgcrypto/px-crypt.c
+++ b/contrib/pgcrypto/px-crypt.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.c,v 1.15 2005/10/15 02:49:06 momjian Exp $
+ * contrib/pgcrypto/px-crypt.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/px-crypt.h b/contrib/pgcrypto/px-crypt.h
index c2460cb9f9..7dde9ab77b 100644
--- a/contrib/pgcrypto/px-crypt.h
+++ b/contrib/pgcrypto/px-crypt.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.h,v 1.10 2006/07/13 04:15:25 neilc Exp $
+ * contrib/pgcrypto/px-crypt.h
*/
#ifndef _PX_CRYPT_H
diff --git a/contrib/pgcrypto/px-hmac.c b/contrib/pgcrypto/px-hmac.c
index 3b2016190e..36efabd4a3 100644
--- a/contrib/pgcrypto/px-hmac.c
+++ b/contrib/pgcrypto/px-hmac.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/px-hmac.c,v 1.8 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/px-hmac.c
*/
#include "postgres.h"
@@ -52,13 +52,11 @@ static void
hmac_init(PX_HMAC *h, const uint8 *key, unsigned klen)
{
unsigned bs,
- hlen,
i;
uint8 *keybuf;
PX_MD *md = h->md;
bs = px_md_block_size(md);
- hlen = px_md_result_size(md);
keybuf = px_alloc(bs);
memset(keybuf, 0, bs);
diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c
index f2db06a898..e3f5e26221 100644
--- a/contrib/pgcrypto/px.c
+++ b/contrib/pgcrypto/px.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/px.c,v 1.18 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/px.c
*/
#include "postgres.h"
@@ -162,14 +162,12 @@ combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
const uint8 *iv, unsigned ivlen)
{
int err;
- unsigned bs,
- ks,
+ unsigned ks,
ivs;
PX_Cipher *c = cx->cipher;
uint8 *ivbuf = NULL;
uint8 *keybuf;
- bs = px_cipher_block_size(c);
ks = px_cipher_key_size(c);
ivs = px_cipher_iv_size(c);
@@ -205,7 +203,6 @@ combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
int err = 0;
uint8 *bbuf;
unsigned bs,
- maxlen,
bpos,
i,
pad;
@@ -213,7 +210,6 @@ combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
PX_Cipher *c = cx->cipher;
bbuf = NULL;
- maxlen = *rlen;
bs = px_cipher_block_size(c);
/* encrypt */
diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h
index c916e9361c..9709f9bdb6 100644
--- a/contrib/pgcrypto/px.h
+++ b/contrib/pgcrypto/px.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/px.h,v 1.19 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/px.h
*/
#ifndef __PX_H
diff --git a/contrib/pgcrypto/random.c b/contrib/pgcrypto/random.c
index b22e029d2c..393a0be983 100644
--- a/contrib/pgcrypto/random.c
+++ b/contrib/pgcrypto/random.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/random.c,v 1.17 2006/06/08 03:29:30 momjian Exp $
+ * contrib/pgcrypto/random.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/rijndael.c b/contrib/pgcrypto/rijndael.c
index cf9eca91dc..5651d03750 100644
--- a/contrib/pgcrypto/rijndael.c
+++ b/contrib/pgcrypto/rijndael.c
@@ -1,6 +1,6 @@
/* $OpenBSD: rijndael.c,v 1.6 2000/12/09 18:51:34 markus Exp $ */
-/* $PostgreSQL: pgsql/contrib/pgcrypto/rijndael.c,v 1.14 2009/06/11 14:48:52 momjian Exp $ */
+/* contrib/pgcrypto/rijndael.c */
/* This is an independent implementation of the encryption algorithm: */
/* */
diff --git a/contrib/pgcrypto/rijndael.h b/contrib/pgcrypto/rijndael.h
index e4c4229170..fb30e46c14 100644
--- a/contrib/pgcrypto/rijndael.h
+++ b/contrib/pgcrypto/rijndael.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pgcrypto/rijndael.h,v 1.7 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgcrypto/rijndael.h
*
* $OpenBSD: rijndael.h,v 1.3 2001/05/09 23:01:32 markus Exp $ */
diff --git a/contrib/pgcrypto/rijndael.tbl b/contrib/pgcrypto/rijndael.tbl
index bc0a3822cc..c7610c0134 100644
--- a/contrib/pgcrypto/rijndael.tbl
+++ b/contrib/pgcrypto/rijndael.tbl
@@ -1133,7 +1133,6 @@ static const u4byte il_tab[4][256] = {
};
static const u4byte rco_tab[10] = {
- 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
0x00000020, 0x00000040, 0x00000080, 0x0000001b, 0x00000036
};
-
diff --git a/contrib/pgcrypto/sha1.c b/contrib/pgcrypto/sha1.c
index 94849a78c5..4ee4f24559 100644
--- a/contrib/pgcrypto/sha1.c
+++ b/contrib/pgcrypto/sha1.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/sha1.c,v 1.18 2010/04/02 15:21:20 mha Exp $
+ * contrib/pgcrypto/sha1.c
*/
/*
* FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
diff --git a/contrib/pgcrypto/sha1.h b/contrib/pgcrypto/sha1.h
index ccd925b75e..3e0931efbc 100644
--- a/contrib/pgcrypto/sha1.h
+++ b/contrib/pgcrypto/sha1.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/pgcrypto/sha1.h,v 1.10 2010/04/02 15:21:20 mha Exp $ */
+/* contrib/pgcrypto/sha1.h */
/* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */
/*
diff --git a/contrib/pgcrypto/sha2.c b/contrib/pgcrypto/sha2.c
index d65995456c..5de94b2fcd 100644
--- a/contrib/pgcrypto/sha2.c
+++ b/contrib/pgcrypto/sha2.c
@@ -33,7 +33,7 @@
*
* $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
*
- * $PostgreSQL: pgsql/contrib/pgcrypto/sha2.c,v 1.13 2010/07/06 19:18:55 momjian Exp $
+ * contrib/pgcrypto/sha2.c
*/
#include "postgres.h"
diff --git a/contrib/pgcrypto/sha2.h b/contrib/pgcrypto/sha2.h
index 8d593c60e5..df77a7a659 100644
--- a/contrib/pgcrypto/sha2.h
+++ b/contrib/pgcrypto/sha2.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.h,v 1.5 2009/06/11 14:48:52 momjian Exp $ */
+/* contrib/pgcrypto/sha2.h */
/* $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $ */
/*
diff --git a/contrib/pgcrypto/sql/3des.sql b/contrib/pgcrypto/sql/3des.sql
index 274d7d81f6..ef54592060 100644
--- a/contrib/pgcrypto/sql/3des.sql
+++ b/contrib/pgcrypto/sql/3des.sql
@@ -29,4 +29,3 @@ select decrypt_iv(decode('50735067b073bb93', 'hex'), '0123456', 'abcd', '3des');
-- long message
select encode(encrypt('Lets try a longer message.', '0123456789012345678901', '3des'), 'hex');
select decrypt(encrypt('Lets try a longer message.', '0123456789012345678901', '3des'), '0123456789012345678901', '3des');
-
diff --git a/contrib/pgcrypto/sql/blowfish.sql b/contrib/pgcrypto/sql/blowfish.sql
index 1a8536d686..ba8df41c68 100644
--- a/contrib/pgcrypto/sql/blowfish.sql
+++ b/contrib/pgcrypto/sql/blowfish.sql
@@ -66,7 +66,7 @@ decode('6b77b4d63006dee605b156e27403979358deb9e7154616d959f1652bd5ff92cc', 'hex'
decode('37363534333231204e6f77206973207468652074696d6520666f722000', 'hex'),
'bf-cbc'), 'hex');
--- blowfish-448
+-- blowfish-448
SELECT encode(encrypt(
decode('fedcba9876543210', 'hex'),
decode('f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455667704689104c2fd3b2f584023641aba61761f1f1f1f0e0e0e0effffffffffffffff', 'hex'),
@@ -74,11 +74,11 @@ decode('f0e1d2c3b4a5968778695a4b3c2d1e0f001122334455667704689104c2fd3b2f58402364
-- result: c04504012e4e1f53
-- empty data
-select encode( encrypt('', 'foo', 'bf'), 'hex');
+select encode(encrypt('', 'foo', 'bf'), 'hex');
-- 10 bytes key
-select encode( encrypt('foo', '0123456789', 'bf'), 'hex');
+select encode(encrypt('foo', '0123456789', 'bf'), 'hex');
-- 22 bytes key
-select encode( encrypt('foo', '0123456789012345678901', 'bf'), 'hex');
+select encode(encrypt('foo', '0123456789012345678901', 'bf'), 'hex');
-- decrypt
select decrypt(encrypt('foo', '0123456', 'bf'), '0123456', 'bf');
@@ -90,4 +90,3 @@ select decrypt_iv(decode('95c7e89322525d59', 'hex'), '0123456', 'abcd', 'bf');
-- long message
select encode(encrypt('Lets try a longer message.', '0123456789', 'bf'), 'hex');
select decrypt(encrypt('Lets try a longer message.', '0123456789', 'bf'), '0123456789', 'bf');
-
diff --git a/contrib/pgcrypto/sql/cast5.sql b/contrib/pgcrypto/sql/cast5.sql
index 599ee060fa..527a76a160 100644
--- a/contrib/pgcrypto/sql/cast5.sql
+++ b/contrib/pgcrypto/sql/cast5.sql
@@ -45,4 +45,3 @@ select decrypt_iv(decode('384a970695ce016a', 'hex'),
-- long message
select encode(encrypt('Lets try a longer message.', '0123456789', 'cast5'), 'hex');
select decrypt(encrypt('Lets try a longer message.', '0123456789', 'cast5'), '0123456789', 'cast5');
-
diff --git a/contrib/pgcrypto/sql/crypt-blowfish.sql b/contrib/pgcrypto/sql/crypt-blowfish.sql
index effc186620..60c1140055 100644
--- a/contrib/pgcrypto/sql/crypt-blowfish.sql
+++ b/contrib/pgcrypto/sql/crypt-blowfish.sql
@@ -11,8 +11,7 @@ INSERT INTO ctest VALUES ('password', '', '');
UPDATE ctest SET salt = gen_salt('bf', 8);
UPDATE ctest SET res = crypt(data, salt);
-SELECT res = crypt(data, res) AS "worked"
+SELECT res = crypt(data, res) AS "worked"
FROM ctest;
DROP TABLE ctest;
-
diff --git a/contrib/pgcrypto/sql/crypt-des.sql b/contrib/pgcrypto/sql/crypt-des.sql
index b13d2f9de7..fabdc652fc 100644
--- a/contrib/pgcrypto/sql/crypt-des.sql
+++ b/contrib/pgcrypto/sql/crypt-des.sql
@@ -15,4 +15,3 @@ SELECT res = crypt(data, res) AS "worked"
FROM ctest;
DROP TABLE ctest;
-
diff --git a/contrib/pgcrypto/sql/crypt-md5.sql b/contrib/pgcrypto/sql/crypt-md5.sql
index 0002f0d34d..ba7befb228 100644
--- a/contrib/pgcrypto/sql/crypt-md5.sql
+++ b/contrib/pgcrypto/sql/crypt-md5.sql
@@ -15,4 +15,3 @@ SELECT res = crypt(data, res) AS "worked"
FROM ctest;
DROP TABLE ctest;
-
diff --git a/contrib/pgcrypto/sql/crypt-xdes.sql b/contrib/pgcrypto/sql/crypt-xdes.sql
index 51271dba6d..d4a74f76bd 100644
--- a/contrib/pgcrypto/sql/crypt-xdes.sql
+++ b/contrib/pgcrypto/sql/crypt-xdes.sql
@@ -15,4 +15,3 @@ SELECT res = crypt(data, res) AS "worked"
FROM ctest;
DROP TABLE ctest;
-
diff --git a/contrib/pgcrypto/sql/des.sql b/contrib/pgcrypto/sql/des.sql
index 0b3d339251..6abc5b5ffe 100644
--- a/contrib/pgcrypto/sql/des.sql
+++ b/contrib/pgcrypto/sql/des.sql
@@ -27,4 +27,3 @@ select decrypt_iv(decode('50735067b073bb93', 'hex'), '0123456', 'abcd', 'des');
-- long message
select encode(encrypt('Lets try a longer message.', '01234567', 'des'), 'hex');
select decrypt(encrypt('Lets try a longer message.', '01234567', 'des'), '01234567', 'des');
-
diff --git a/contrib/pgcrypto/sql/hmac-md5.sql b/contrib/pgcrypto/sql/hmac-md5.sql
index 70bef7cd50..71dcd089e6 100644
--- a/contrib/pgcrypto/sql/hmac-md5.sql
+++ b/contrib/pgcrypto/sql/hmac-md5.sql
@@ -42,5 +42,3 @@ SELECT encode(hmac(
'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data',
decode('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'hex'),
'md5'), 'hex');
-
-
diff --git a/contrib/pgcrypto/sql/hmac-sha1.sql b/contrib/pgcrypto/sql/hmac-sha1.sql
index 4adf6ed086..6f741934bf 100644
--- a/contrib/pgcrypto/sql/hmac-sha1.sql
+++ b/contrib/pgcrypto/sql/hmac-sha1.sql
@@ -42,5 +42,3 @@ SELECT encode(hmac(
'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data',
decode('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'hex'),
'sha1'), 'hex');
-
-
diff --git a/contrib/pgcrypto/sql/init.sql b/contrib/pgcrypto/sql/init.sql
index ee1c231bdc..5c3d100576 100644
--- a/contrib/pgcrypto/sql/init.sql
+++ b/contrib/pgcrypto/sql/init.sql
@@ -2,15 +2,7 @@
-- init pgcrypto
--
---
--- first, define the functions. Turn off echoing so that expected file
--- does not depend on contents of pgcrypto.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i pgcrypto.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION pgcrypto;
-- ensure consistent test output regardless of the default bytea format
SET bytea_output TO escape;
@@ -24,4 +16,3 @@ select gen_salt('foo');
select digest('foo', 'foo');
select hmac('foo', 'foo', 'foo');
select encrypt('foo', 'foo', 'foo');
-
diff --git a/contrib/pgcrypto/sql/md5.sql b/contrib/pgcrypto/sql/md5.sql
index d6e502779a..4df910fafb 100644
--- a/contrib/pgcrypto/sql/md5.sql
+++ b/contrib/pgcrypto/sql/md5.sql
@@ -9,4 +9,3 @@ SELECT encode(digest('message digest', 'md5'), 'hex');
SELECT encode(digest('abcdefghijklmnopqrstuvwxyz', 'md5'), 'hex');
SELECT encode(digest('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', 'md5'), 'hex');
SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'md5'), 'hex');
-
diff --git a/contrib/pgcrypto/sql/pgp-compression.sql b/contrib/pgcrypto/sql/pgp-compression.sql
index f71c176da5..ca9ee1fc00 100644
--- a/contrib/pgcrypto/sql/pgp-compression.sql
+++ b/contrib/pgcrypto/sql/pgp-compression.sql
@@ -28,4 +28,3 @@ select pgp_sym_decrypt(
pgp_sym_encrypt('Secret message', 'key',
'compress-algo=2, compress-level=0'),
'key', 'expect-compress-algo=0');
-
diff --git a/contrib/pgcrypto/sql/pgp-encrypt-DISABLED.sql b/contrib/pgcrypto/sql/pgp-encrypt-DISABLED.sql
index 80fb4d123c..4122300d97 100644
--- a/contrib/pgcrypto/sql/pgp-encrypt-DISABLED.sql
+++ b/contrib/pgcrypto/sql/pgp-encrypt-DISABLED.sql
@@ -1,3 +1 @@
-
-- no random source
-
diff --git a/contrib/pgcrypto/sql/pgp-encrypt.sql b/contrib/pgcrypto/sql/pgp-encrypt.sql
index 218bd419e5..cac37c8442 100644
--- a/contrib/pgcrypto/sql/pgp-encrypt.sql
+++ b/contrib/pgcrypto/sql/pgp-encrypt.sql
@@ -95,4 +95,3 @@ select encode(digest(pgp_sym_decrypt(
pgp_sym_encrypt(E'\r\n0\n1\r\r\n\n2\r', 'key', 'convert-crlf=1'),
'key', 'convert-crlf=1'), 'sha1'), 'hex') as result,
encode(digest(E'\r\n0\n1\r\r\n\n2\r', 'sha1'), 'hex') as expect;
-
diff --git a/contrib/pgcrypto/sql/pgp-info.sql b/contrib/pgcrypto/sql/pgp-info.sql
index c525ce307e..8e1d72a415 100644
--- a/contrib/pgcrypto/sql/pgp-info.sql
+++ b/contrib/pgcrypto/sql/pgp-info.sql
@@ -20,4 +20,3 @@ select pgp_key_id(dearmor(seckey)) from keytbl where id=6;
select pgp_key_id(dearmor(data)) as data_key_id
from encdata order by id;
-
diff --git a/contrib/pgcrypto/sql/pgp-pubkey-DISABLED.sql b/contrib/pgcrypto/sql/pgp-pubkey-DISABLED.sql
index b4aec5daf6..d35c0971ba 100644
--- a/contrib/pgcrypto/sql/pgp-pubkey-DISABLED.sql
+++ b/contrib/pgcrypto/sql/pgp-pubkey-DISABLED.sql
@@ -1,3 +1 @@
-
-- no bignum support
-
diff --git a/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql b/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
index a7cb880625..cc82420084 100644
--- a/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
+++ b/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
@@ -546,4 +546,3 @@ from keytbl, encdata where keytbl.id=5 and encdata.id=1;
-- password-protected secret key, right password
select pgp_pub_decrypt(dearmor(data), dearmor(seckey), 'parool')
from keytbl, encdata where keytbl.id=5 and encdata.id=1;
-
diff --git a/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql b/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
index 2c4e622e5c..879b47f871 100644
--- a/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
+++ b/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
@@ -48,5 +48,3 @@ select pgp_pub_decrypt(
pgp_pub_encrypt_bytea('Secret msg', dearmor(pubkey)),
dearmor(seckey))
from keytbl where keytbl.id=1;
-
-
diff --git a/contrib/pgcrypto/sql/pgp-zlib-DISABLED.sql b/contrib/pgcrypto/sql/pgp-zlib-DISABLED.sql
index 85c24683be..6f4eccd457 100644
--- a/contrib/pgcrypto/sql/pgp-zlib-DISABLED.sql
+++ b/contrib/pgcrypto/sql/pgp-zlib-DISABLED.sql
@@ -1,3 +1 @@
-
-- zlib is disabled
-
diff --git a/contrib/pgcrypto/sql/rijndael.sql b/contrib/pgcrypto/sql/rijndael.sql
index 428ad1332c..bfbf95d39b 100644
--- a/contrib/pgcrypto/sql/rijndael.sql
+++ b/contrib/pgcrypto/sql/rijndael.sql
@@ -44,11 +44,11 @@ decode('000102030405060708090a0b0c0d0e0f101112131415161718191a1b', 'hex'),
'aes-cbc'), 'hex');
-- empty data
-select encode( encrypt('', 'foo', 'aes'), 'hex');
+select encode(encrypt('', 'foo', 'aes'), 'hex');
-- 10 bytes key
-select encode( encrypt('foo', '0123456789', 'aes'), 'hex');
+select encode(encrypt('foo', '0123456789', 'aes'), 'hex');
-- 22 bytes key
-select encode( encrypt('foo', '0123456789012345678901', 'aes'), 'hex');
+select encode(encrypt('foo', '0123456789012345678901', 'aes'), 'hex');
-- decrypt
select decrypt(encrypt('foo', '0123456', 'aes'), '0123456', 'aes');
@@ -56,9 +56,8 @@ select decrypt(encrypt('foo', '0123456', 'aes'), '0123456', 'aes');
-- iv
select encode(encrypt_iv('foo', '0123456', 'abcd', 'aes'), 'hex');
select decrypt_iv(decode('2c24cb7da91d6d5699801268b0f5adad', 'hex'),
- '0123456', 'abcd', 'aes');
+ '0123456', 'abcd', 'aes');
-- long message
select encode(encrypt('Lets try a longer message.', '0123456789', 'aes'), 'hex');
select decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes'), '0123456789', 'aes');
-
diff --git a/contrib/pgcrypto/sql/sha1.sql b/contrib/pgcrypto/sql/sha1.sql
index 6a398b411e..32b1f0698f 100644
--- a/contrib/pgcrypto/sql/sha1.sql
+++ b/contrib/pgcrypto/sql/sha1.sql
@@ -9,4 +9,3 @@ SELECT encode(digest('message digest', 'sha1'), 'hex');
SELECT encode(digest('abcdefghijklmnopqrstuvwxyz', 'sha1'), 'hex');
SELECT encode(digest('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', 'sha1'), 'hex');
SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha1'), 'hex');
-
diff --git a/contrib/pgcrypto/sql/sha2.sql b/contrib/pgcrypto/sql/sha2.sql
index 447ae90765..3fe63d3e87 100644
--- a/contrib/pgcrypto/sql/sha2.sql
+++ b/contrib/pgcrypto/sql/sha2.sql
@@ -31,5 +31,3 @@ SELECT encode(digest('abc', 'sha512'), 'hex');
SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha512'), 'hex');
SELECT encode(digest('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', 'sha512'), 'hex');
SELECT encode(digest('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz', 'sha512'), 'hex');
-
-
diff --git a/contrib/pgcrypto/uninstall_pgcrypto.sql b/contrib/pgcrypto/uninstall_pgcrypto.sql
deleted file mode 100644
index a2891f6882..0000000000
--- a/contrib/pgcrypto/uninstall_pgcrypto.sql
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pgcrypto/uninstall_pgcrypto.sql,v 1.4 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION digest(text, text);
-DROP FUNCTION digest(bytea, text);
-
-DROP FUNCTION hmac(text, text, text);
-DROP FUNCTION hmac(bytea, bytea, text);
-
-DROP FUNCTION crypt(text, text);
-DROP FUNCTION gen_salt(text);
-DROP FUNCTION gen_salt(text, int4);
-
-DROP FUNCTION encrypt(bytea, bytea, text);
-DROP FUNCTION decrypt(bytea, bytea, text);
-DROP FUNCTION encrypt_iv(bytea, bytea, bytea, text);
-DROP FUNCTION decrypt_iv(bytea, bytea, bytea, text);
-
-DROP FUNCTION gen_random_bytes(int4);
-
-DROP FUNCTION pgp_sym_encrypt(text, text);
-DROP FUNCTION pgp_sym_encrypt_bytea(bytea, text);
-DROP FUNCTION pgp_sym_encrypt(text, text, text);
-DROP FUNCTION pgp_sym_encrypt_bytea(bytea, text, text);
-DROP FUNCTION pgp_sym_decrypt(bytea, text);
-DROP FUNCTION pgp_sym_decrypt_bytea(bytea, text);
-DROP FUNCTION pgp_sym_decrypt(bytea, text, text);
-DROP FUNCTION pgp_sym_decrypt_bytea(bytea, text, text);
-
-DROP FUNCTION pgp_pub_encrypt(text, bytea);
-DROP FUNCTION pgp_pub_encrypt_bytea(bytea, bytea);
-DROP FUNCTION pgp_pub_encrypt(text, bytea, text);
-DROP FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text);
-DROP FUNCTION pgp_pub_decrypt(bytea, bytea);
-DROP FUNCTION pgp_pub_decrypt_bytea(bytea, bytea);
-DROP FUNCTION pgp_pub_decrypt(bytea, bytea, text);
-DROP FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text);
-DROP FUNCTION pgp_pub_decrypt(bytea, bytea, text, text);
-DROP FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text);
-
-DROP FUNCTION pgp_key_id(bytea);
-DROP FUNCTION armor(bytea);
-DROP FUNCTION dearmor(text);
-
diff --git a/contrib/pgrowlocks/Makefile b/contrib/pgrowlocks/Makefile
index dca7f22d26..f56389b0e2 100644
--- a/contrib/pgrowlocks/Makefile
+++ b/contrib/pgrowlocks/Makefile
@@ -1,15 +1,10 @@
-#-------------------------------------------------------------------------
-#
-# pgrowlocks Makefile
-#
-# $PostgreSQL: pgsql/contrib/pgrowlocks/Makefile,v 1.6 2009/04/28 17:07:50 momjian Exp $
-#
-#-------------------------------------------------------------------------
+# contrib/pgrowlocks/Makefile
MODULE_big = pgrowlocks
OBJS = pgrowlocks.o
-DATA_built = pgrowlocks.sql
-DATA = uninstall_pgrowlocks.sql
+
+EXTENSION = pgrowlocks
+DATA = pgrowlocks--1.0.sql pgrowlocks--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/pgrowlocks/pgrowlocks.sql.in b/contrib/pgrowlocks/pgrowlocks--1.0.sql
index 405d1cb0d0..0b60fdcd07 100644
--- a/contrib/pgrowlocks/pgrowlocks.sql.in
+++ b/contrib/pgrowlocks/pgrowlocks--1.0.sql
@@ -1,9 +1,6 @@
-/* $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.sql.in,v 1.3 2007/11/13 04:24:28 momjian Exp $ */
+/* contrib/pgrowlocks/pgrowlocks--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION pgrowlocks(IN relname text,
+CREATE FUNCTION pgrowlocks(IN relname text,
OUT locked_row TID, -- row TID
OUT lock_type TEXT, -- lock type
OUT locker XID, -- locking XID
diff --git a/contrib/pgrowlocks/pgrowlocks--unpackaged--1.0.sql b/contrib/pgrowlocks/pgrowlocks--unpackaged--1.0.sql
new file mode 100644
index 0000000000..2d9d1eed41
--- /dev/null
+++ b/contrib/pgrowlocks/pgrowlocks--unpackaged--1.0.sql
@@ -0,0 +1,3 @@
+/* contrib/pgrowlocks/pgrowlocks--unpackaged--1.0.sql */
+
+ALTER EXTENSION pgrowlocks ADD function pgrowlocks(text);
diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c
index e0d21a8926..302bb5c39c 100644
--- a/contrib/pgrowlocks/pgrowlocks.c
+++ b/contrib/pgrowlocks/pgrowlocks.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.c,v 1.12 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgrowlocks/pgrowlocks.c
*
* Copyright (c) 2005-2006 Tatsuo Ishii
*
diff --git a/contrib/pgrowlocks/pgrowlocks.control b/contrib/pgrowlocks/pgrowlocks.control
new file mode 100644
index 0000000000..a6ba164515
--- /dev/null
+++ b/contrib/pgrowlocks/pgrowlocks.control
@@ -0,0 +1,5 @@
+# pgrowlocks extension
+comment = 'show row-level locking information'
+default_version = '1.0'
+module_pathname = '$libdir/pgrowlocks'
+relocatable = true
diff --git a/contrib/pgrowlocks/uninstall_pgrowlocks.sql b/contrib/pgrowlocks/uninstall_pgrowlocks.sql
deleted file mode 100644
index 6bfae44f33..0000000000
--- a/contrib/pgrowlocks/uninstall_pgrowlocks.sql
+++ /dev/null
@@ -1,6 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pgrowlocks/uninstall_pgrowlocks.sql,v 1.4 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION pgrowlocks(text);
diff --git a/contrib/pgstattuple/Makefile b/contrib/pgstattuple/Makefile
index ab960de9c4..13b87090ee 100644
--- a/contrib/pgstattuple/Makefile
+++ b/contrib/pgstattuple/Makefile
@@ -1,15 +1,10 @@
-#-------------------------------------------------------------------------
-#
-# pgstattuple Makefile
-#
-# $PostgreSQL: pgsql/contrib/pgstattuple/Makefile,v 1.10 2009/04/28 17:07:50 momjian Exp $
-#
-#-------------------------------------------------------------------------
+# contrib/pgstattuple/Makefile
MODULE_big = pgstattuple
OBJS = pgstattuple.o pgstatindex.o
-DATA_built = pgstattuple.sql
-DATA = uninstall_pgstattuple.sql
+
+EXTENSION = pgstattuple
+DATA = pgstattuple--1.0.sql pgstattuple--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index 83b50bb432..fd2cc9246b 100644
--- a/contrib/pgstattuple/pgstatindex.c
+++ b/contrib/pgstattuple/pgstatindex.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pgstattuple/pgstatindex.c,v 1.13 2009/06/11 14:48:52 momjian Exp $
+ * contrib/pgstattuple/pgstatindex.c
*
*
* pgstatindex
diff --git a/contrib/pgstattuple/pgstattuple.sql.in b/contrib/pgstattuple/pgstattuple--1.0.sql
index 0d18f19dd0..83445ec4ae 100644
--- a/contrib/pgstattuple/pgstattuple.sql.in
+++ b/contrib/pgstattuple/pgstattuple--1.0.sql
@@ -1,9 +1,6 @@
-/* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.sql.in,v 1.16 2008/03/21 03:23:30 tgl Exp $ */
+/* contrib/pgstattuple/pgstattuple--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION pgstattuple(IN relname text,
+CREATE FUNCTION pgstattuple(IN relname text,
OUT table_len BIGINT, -- physical table length in bytes
OUT tuple_count BIGINT, -- number of live tuples
OUT tuple_len BIGINT, -- total tuples length in bytes
@@ -16,7 +13,7 @@ CREATE OR REPLACE FUNCTION pgstattuple(IN relname text,
AS 'MODULE_PATHNAME', 'pgstattuple'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pgstattuple(IN reloid oid,
+CREATE FUNCTION pgstattuple(IN reloid oid,
OUT table_len BIGINT, -- physical table length in bytes
OUT tuple_count BIGINT, -- number of live tuples
OUT tuple_len BIGINT, -- total tuples length in bytes
@@ -29,7 +26,7 @@ CREATE OR REPLACE FUNCTION pgstattuple(IN reloid oid,
AS 'MODULE_PATHNAME', 'pgstattuplebyid'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pgstatindex(IN relname text,
+CREATE FUNCTION pgstatindex(IN relname text,
OUT version INT,
OUT tree_level INT,
OUT index_size BIGINT,
@@ -43,7 +40,7 @@ CREATE OR REPLACE FUNCTION pgstatindex(IN relname text,
AS 'MODULE_PATHNAME', 'pgstatindex'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pg_relpages(IN relname text)
+CREATE FUNCTION pg_relpages(IN relname text)
RETURNS BIGINT
AS 'MODULE_PATHNAME', 'pg_relpages'
LANGUAGE C STRICT;
diff --git a/contrib/pgstattuple/pgstattuple--unpackaged--1.0.sql b/contrib/pgstattuple/pgstattuple--unpackaged--1.0.sql
new file mode 100644
index 0000000000..3cfb8db534
--- /dev/null
+++ b/contrib/pgstattuple/pgstattuple--unpackaged--1.0.sql
@@ -0,0 +1,6 @@
+/* contrib/pgstattuple/pgstattuple--unpackaged--1.0.sql */
+
+ALTER EXTENSION pgstattuple ADD function pgstattuple(text);
+ALTER EXTENSION pgstattuple ADD function pgstattuple(oid);
+ALTER EXTENSION pgstattuple ADD function pgstatindex(text);
+ALTER EXTENSION pgstattuple ADD function pg_relpages(text);
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 994773a9d7..e5ddd87091 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.39 2010/04/02 16:16:51 tgl Exp $
+ * contrib/pgstattuple/pgstattuple.c
*
* Copyright (c) 2001,2002 Tatsuo Ishii
*
@@ -242,6 +242,9 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
case RELKIND_COMPOSITE_TYPE:
err = "composite type";
break;
+ case RELKIND_FOREIGN_TABLE:
+ err = "foreign table";
+ break;
default:
err = "unknown";
break;
diff --git a/contrib/pgstattuple/pgstattuple.control b/contrib/pgstattuple/pgstattuple.control
new file mode 100644
index 0000000000..7b5129b2f2
--- /dev/null
+++ b/contrib/pgstattuple/pgstattuple.control
@@ -0,0 +1,5 @@
+# pgstattuple extension
+comment = 'show tuple-level statistics'
+default_version = '1.0'
+module_pathname = '$libdir/pgstattuple'
+relocatable = true
diff --git a/contrib/pgstattuple/uninstall_pgstattuple.sql b/contrib/pgstattuple/uninstall_pgstattuple.sql
deleted file mode 100644
index ae0ae90295..0000000000
--- a/contrib/pgstattuple/uninstall_pgstattuple.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/pgstattuple/uninstall_pgstattuple.sql,v 1.6 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION pgstattuple(text);
-DROP FUNCTION pgstattuple(oid);
-DROP FUNCTION pgstatindex(text);
-DROP FUNCTION pg_relpages(text);
diff --git a/contrib/seg/.cvsignore b/contrib/seg/.cvsignore
deleted file mode 100644
index aa740d3474..0000000000
--- a/contrib/seg/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-segparse.c
-segscan.c
diff --git a/contrib/seg/.gitignore b/contrib/seg/.gitignore
new file mode 100644
index 0000000000..69e73d2096
--- /dev/null
+++ b/contrib/seg/.gitignore
@@ -0,0 +1,6 @@
+/segparse.c
+/segscan.c
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/seg/Makefile b/contrib/seg/Makefile
index c6a5ef4efe..d84934c67f 100644
--- a/contrib/seg/Makefile
+++ b/contrib/seg/Makefile
@@ -1,9 +1,11 @@
-# $PostgreSQL: pgsql/contrib/seg/Makefile,v 1.22 2009/08/28 20:26:18 petere Exp $
+# contrib/seg/Makefile
MODULE_big = seg
OBJS = seg.o segparse.o
-DATA_built = seg.sql
-DATA = uninstall_seg.sql
+
+EXTENSION = seg
+DATA = seg--1.0.sql seg--unpackaged--1.0.sql
+
REGRESS = seg
EXTRA_CLEAN = y.tab.c y.tab.h
diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out
index bd099a222c..1f82a4abb8 100644
--- a/contrib/seg/expected/seg.out
+++ b/contrib/seg/expected/seg.out
@@ -1,13 +1,7 @@
--
-- Test seg datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of seg.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION seg;
--
-- testing the input and output functions
--
@@ -924,7 +918,7 @@ SELECT '1'::seg <@ '-1 .. 1'::seg AS bool;
(1 row)
-- Load some example data and build the index
---
+--
CREATE TABLE test_seg (s seg);
\copy test_seg from 'data/test_seg.data'
CREATE INDEX test_seg_ix ON test_seg USING gist (s);
@@ -934,7 +928,7 @@ SELECT count(*) FROM test_seg WHERE s @> '11..11.3';
143
(1 row)
--- Test sorting
+-- Test sorting
SELECT * FROM test_seg WHERE s @> '11..11.3' GROUP BY s;
s
-----------------
diff --git a/contrib/seg/expected/seg_1.out b/contrib/seg/expected/seg_1.out
index c92cd83510..563c744b2d 100644
--- a/contrib/seg/expected/seg_1.out
+++ b/contrib/seg/expected/seg_1.out
@@ -1,13 +1,7 @@
--
-- Test seg datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of seg.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION seg;
--
-- testing the input and output functions
--
@@ -924,7 +918,7 @@ SELECT '1'::seg <@ '-1 .. 1'::seg AS bool;
(1 row)
-- Load some example data and build the index
---
+--
CREATE TABLE test_seg (s seg);
\copy test_seg from 'data/test_seg.data'
CREATE INDEX test_seg_ix ON test_seg USING gist (s);
@@ -934,7 +928,7 @@ SELECT count(*) FROM test_seg WHERE s @> '11..11.3';
143
(1 row)
--- Test sorting
+-- Test sorting
SELECT * FROM test_seg WHERE s @> '11..11.3' GROUP BY s;
s
-----------------
diff --git a/contrib/seg/seg.sql.in b/contrib/seg/seg--1.0.sql
index 5dac75374b..563411da6a 100644
--- a/contrib/seg/seg.sql.in
+++ b/contrib/seg/seg--1.0.sql
@@ -1,17 +1,13 @@
-/* $PostgreSQL: pgsql/contrib/seg/seg.sql.in,v 1.19 2009/06/11 18:30:03 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/seg/seg--1.0.sql */
-- Create the user-defined type for 1-D floating point intervals (seg)
---
-CREATE OR REPLACE FUNCTION seg_in(cstring)
+CREATE FUNCTION seg_in(cstring)
RETURNS seg
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION seg_out(seg)
+CREATE FUNCTION seg_out(seg)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -31,7 +27,7 @@ COMMENT ON TYPE seg IS
-- Left/Right methods
-CREATE OR REPLACE FUNCTION seg_over_left(seg, seg)
+CREATE FUNCTION seg_over_left(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -39,7 +35,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_over_left(seg, seg) IS
'overlaps or is left of';
-CREATE OR REPLACE FUNCTION seg_over_right(seg, seg)
+CREATE FUNCTION seg_over_right(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -47,7 +43,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_over_right(seg, seg) IS
'overlaps or is right of';
-CREATE OR REPLACE FUNCTION seg_left(seg, seg)
+CREATE FUNCTION seg_left(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -55,7 +51,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_left(seg, seg) IS
'is left of';
-CREATE OR REPLACE FUNCTION seg_right(seg, seg)
+CREATE FUNCTION seg_right(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -66,7 +62,7 @@ COMMENT ON FUNCTION seg_right(seg, seg) IS
-- Scalar comparison methods
-CREATE OR REPLACE FUNCTION seg_lt(seg, seg)
+CREATE FUNCTION seg_lt(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -74,7 +70,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_lt(seg, seg) IS
'less than';
-CREATE OR REPLACE FUNCTION seg_le(seg, seg)
+CREATE FUNCTION seg_le(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -82,7 +78,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_le(seg, seg) IS
'less than or equal';
-CREATE OR REPLACE FUNCTION seg_gt(seg, seg)
+CREATE FUNCTION seg_gt(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -90,7 +86,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_gt(seg, seg) IS
'greater than';
-CREATE OR REPLACE FUNCTION seg_ge(seg, seg)
+CREATE FUNCTION seg_ge(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -98,7 +94,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_ge(seg, seg) IS
'greater than or equal';
-CREATE OR REPLACE FUNCTION seg_contains(seg, seg)
+CREATE FUNCTION seg_contains(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -106,7 +102,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_contains(seg, seg) IS
'contains';
-CREATE OR REPLACE FUNCTION seg_contained(seg, seg)
+CREATE FUNCTION seg_contained(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -114,7 +110,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_contained(seg, seg) IS
'contained in';
-CREATE OR REPLACE FUNCTION seg_overlap(seg, seg)
+CREATE FUNCTION seg_overlap(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -122,7 +118,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_overlap(seg, seg) IS
'overlaps';
-CREATE OR REPLACE FUNCTION seg_same(seg, seg)
+CREATE FUNCTION seg_same(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -130,7 +126,7 @@ LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_same(seg, seg) IS
'same as';
-CREATE OR REPLACE FUNCTION seg_different(seg, seg)
+CREATE FUNCTION seg_different(seg, seg)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -140,41 +136,41 @@ COMMENT ON FUNCTION seg_different(seg, seg) IS
-- support routines for indexing
-CREATE OR REPLACE FUNCTION seg_cmp(seg, seg)
+CREATE FUNCTION seg_cmp(seg, seg)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
COMMENT ON FUNCTION seg_cmp(seg, seg) IS 'btree comparison function';
-CREATE OR REPLACE FUNCTION seg_union(seg, seg)
+CREATE FUNCTION seg_union(seg, seg)
RETURNS seg
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION seg_inter(seg, seg)
+CREATE FUNCTION seg_inter(seg, seg)
RETURNS seg
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION seg_size(seg)
+CREATE FUNCTION seg_size(seg)
RETURNS float4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-- miscellaneous
-CREATE OR REPLACE FUNCTION seg_center(seg)
+CREATE FUNCTION seg_center(seg)
RETURNS float4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION seg_upper(seg)
+CREATE FUNCTION seg_upper(seg)
RETURNS float4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
-CREATE OR REPLACE FUNCTION seg_lower(seg)
+CREATE FUNCTION seg_lower(seg)
RETURNS float4
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT IMMUTABLE;
@@ -327,38 +323,38 @@ CREATE OPERATOR ~ (
-- define the GiST support methods
-CREATE OR REPLACE FUNCTION gseg_consistent(internal,seg,int,oid,internal)
+CREATE FUNCTION gseg_consistent(internal,seg,int,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gseg_compress(internal)
-RETURNS internal
+CREATE FUNCTION gseg_compress(internal)
+RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gseg_decompress(internal)
-RETURNS internal
+CREATE FUNCTION gseg_decompress(internal)
+RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gseg_penalty(internal,internal,internal)
+CREATE FUNCTION gseg_penalty(internal,internal,internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gseg_picksplit(internal, internal)
+CREATE FUNCTION gseg_picksplit(internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gseg_union(internal, internal)
-RETURNS seg
+CREATE FUNCTION gseg_union(internal, internal)
+RETURNS seg
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION gseg_same(seg, seg, internal)
-RETURNS internal
+CREATE FUNCTION gseg_same(seg, seg, internal)
+RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
@@ -375,7 +371,7 @@ CREATE OPERATOR CLASS seg_ops
FUNCTION 1 seg_cmp(seg, seg);
CREATE OPERATOR CLASS gist_seg_ops
-DEFAULT FOR TYPE seg USING gist
+DEFAULT FOR TYPE seg USING gist
AS
OPERATOR 1 << ,
OPERATOR 2 &< ,
diff --git a/contrib/seg/seg--unpackaged--1.0.sql b/contrib/seg/seg--unpackaged--1.0.sql
new file mode 100644
index 0000000000..9fefbfc9aa
--- /dev/null
+++ b/contrib/seg/seg--unpackaged--1.0.sql
@@ -0,0 +1,51 @@
+/* contrib/seg/seg--unpackaged--1.0.sql */
+
+ALTER EXTENSION seg ADD type seg;
+ALTER EXTENSION seg ADD function seg_in(cstring);
+ALTER EXTENSION seg ADD function seg_out(seg);
+ALTER EXTENSION seg ADD function seg_over_left(seg,seg);
+ALTER EXTENSION seg ADD function seg_over_right(seg,seg);
+ALTER EXTENSION seg ADD function seg_left(seg,seg);
+ALTER EXTENSION seg ADD function seg_right(seg,seg);
+ALTER EXTENSION seg ADD function seg_lt(seg,seg);
+ALTER EXTENSION seg ADD function seg_le(seg,seg);
+ALTER EXTENSION seg ADD function seg_gt(seg,seg);
+ALTER EXTENSION seg ADD function seg_ge(seg,seg);
+ALTER EXTENSION seg ADD function seg_contains(seg,seg);
+ALTER EXTENSION seg ADD function seg_contained(seg,seg);
+ALTER EXTENSION seg ADD function seg_overlap(seg,seg);
+ALTER EXTENSION seg ADD function seg_same(seg,seg);
+ALTER EXTENSION seg ADD function seg_different(seg,seg);
+ALTER EXTENSION seg ADD function seg_cmp(seg,seg);
+ALTER EXTENSION seg ADD function seg_union(seg,seg);
+ALTER EXTENSION seg ADD function seg_inter(seg,seg);
+ALTER EXTENSION seg ADD function seg_size(seg);
+ALTER EXTENSION seg ADD function seg_center(seg);
+ALTER EXTENSION seg ADD function seg_upper(seg);
+ALTER EXTENSION seg ADD function seg_lower(seg);
+ALTER EXTENSION seg ADD operator >(seg,seg);
+ALTER EXTENSION seg ADD operator >=(seg,seg);
+ALTER EXTENSION seg ADD operator <(seg,seg);
+ALTER EXTENSION seg ADD operator <=(seg,seg);
+ALTER EXTENSION seg ADD operator >>(seg,seg);
+ALTER EXTENSION seg ADD operator <<(seg,seg);
+ALTER EXTENSION seg ADD operator &<(seg,seg);
+ALTER EXTENSION seg ADD operator &&(seg,seg);
+ALTER EXTENSION seg ADD operator &>(seg,seg);
+ALTER EXTENSION seg ADD operator <>(seg,seg);
+ALTER EXTENSION seg ADD operator =(seg,seg);
+ALTER EXTENSION seg ADD operator <@(seg,seg);
+ALTER EXTENSION seg ADD operator @>(seg,seg);
+ALTER EXTENSION seg ADD operator ~(seg,seg);
+ALTER EXTENSION seg ADD operator @(seg,seg);
+ALTER EXTENSION seg ADD function gseg_consistent(internal,seg,integer,oid,internal);
+ALTER EXTENSION seg ADD function gseg_compress(internal);
+ALTER EXTENSION seg ADD function gseg_decompress(internal);
+ALTER EXTENSION seg ADD function gseg_penalty(internal,internal,internal);
+ALTER EXTENSION seg ADD function gseg_picksplit(internal,internal);
+ALTER EXTENSION seg ADD function gseg_union(internal,internal);
+ALTER EXTENSION seg ADD function gseg_same(seg,seg,internal);
+ALTER EXTENSION seg ADD operator family seg_ops using btree;
+ALTER EXTENSION seg ADD operator class seg_ops using btree;
+ALTER EXTENSION seg ADD operator family gist_seg_ops using gist;
+ALTER EXTENSION seg ADD operator class gist_seg_ops using gist;
diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c
index 930a35b009..0a787ff946 100644
--- a/contrib/seg/seg.c
+++ b/contrib/seg/seg.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/seg/seg.c,v 1.25 2009/06/11 14:48:52 momjian Exp $
+ * contrib/seg/seg.c
*
******************************************************************************
This file contains routines that can be bound to a Postgres backend and
@@ -34,6 +34,16 @@ extern int seg_yydebug;
*/
/*
+ * Auxiliary data structure for picksplit method.
+ */
+typedef struct
+{
+ float center;
+ OffsetNumber index;
+ SEG *data;
+} gseg_picksplit_item;
+
+/*
** Input/Output routines
*/
PG_FUNCTION_INFO_V1(seg_in);
@@ -292,152 +302,104 @@ gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
return (result);
}
+/*
+ * Compare function for gseg_picksplit_item: sort by center.
+ */
+static int
+gseg_picksplit_item_cmp(const void *a, const void *b)
+{
+ const gseg_picksplit_item *i1 = (const gseg_picksplit_item *) a;
+ const gseg_picksplit_item *i2 = (const gseg_picksplit_item *) b;
+ if (i1->center < i2->center)
+ return -1;
+ else if (i1->center == i2->center)
+ return 0;
+ else
+ return 1;
+}
/*
-** The GiST PickSplit method for segments
-** We use Guttman's poly time split algorithm
-*/
+ * The GiST PickSplit method for segments
+ *
+ * We used to use Guttman's split algorithm here, but since the data is 1-D
+ * it's easier and more robust to just sort the segments by center-point and
+ * split at the middle.
+ */
GIST_SPLITVEC *
gseg_picksplit(GistEntryVector *entryvec,
GIST_SPLITVEC *v)
{
- OffsetNumber i,
- j;
- SEG *datum_alpha,
- *datum_beta;
+ int i;
SEG *datum_l,
- *datum_r;
- SEG *union_d,
- *union_dl,
- *union_dr;
- SEG *inter_d;
- bool firsttime;
- float size_alpha,
- size_beta,
- size_union,
- size_inter;
- float size_waste,
- waste;
- float size_l,
- size_r;
- int nbytes;
- OffsetNumber seed_1 = 1,
- seed_2 = 2;
+ *datum_r,
+ *seg;
+ gseg_picksplit_item *sort_items;
OffsetNumber *left,
*right;
OffsetNumber maxoff;
+ OffsetNumber firstright;
#ifdef GIST_DEBUG
fprintf(stderr, "picksplit\n");
#endif
- maxoff = entryvec->n - 2;
- nbytes = (maxoff + 2) * sizeof(OffsetNumber);
- v->spl_left = (OffsetNumber *) palloc(nbytes);
- v->spl_right = (OffsetNumber *) palloc(nbytes);
+ /* Valid items in entryvec->vector[] are indexed 1..maxoff */
+ maxoff = entryvec->n - 1;
- firsttime = true;
- waste = 0.0;
-
- for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
+ /*
+ * Prepare the auxiliary array and sort it.
+ */
+ sort_items = (gseg_picksplit_item *)
+ palloc(maxoff * sizeof(gseg_picksplit_item));
+ for (i = 1; i <= maxoff; i++)
{
- datum_alpha = (SEG *) DatumGetPointer(entryvec->vector[i].key);
- for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
- {
- datum_beta = (SEG *) DatumGetPointer(entryvec->vector[j].key);
-
- /* compute the wasted space by unioning these guys */
- /* size_waste = size_union - size_inter; */
- union_d = seg_union(datum_alpha, datum_beta);
- rt_seg_size(union_d, &size_union);
- inter_d = seg_inter(datum_alpha, datum_beta);
- rt_seg_size(inter_d, &size_inter);
- size_waste = size_union - size_inter;
-
- /*
- * are these a more promising split that what we've already seen?
- */
- if (size_waste > waste || firsttime)
- {
- waste = size_waste;
- seed_1 = i;
- seed_2 = j;
- firsttime = false;
- }
- }
+ seg = (SEG *) DatumGetPointer(entryvec->vector[i].key);
+ /* center calculation is done this way to avoid possible overflow */
+ sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f;
+ sort_items[i - 1].index = i;
+ sort_items[i - 1].data = seg;
}
+ qsort(sort_items, maxoff, sizeof(gseg_picksplit_item),
+ gseg_picksplit_item_cmp);
+ /* sort items below "firstright" will go into the left side */
+ firstright = maxoff / 2;
+
+ v->spl_left = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
+ v->spl_right = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
left = v->spl_left;
v->spl_nleft = 0;
right = v->spl_right;
v->spl_nright = 0;
- datum_alpha = (SEG *) DatumGetPointer(entryvec->vector[seed_1].key);
- datum_l = seg_union(datum_alpha, datum_alpha);
- rt_seg_size(datum_l, &size_l);
- datum_beta = (SEG *) DatumGetPointer(entryvec->vector[seed_2].key);
- datum_r = seg_union(datum_beta, datum_beta);
- rt_seg_size(datum_r, &size_r);
-
/*
- * Now split up the regions between the two seeds. An important property
- * of this split algorithm is that the split vector v has the indices of
- * items to be split in order in its left and right vectors. We exploit
- * this property by doing a merge in the code that actually splits the
- * page.
- *
- * For efficiency, we also place the new index tuple in this loop. This is
- * handled at the very end, when we have placed all the existing tuples
- * and i == maxoff + 1.
+ * Emit segments to the left output page, and compute its bounding box.
*/
-
- maxoff = OffsetNumberNext(maxoff);
- for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+ datum_l = (SEG *) palloc(sizeof(SEG));
+ memcpy(datum_l, sort_items[0].data, sizeof(SEG));
+ *left++ = sort_items[0].index;
+ v->spl_nleft++;
+ for (i = 1; i < firstright; i++)
{
- /*
- * If we've already decided where to place this item, just put it on
- * the right list. Otherwise, we need to figure out which page needs
- * the least enlargement in order to store the item.
- */
-
- if (i == seed_1)
- {
- *left++ = i;
- v->spl_nleft++;
- continue;
- }
- else if (i == seed_2)
- {
- *right++ = i;
- v->spl_nright++;
- continue;
- }
-
- /* okay, which page needs least enlargement? */
- datum_alpha = (SEG *) DatumGetPointer(entryvec->vector[i].key);
- union_dl = seg_union(datum_l, datum_alpha);
- union_dr = seg_union(datum_r, datum_alpha);
- rt_seg_size(union_dl, &size_alpha);
- rt_seg_size(union_dr, &size_beta);
+ datum_l = seg_union(datum_l, sort_items[i].data);
+ *left++ = sort_items[i].index;
+ v->spl_nleft++;
+ }
- /* pick which page to add it to */
- if (size_alpha - size_l < size_beta - size_r)
- {
- datum_l = union_dl;
- size_l = size_alpha;
- *left++ = i;
- v->spl_nleft++;
- }
- else
- {
- datum_r = union_dr;
- size_r = size_alpha;
- *right++ = i;
- v->spl_nright++;
- }
+ /*
+ * Likewise for the right page.
+ */
+ datum_r = (SEG *) palloc(sizeof(SEG));
+ memcpy(datum_r, sort_items[firstright].data, sizeof(SEG));
+ *right++ = sort_items[firstright].index;
+ v->spl_nright++;
+ for (i = firstright + 1; i < maxoff; i++)
+ {
+ datum_r = seg_union(datum_r, sort_items[i].data);
+ *right++ = sort_items[i].index;
+ v->spl_nright++;
}
- *left = *right = FirstOffsetNumber; /* sentinel value, see dosplit() */
v->spl_ldatum = PointerGetDatum(datum_l);
v->spl_rdatum = PointerGetDatum(datum_r);
@@ -905,7 +867,6 @@ restore(char *result, float val, int n)
'0', '0', '0', '0', '\0'
};
char *p;
- char *mant;
int exp;
int i,
dp,
@@ -931,7 +892,7 @@ restore(char *result, float val, int n)
*p = '\0';
/* get the exponent */
- mant = (char *) strtok(strdup(result), "e");
+ strtok(pstrdup(result), "e");
exp = atoi(strtok(NULL, "e"));
if (exp == 0)
diff --git a/contrib/seg/seg.control b/contrib/seg/seg.control
new file mode 100644
index 0000000000..a1286962ee
--- /dev/null
+++ b/contrib/seg/seg.control
@@ -0,0 +1,5 @@
+# seg extension
+comment = 'data type for representing line segments or floating-point intervals'
+default_version = '1.0'
+module_pathname = '$libdir/seg'
+relocatable = true
diff --git a/contrib/seg/segdata.h b/contrib/seg/segdata.h
index c92854da83..90be6e27aa 100644
--- a/contrib/seg/segdata.h
+++ b/contrib/seg/segdata.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/seg/segdata.h,v 1.6 2009/06/11 14:48:52 momjian Exp $
+ * contrib/seg/segdata.h
*/
typedef struct SEG
{
diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y
index ca351c661b..1f5f0affe8 100644
--- a/contrib/seg/segparse.y
+++ b/contrib/seg/segparse.y
@@ -1,6 +1,6 @@
%{
#define YYPARSE_PARAM result /* need this to pass a pointer (void *) to yyparse */
-
+
#include "postgres.h"
#include <math.h>
@@ -23,7 +23,7 @@
extern int seg_yylex(void);
extern int significant_digits(char *str); /* defined in seg.c */
-
+
void seg_yyerror(const char *message);
int seg_yyparse(void *result);
@@ -126,7 +126,7 @@ boundary:
$$.sigd = significant_digits($1);
$$.val = val;
}
- |
+ |
EXTENSION SEGFLOAT {
/* temp variable avoids a gcc 3.3.x bug on Sparc64 */
float val = seg_atof($2);
diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l
index 36da5fa395..c2b5ca8789 100644
--- a/contrib/seg/segscan.l
+++ b/contrib/seg/segscan.l
@@ -1,7 +1,7 @@
%{
-/*
-** A scanner for EMP-style numeric ranges
-*/
+/*
+ * A scanner for EMP-style numeric ranges
+ */
#include "postgres.h"
diff --git a/contrib/seg/sort-segments.pl b/contrib/seg/sort-segments.pl
index 1205d3b972..62cdfb1ffd 100755
--- a/contrib/seg/sort-segments.pl
+++ b/contrib/seg/sort-segments.pl
@@ -7,7 +7,7 @@ while (<>) {
push @rows, $_;
}
-foreach ( sort {
+foreach ( sort {
@ar = split("\t", $a);
$valA = pop @ar;
$valA =~ s/[~<> ]+//g;
diff --git a/contrib/seg/sql/seg.sql b/contrib/seg/sql/seg.sql
index 61ad519613..7b7f138dbf 100644
--- a/contrib/seg/sql/seg.sql
+++ b/contrib/seg/sql/seg.sql
@@ -2,15 +2,7 @@
-- Test seg datatype
--
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of seg.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i seg.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION seg;
--
-- testing the input and output functions
@@ -213,7 +205,7 @@ SELECT '-1'::seg <@ '-1 .. 1'::seg AS bool;
SELECT '1'::seg <@ '-1 .. 1'::seg AS bool;
-- Load some example data and build the index
---
+--
CREATE TABLE test_seg (s seg);
\copy test_seg from 'data/test_seg.data'
@@ -221,7 +213,7 @@ CREATE TABLE test_seg (s seg);
CREATE INDEX test_seg_ix ON test_seg USING gist (s);
SELECT count(*) FROM test_seg WHERE s @> '11..11.3';
--- Test sorting
+-- Test sorting
SELECT * FROM test_seg WHERE s @> '11..11.3' GROUP BY s;
-- Test functions
diff --git a/contrib/seg/uninstall_seg.sql b/contrib/seg/uninstall_seg.sql
deleted file mode 100644
index 785de03950..0000000000
--- a/contrib/seg/uninstall_seg.sql
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/seg/uninstall_seg.sql,v 1.8 2008/04/18 20:51:17 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP OPERATOR CLASS gist_seg_ops USING gist;
-
-DROP OPERATOR CLASS seg_ops USING btree;
-
-DROP FUNCTION gseg_same(seg, seg, internal);
-
-DROP FUNCTION gseg_union(internal, internal);
-
-DROP FUNCTION gseg_picksplit(internal, internal);
-
-DROP FUNCTION gseg_penalty(internal,internal,internal);
-
-DROP FUNCTION gseg_decompress(internal);
-
-DROP FUNCTION gseg_compress(internal);
-
-DROP FUNCTION gseg_consistent(internal,seg,int,oid,internal);
-
-DROP OPERATOR <@ (seg, seg);
-
-DROP OPERATOR @> (seg, seg);
-
-DROP OPERATOR ~ (seg, seg);
-
-DROP OPERATOR @ (seg, seg);
-
-DROP OPERATOR <> (seg, seg);
-
-DROP OPERATOR = (seg, seg);
-
-DROP OPERATOR >> (seg, seg);
-
-DROP OPERATOR &> (seg, seg);
-
-DROP OPERATOR && (seg, seg);
-
-DROP OPERATOR &< (seg, seg);
-
-DROP OPERATOR << (seg, seg);
-
-DROP OPERATOR >= (seg, seg);
-
-DROP OPERATOR > (seg, seg);
-
-DROP OPERATOR <= (seg, seg);
-
-DROP OPERATOR < (seg, seg);
-
-DROP FUNCTION seg_center(seg);
-
-DROP FUNCTION seg_lower(seg);
-
-DROP FUNCTION seg_upper(seg);
-
-DROP FUNCTION seg_size(seg);
-
-DROP FUNCTION seg_inter(seg, seg);
-
-DROP FUNCTION seg_union(seg, seg);
-
-DROP FUNCTION seg_cmp(seg, seg);
-
-DROP FUNCTION seg_different(seg, seg);
-
-DROP FUNCTION seg_same(seg, seg);
-
-DROP FUNCTION seg_overlap(seg, seg);
-
-DROP FUNCTION seg_contained(seg, seg);
-
-DROP FUNCTION seg_contains(seg, seg);
-
-DROP FUNCTION seg_ge(seg, seg);
-
-DROP FUNCTION seg_gt(seg, seg);
-
-DROP FUNCTION seg_le(seg, seg);
-
-DROP FUNCTION seg_lt(seg, seg);
-
-DROP FUNCTION seg_right(seg, seg);
-
-DROP FUNCTION seg_left(seg, seg);
-
-DROP FUNCTION seg_over_right(seg, seg);
-
-DROP FUNCTION seg_over_left(seg, seg);
-
-DROP TYPE seg CASCADE;
diff --git a/contrib/sepgsql/.gitignore b/contrib/sepgsql/.gitignore
new file mode 100644
index 0000000000..31613e011f
--- /dev/null
+++ b/contrib/sepgsql/.gitignore
@@ -0,0 +1,7 @@
+/sepgsql.sql
+/sepgsql-regtest.fc
+/sepgsql-regtest.if
+/sepgsql-regtest.pp
+/tmp
+# Generated subdirectories
+/results/
diff --git a/contrib/sepgsql/Makefile b/contrib/sepgsql/Makefile
new file mode 100644
index 0000000000..bc995dd29a
--- /dev/null
+++ b/contrib/sepgsql/Makefile
@@ -0,0 +1,22 @@
+# contrib/sepgsql/Makefile
+
+MODULE_big = sepgsql
+OBJS = hooks.o selinux.o label.o dml.o \
+ schema.o relation.o proc.o
+DATA_built = sepgsql.sql
+REGRESS = label dml misc
+EXTRA_CLEAN = -r tmp *.pp sepgsql-regtest.if sepgsql-regtest.fc
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/sepgsql
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
+
+SHLIB_LINK += $(filter -lselinux, $(LIBS))
+REGRESS_OPTS += --launcher $(top_builddir)/contrib/sepgsql/launcher
diff --git a/contrib/sepgsql/dml.c b/contrib/sepgsql/dml.c
new file mode 100644
index 0000000000..22666b708e
--- /dev/null
+++ b/contrib/sepgsql/dml.c
@@ -0,0 +1,367 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/dml.c
+ *
+ * Routines to handle DML permission checks
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/sysattr.h"
+#include "access/tupdesc.h"
+#include "catalog/catalog.h"
+#include "catalog/heap.h"
+#include "catalog/dependency.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_inherits_fn.h"
+#include "commands/seclabel.h"
+#include "commands/tablecmds.h"
+#include "executor/executor.h"
+#include "nodes/bitmapset.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+#include "sepgsql.h"
+
+/*
+ * fixup_whole_row_references
+ *
+ * When user reference a whole of row, it is equivalent to reference to
+ * all the user columns (not system columns). So, we need to fix up the
+ * given bitmapset, if it contains a whole of the row reference.
+ */
+static Bitmapset *
+fixup_whole_row_references(Oid relOid, Bitmapset *columns)
+{
+ Bitmapset *result;
+ HeapTuple tuple;
+ AttrNumber natts;
+ AttrNumber attno;
+ int index;
+
+ /* if no whole of row references, do not anything */
+ index = InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber;
+ if (!bms_is_member(index, columns))
+ return columns;
+
+ /* obtain number of attributes */
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", relOid);
+ natts = ((Form_pg_class) GETSTRUCT(tuple))->relnatts;
+ ReleaseSysCache(tuple);
+
+ /* fix up the given columns */
+ result = bms_copy(columns);
+ result = bms_del_member(result, index);
+
+ for (attno = 1; attno <= natts; attno++)
+ {
+ tuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(relOid),
+ Int16GetDatum(attno));
+ if (!HeapTupleIsValid(tuple))
+ continue;
+
+ if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
+ continue;
+
+ index = attno - FirstLowInvalidHeapAttributeNumber;
+
+ result = bms_add_member(result, index);
+
+ ReleaseSysCache(tuple);
+ }
+ return result;
+}
+
+/*
+ * fixup_inherited_columns
+ *
+ * When user is querying on a table with children, it implicitly accesses
+ * child tables also. So, we also need to check security label of child
+ * tables and columns, but here is no guarantee attribute numbers are
+ * same between the parent ans children.
+ * It returns a bitmapset which contains attribute number of the child
+ * table based on the given bitmapset of the parent.
+ */
+static Bitmapset *
+fixup_inherited_columns(Oid parentId, Oid childId, Bitmapset *columns)
+{
+ AttrNumber attno;
+ Bitmapset *tmpset;
+ Bitmapset *result = NULL;
+ char *attname;
+ int index;
+
+ /*
+ * obviously, no need to do anything here
+ */
+ if (parentId == childId)
+ return columns;
+
+ tmpset = bms_copy(columns);
+ while ((index = bms_first_member(tmpset)) > 0)
+ {
+ attno = index + FirstLowInvalidHeapAttributeNumber;
+
+ /*
+ * whole-row-reference shall be fixed-up later
+ */
+ if (attno == InvalidAttrNumber)
+ {
+ result = bms_add_member(result, index);
+ continue;
+ }
+
+ attname = get_attname(parentId, attno);
+ if (!attname)
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ attno, parentId);
+ attno = get_attnum(childId, attname);
+ if (attno == InvalidAttrNumber)
+ elog(ERROR, "cache lookup failed for attribute %s of relation %u",
+ attname, childId);
+
+ index = attno - FirstLowInvalidHeapAttributeNumber;
+ result = bms_add_member(result, index);
+
+ pfree(attname);
+ }
+ bms_free(tmpset);
+
+ return result;
+}
+
+/*
+ * check_relation_privileges
+ *
+ * It actually checks required permissions on a certain relation
+ * and its columns.
+ */
+static bool
+check_relation_privileges(Oid relOid,
+ Bitmapset *selected,
+ Bitmapset *modified,
+ uint32 required,
+ bool abort)
+{
+ char relkind = get_rel_relkind(relOid);
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *audit_name;
+ Bitmapset *columns;
+ int index;
+ bool result = true;
+
+ /*
+ * Hardwired Policies: SE-PostgreSQL enforces - clients cannot modify
+ * system catalogs using DMLs - clients cannot reference/modify toast
+ * relations using DMLs
+ */
+ if (sepgsql_getenforce() > 0)
+ {
+ Oid relnamespace = get_rel_namespace(relOid);
+
+ if (IsSystemNamespace(relnamespace) &&
+ (required & (SEPG_DB_TABLE__UPDATE |
+ SEPG_DB_TABLE__INSERT |
+ SEPG_DB_TABLE__DELETE)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("SELinux: hardwired security policy violation")));
+
+ if (relkind == RELKIND_TOASTVALUE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("SELinux: hardwired security policy violation")));
+ }
+
+ /*
+ * Check permissions on the relation
+ */
+ tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
+ audit_name = getObjectDescriptionOids(RelationRelationId, relOid);
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ result = sepgsql_check_perms(scontext,
+ tcontext,
+ SEPG_CLASS_DB_TABLE,
+ required,
+ audit_name,
+ abort);
+ break;
+
+ case RELKIND_SEQUENCE:
+ Assert((required & ~SEPG_DB_TABLE__SELECT) == 0);
+
+ if (required & SEPG_DB_TABLE__SELECT)
+ result = sepgsql_check_perms(scontext,
+ tcontext,
+ SEPG_CLASS_DB_SEQUENCE,
+ SEPG_DB_SEQUENCE__GET_VALUE,
+ audit_name,
+ abort);
+ break;
+
+ case RELKIND_VIEW:
+ result = sepgsql_check_perms(scontext,
+ tcontext,
+ SEPG_CLASS_DB_VIEW,
+ SEPG_DB_VIEW__EXPAND,
+ audit_name,
+ abort);
+ break;
+
+ default:
+ /* nothing to be checked */
+ break;
+ }
+ pfree(tcontext);
+ pfree(audit_name);
+
+ /*
+ * Only columns owned by relations shall be checked
+ */
+ if (relkind != RELKIND_RELATION)
+ return true;
+
+ /*
+ * Check permissions on the columns
+ */
+ selected = fixup_whole_row_references(relOid, selected);
+ modified = fixup_whole_row_references(relOid, modified);
+ columns = bms_union(selected, modified);
+
+ while ((index = bms_first_member(columns)) >= 0)
+ {
+ AttrNumber attnum;
+ uint32 column_perms = 0;
+ ObjectAddress object;
+
+ if (bms_is_member(index, selected))
+ column_perms |= SEPG_DB_COLUMN__SELECT;
+ if (bms_is_member(index, modified))
+ {
+ if (required & SEPG_DB_TABLE__UPDATE)
+ column_perms |= SEPG_DB_COLUMN__UPDATE;
+ if (required & SEPG_DB_TABLE__INSERT)
+ column_perms |= SEPG_DB_COLUMN__INSERT;
+ }
+ if (column_perms == 0)
+ continue;
+
+ /* obtain column's permission */
+ attnum = index + FirstLowInvalidHeapAttributeNumber;
+ tcontext = sepgsql_get_label(RelationRelationId, relOid, attnum);
+
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = attnum;
+ audit_name = getObjectDescription(&object);
+
+ result = sepgsql_check_perms(scontext,
+ tcontext,
+ SEPG_CLASS_DB_COLUMN,
+ column_perms,
+ audit_name,
+ abort);
+ pfree(tcontext);
+ pfree(audit_name);
+
+ if (!result)
+ return result;
+ }
+ return true;
+}
+
+/*
+ * sepgsql_dml_privileges
+ *
+ * Entrypoint of the DML permission checks
+ */
+bool
+sepgsql_dml_privileges(List *rangeTabls, bool abort)
+{
+ ListCell *lr;
+
+ foreach(lr, rangeTabls)
+ {
+ RangeTblEntry *rte = lfirst(lr);
+ uint32 required = 0;
+ List *tableIds;
+ ListCell *li;
+
+ /*
+ * Only regular relations shall be checked
+ */
+ if (rte->rtekind != RTE_RELATION)
+ continue;
+
+ /*
+ * Find out required permissions
+ */
+ if (rte->requiredPerms & ACL_SELECT)
+ required |= SEPG_DB_TABLE__SELECT;
+ if (rte->requiredPerms & ACL_INSERT)
+ required |= SEPG_DB_TABLE__INSERT;
+ if (rte->requiredPerms & ACL_UPDATE)
+ {
+ if (!bms_is_empty(rte->modifiedCols))
+ required |= SEPG_DB_TABLE__UPDATE;
+ else
+ required |= SEPG_DB_TABLE__LOCK;
+ }
+ if (rte->requiredPerms & ACL_DELETE)
+ required |= SEPG_DB_TABLE__DELETE;
+
+ /*
+ * Skip, if nothing to be checked
+ */
+ if (required == 0)
+ continue;
+
+ /*
+ * If this RangeTblEntry is also supposed to reference inherited
+ * tables, we need to check security label of the child tables. So, we
+ * expand rte->relid into list of OIDs of inheritance hierarchy, then
+ * checker routine will be invoked for each relations.
+ */
+ if (!rte->inh)
+ tableIds = list_make1_oid(rte->relid);
+ else
+ tableIds = find_all_inheritors(rte->relid, NoLock, NULL);
+
+ foreach(li, tableIds)
+ {
+ Oid tableOid = lfirst_oid(li);
+ Bitmapset *selectedCols;
+ Bitmapset *modifiedCols;
+
+ /*
+ * child table has different attribute numbers, so we need to fix
+ * up them.
+ */
+ selectedCols = fixup_inherited_columns(rte->relid, tableOid,
+ rte->selectedCols);
+ modifiedCols = fixup_inherited_columns(rte->relid, tableOid,
+ rte->modifiedCols);
+
+ /*
+ * check permissions on individual tables
+ */
+ if (!check_relation_privileges(tableOid,
+ selectedCols,
+ modifiedCols,
+ required, abort))
+ return false;
+ }
+ list_free(tableIds);
+ }
+ return true;
+}
diff --git a/contrib/sepgsql/expected/dml.out b/contrib/sepgsql/expected/dml.out
new file mode 100644
index 0000000000..949789f2f1
--- /dev/null
+++ b/contrib/sepgsql/expected/dml.out
@@ -0,0 +1,183 @@
+--
+-- Regression Test for DML Permissions
+--
+--
+-- Setup
+--
+CREATE TABLE t1 (a int, b text);
+SECURITY LABEL ON TABLE t1 IS 'system_u:object_r:sepgsql_table_t:s0';
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+CREATE TABLE t2 (x int, y text);
+SECURITY LABEL ON TABLE t2 IS 'system_u:object_r:sepgsql_ro_table_t:s0';
+INSERT INTO t2 VALUES (1, 'xxx'), (2, 'yyy'), (3, 'zzz');
+CREATE TABLE t3 (s int, t text);
+SECURITY LABEL ON TABLE t3 IS 'system_u:object_r:sepgsql_fixed_table_t:s0';
+INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu');
+CREATE TABLE t4 (m int, n text);
+SECURITY LABEL ON TABLE t4 IS 'system_u:object_r:sepgsql_secret_table_t:s0';
+INSERT INTO t4 VALUES (1, 'mmm'), (2, 'nnn'), (3, 'ooo');
+CREATE TABLE t5 (e text, f text, g text);
+SECURITY LABEL ON TABLE t5 IS 'system_u:object_r:sepgsql_table_t:s0';
+SECURITY LABEL ON COLUMN t5.e IS 'system_u:object_r:sepgsql_table_t:s0';
+SECURITY LABEL ON COLUMN t5.f IS 'system_u:object_r:sepgsql_ro_table_t:s0';
+SECURITY LABEL ON COLUMN t5.g IS 'system_u:object_r:sepgsql_secret_table_t:s0';
+CREATE TABLE customer (cid int primary key, cname text, ccredit text);
+NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "customer_pkey" for table "customer"
+SECURITY LABEL ON COLUMN customer.ccredit IS 'system_u:object_r:sepgsql_secret_table_t:s0';
+INSERT INTO customer VALUES (1, 'Taro', '1111-2222-3333-4444'),
+ (2, 'Hanako', '5555-6666-7777-8888');
+CREATE FUNCTION customer_credit(int) RETURNS text
+ AS 'SELECT regexp_replace(ccredit, ''-[0-9]+$'', ''-????'') FROM customer WHERE cid = $1'
+ LANGUAGE sql;
+SECURITY LABEL ON FUNCTION customer_credit(int)
+ IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
+SELECT objtype, objname, label FROM pg_seclabels
+ WHERE provider = 'selinux'
+ AND objtype in ('table', 'column')
+ AND objname in ('t1', 't2', 't3', 't4', 't5', 't5.e', 't5.f', 't5.g')
+ORDER BY objname;
+ objtype | objname | label
+---------+---------+---------------------------------------------
+ table | t1 | system_u:object_r:sepgsql_table_t:s0
+ table | t2 | system_u:object_r:sepgsql_ro_table_t:s0
+ table | t3 | system_u:object_r:sepgsql_fixed_table_t:s0
+ table | t4 | system_u:object_r:sepgsql_secret_table_t:s0
+ table | t5 | system_u:object_r:sepgsql_table_t:s0
+ column | t5.e | system_u:object_r:sepgsql_table_t:s0
+ column | t5.f | system_u:object_r:sepgsql_ro_table_t:s0
+ column | t5.g | system_u:object_r:sepgsql_secret_table_t:s0
+(8 rows)
+
+-- Hardwired Rules
+UPDATE pg_attribute SET attisdropped = true
+ WHERE attrelid = 't5'::regclass AND attname = 'f'; -- failed
+ERROR: SELinux: hardwired security policy violation
+--
+-- Simple DML statements
+--
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+-----------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+(1 row)
+
+SELECT * FROM t1; -- ok
+ a | b
+---+-----
+ 1 | aaa
+ 2 | bbb
+ 3 | ccc
+(3 rows)
+
+SELECT * FROM t2; -- ok
+ x | y
+---+-----
+ 1 | xxx
+ 2 | yyy
+ 3 | zzz
+(3 rows)
+
+SELECT * FROM t3; -- ok
+ s | t
+---+-----
+ 1 | sss
+ 2 | ttt
+ 3 | uuu
+(3 rows)
+
+SELECT * FROM t4; -- failed
+ERROR: SELinux: security policy violation
+SELECT * FROM t5; -- failed
+ERROR: SELinux: security policy violation
+SELECT e,f FROM t5; -- ok
+ e | f
+---+---
+(0 rows)
+
+SELECT * FROM customer; -- failed
+ERROR: SELinux: security policy violation
+SELECT cid, cname, customer_credit(cid) FROM customer; -- ok
+ cid | cname | customer_credit
+-----+--------+---------------------
+ 1 | Taro | 1111-2222-3333-????
+ 2 | Hanako | 5555-6666-7777-????
+(2 rows)
+
+SELECT count(*) FROM t5; -- ok
+ count
+-------
+ 0
+(1 row)
+
+SELECT count(*) FROM t5 WHERE g IS NULL; -- failed
+ERROR: SELinux: security policy violation
+INSERT INTO t1 VALUES (4, 'abc'); -- ok
+INSERT INTO t2 VALUES (4, 'xyz'); -- failed
+ERROR: SELinux: security policy violation
+INSERT INTO t3 VALUES (4, 'stu'); -- ok
+INSERT INTO t4 VALUES (4, 'mno'); -- failed
+ERROR: SELinux: security policy violation
+INSERT INTO t5 VALUES (1,2,3); -- failed
+ERROR: SELinux: security policy violation
+INSERT INTO t5 (e,f) VALUES ('abc', 'def'); -- failed
+ERROR: SELinux: security policy violation
+INSERT INTO t5 (e) VALUES ('abc'); -- ok
+UPDATE t1 SET b = b || '_upd'; -- ok
+UPDATE t2 SET y = y || '_upd'; -- failed
+ERROR: SELinux: security policy violation
+UPDATE t3 SET t = t || '_upd'; -- failed
+ERROR: SELinux: security policy violation
+UPDATE t4 SET n = n || '_upd'; -- failed
+ERROR: SELinux: security policy violation
+UPDATE t5 SET e = 'xyz'; -- ok
+UPDATE t5 SET e = f || '_upd'; -- ok
+UPDATE t5 SET e = g || '_upd'; -- failed
+ERROR: SELinux: security policy violation
+DELETE FROM t1; -- ok
+DELETE FROM t2; -- failed
+ERROR: SELinux: security policy violation
+DELETE FROM t3; -- failed
+ERROR: SELinux: security policy violation
+DELETE FROM t4; -- failed
+ERROR: SELinux: security policy violation
+DELETE FROM t5; -- ok
+DELETE FROM t5 WHERE f IS NULL; -- ok
+DELETE FROM t5 WHERE g IS NULL; -- failed
+ERROR: SELinux: security policy violation
+--
+-- COPY TO/FROM statements
+--
+COPY t1 TO '/dev/null'; -- ok
+COPY t2 TO '/dev/null'; -- ok
+COPY t3 TO '/dev/null'; -- ok
+COPY t4 TO '/dev/null'; -- failed
+ERROR: SELinux: security policy violation
+COPY t5 TO '/dev/null'; -- failed
+ERROR: SELinux: security policy violation
+COPY t5(e,f) TO '/dev/null'; -- ok
+COPY t1 FROM '/dev/null'; -- ok
+COPY t2 FROM '/dev/null'; -- failed
+ERROR: SELinux: security policy violation
+COPY t3 FROM '/dev/null'; -- ok
+COPY t4 FROM '/dev/null'; -- failed
+ERROR: SELinux: security policy violation
+COPY t5 FROM '/dev/null'; -- failed
+ERROR: SELinux: security policy violation
+COPY t5 (e,f) FROM '/dev/null'; -- failed
+ERROR: SELinux: security policy violation
+COPY t5 (e) FROM '/dev/null'; -- ok
+--
+-- Clean up
+--
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+------------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c255
+(1 row)
+
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE IF EXISTS t5 CASCADE;
+DROP TABLE IF EXISTS customer CASCADE;
diff --git a/contrib/sepgsql/expected/label.out b/contrib/sepgsql/expected/label.out
new file mode 100644
index 0000000000..bac169f37b
--- /dev/null
+++ b/contrib/sepgsql/expected/label.out
@@ -0,0 +1,117 @@
+--
+-- Regression Tests for Label Management
+--
+--
+-- Setup
+--
+CREATE TABLE t1 (a int, b text);
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+SELECT * INTO t2 FROM t1 WHERE a % 2 = 0;
+CREATE FUNCTION f1 () RETURNS text
+ AS 'SELECT sepgsql_getcon()'
+ LANGUAGE sql;
+CREATE FUNCTION f2 () RETURNS text
+ AS 'SELECT sepgsql_getcon()'
+ LANGUAGE sql;
+SECURITY LABEL ON FUNCTION f2()
+ IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
+CREATE FUNCTION f3 () RETURNS text
+ AS 'BEGIN
+ RAISE EXCEPTION ''an exception from f3()'';
+ RETURN NULL;
+ END;' LANGUAGE plpgsql;
+SECURITY LABEL ON FUNCTION f3()
+ IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
+CREATE FUNCTION f4 () RETURNS text
+ AS 'SELECT sepgsql_getcon()'
+ LANGUAGE sql;
+SECURITY LABEL ON FUNCTION f4()
+ IS 'system_u:object_r:sepgsql_regtest_trusted_proc_exec_t:s0';
+--
+-- Tests for default labeling behavior
+--
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+-----------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+(1 row)
+
+CREATE TABLE t3 (s int, t text);
+INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu');
+SELECT objtype, objname, label FROM pg_seclabels
+ WHERE provider = 'selinux'
+ AND objtype in ('table', 'column')
+ AND objname in ('t1', 't2', 't3');
+ objtype | objname | label
+---------+---------+-----------------------------------------------
+ table | t1 | unconfined_u:object_r:sepgsql_table_t:s0
+ table | t2 | unconfined_u:object_r:sepgsql_table_t:s0
+ table | t3 | unconfined_u:object_r:user_sepgsql_table_t:s0
+(3 rows)
+
+--
+-- Tests for SECURITY LABEL
+--
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+----------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_regtest_dba_t:s0
+(1 row)
+
+SECURITY LABEL ON TABLE t1
+ IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok
+SECURITY LABEL ON TABLE t2
+ IS 'invalid security context'; -- be failed
+ERROR: SELinux: invalid security label: "invalid security context"
+SECURITY LABEL ON COLUMN t2
+ IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- be failed
+ERROR: improper relation name (too many dotted names):
+SECURITY LABEL ON COLUMN t2.b
+ IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok
+--
+-- Tests for Trusted Procedures
+--
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+-----------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+(1 row)
+
+SELECT f1(); -- normal procedure
+ f1
+-----------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+(1 row)
+
+SELECT f2(); -- trusted procedure
+ f2
+-----------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_trusted_proc_t:s0
+(1 row)
+
+SELECT f3(); -- trusted procedure that raises an error
+ERROR: an exception from f3()
+SELECT f4(); -- failed on domain transition
+ERROR: SELinux: security policy violation
+SELECT sepgsql_getcon(); -- client's label must be restored
+ sepgsql_getcon
+-----------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+(1 row)
+
+--
+-- Clean up
+--
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+------------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c255
+(1 row)
+
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP FUNCTION IF EXISTS f1() CASCADE;
+DROP FUNCTION IF EXISTS f2() CASCADE;
+DROP FUNCTION IF EXISTS f3() CASCADE;
+DROP FUNCTION IF EXISTS f4() CASCADE;
diff --git a/contrib/sepgsql/expected/misc.out b/contrib/sepgsql/expected/misc.out
new file mode 100644
index 0000000000..329852c574
--- /dev/null
+++ b/contrib/sepgsql/expected/misc.out
@@ -0,0 +1,5 @@
+--
+-- Regression Test for Misc Permission Checks
+--
+LOAD '$libdir/sepgsql'; -- failed
+ERROR: SELinux: LOAD is not permitted
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
new file mode 100644
index 0000000000..7797ccb199
--- /dev/null
+++ b/contrib/sepgsql/hooks.c
@@ -0,0 +1,462 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/hooks.c
+ *
+ * Entrypoints of the hooks in PostgreSQL, and dispatches the callbacks.
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/objectaccess.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+#include "commands/seclabel.h"
+#include "executor/executor.h"
+#include "fmgr.h"
+#include "libpq/auth.h"
+#include "miscadmin.h"
+#include "tcop/utility.h"
+#include "utils/guc.h"
+
+#include "sepgsql.h"
+
+PG_MODULE_MAGIC;
+
+/*
+ * Declarations
+ */
+void _PG_init(void);
+
+/*
+ * Saved hook entries (if stacked)
+ */
+static object_access_hook_type next_object_access_hook = NULL;
+static ClientAuthentication_hook_type next_client_auth_hook = NULL;
+static ExecutorCheckPerms_hook_type next_exec_check_perms_hook = NULL;
+static needs_fmgr_hook_type next_needs_fmgr_hook = NULL;
+static fmgr_hook_type next_fmgr_hook = NULL;
+static ProcessUtility_hook_type next_ProcessUtility_hook = NULL;
+
+/*
+ * GUC: sepgsql.permissive = (on|off)
+ */
+static bool sepgsql_permissive;
+
+bool
+sepgsql_get_permissive(void)
+{
+ return sepgsql_permissive;
+}
+
+/*
+ * GUC: sepgsql.debug_audit = (on|off)
+ */
+static bool sepgsql_debug_audit;
+
+bool
+sepgsql_get_debug_audit(void)
+{
+ return sepgsql_debug_audit;
+}
+
+/*
+ * sepgsql_client_auth
+ *
+ * Entrypoint of the client authentication hook.
+ * It switches the client label according to getpeercon(), and the current
+ * performing mode according to the GUC setting.
+ */
+static void
+sepgsql_client_auth(Port *port, int status)
+{
+ char *context;
+
+ if (next_client_auth_hook)
+ (*next_client_auth_hook) (port, status);
+
+ /*
+ * In the case when authentication failed, the supplied socket shall be
+ * closed soon, so we don't need to do anything here.
+ */
+ if (status != STATUS_OK)
+ return;
+
+ /*
+ * Getting security label of the peer process using API of libselinux.
+ */
+ if (getpeercon_raw(port->sock, &context) < 0)
+ ereport(FATAL,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux: unable to get peer label: %m")));
+
+ sepgsql_set_client_label(context);
+
+ /*
+ * Switch the current performing mode from INTERNAL to either DEFAULT or
+ * PERMISSIVE.
+ */
+ if (sepgsql_permissive)
+ sepgsql_set_mode(SEPGSQL_MODE_PERMISSIVE);
+ else
+ sepgsql_set_mode(SEPGSQL_MODE_DEFAULT);
+}
+
+/*
+ * sepgsql_object_access
+ *
+ * Entrypoint of the object_access_hook. This routine performs as
+ * a dispatcher of invocation based on access type and object classes.
+ */
+static void
+sepgsql_object_access(ObjectAccessType access,
+ Oid classId,
+ Oid objectId,
+ int subId)
+{
+ if (next_object_access_hook)
+ (*next_object_access_hook) (access, classId, objectId, subId);
+
+ switch (access)
+ {
+ case OAT_POST_CREATE:
+ switch (classId)
+ {
+ case NamespaceRelationId:
+ sepgsql_schema_post_create(objectId);
+ break;
+
+ case RelationRelationId:
+ if (subId == 0)
+ sepgsql_relation_post_create(objectId);
+ else
+ sepgsql_attribute_post_create(objectId, subId);
+ break;
+
+ case ProcedureRelationId:
+ sepgsql_proc_post_create(objectId);
+ break;
+
+ default:
+ /* Ignore unsupported object classes */
+ break;
+ }
+ break;
+
+ default:
+ elog(ERROR, "unexpected object access type: %d", (int) access);
+ break;
+ }
+}
+
+/*
+ * sepgsql_exec_check_perms
+ *
+ * Entrypoint of DML permissions
+ */
+static bool
+sepgsql_exec_check_perms(List *rangeTabls, bool abort)
+{
+ /*
+ * If security provider is stacking and one of them replied 'false' at
+ * least, we don't need to check any more.
+ */
+ if (next_exec_check_perms_hook &&
+ !(*next_exec_check_perms_hook) (rangeTabls, abort))
+ return false;
+
+ if (!sepgsql_dml_privileges(rangeTabls, abort))
+ return false;
+
+ return true;
+}
+
+/*
+ * sepgsql_needs_fmgr_hook
+ *
+ * It informs the core whether the supplied function is trusted procedure,
+ * or not. If true, sepgsql_fmgr_hook shall be invoked at start, end, and
+ * abort time of function invocation.
+ */
+static bool
+sepgsql_needs_fmgr_hook(Oid functionId)
+{
+ char *old_label;
+ char *new_label;
+ char *function_label;
+
+ if (next_needs_fmgr_hook &&
+ (*next_needs_fmgr_hook) (functionId))
+ return true;
+
+ /*
+ * SELinux needs the function to be called via security_definer wrapper,
+ * if this invocation will take a domain-transition. We call these
+ * functions as trusted-procedure, if the security policy has a rule that
+ * switches security label of the client on execution.
+ */
+ old_label = sepgsql_get_client_label();
+ new_label = sepgsql_proc_get_domtrans(functionId);
+ if (strcmp(old_label, new_label) != 0)
+ {
+ pfree(new_label);
+ return true;
+ }
+ pfree(new_label);
+
+ /*
+ * Even if not a trusted-procedure, this function should not be inlined
+ * unless the client has db_procedure:{execute} permission. Please note
+ * that it shall be actually failed later because of same reason with
+ * ACL_EXECUTE.
+ */
+ function_label = sepgsql_get_label(ProcedureRelationId, functionId, 0);
+ if (sepgsql_check_perms(sepgsql_get_client_label(),
+ function_label,
+ SEPG_CLASS_DB_PROCEDURE,
+ SEPG_DB_PROCEDURE__EXECUTE,
+ NULL, false) != true)
+ {
+ pfree(function_label);
+ return true;
+ }
+ pfree(function_label);
+ return false;
+}
+
+/*
+ * sepgsql_fmgr_hook
+ *
+ * It switches security label of the client on execution of trusted
+ * procedures.
+ */
+static void
+sepgsql_fmgr_hook(FmgrHookEventType event,
+ FmgrInfo *flinfo, Datum *private)
+{
+ struct
+ {
+ char *old_label;
+ char *new_label;
+ Datum next_private;
+ } *stack;
+
+ switch (event)
+ {
+ case FHET_START:
+ stack = (void *) DatumGetPointer(*private);
+ if (!stack)
+ {
+ MemoryContext oldcxt;
+ const char *cur_label = sepgsql_get_client_label();
+
+ oldcxt = MemoryContextSwitchTo(flinfo->fn_mcxt);
+ stack = palloc(sizeof(*stack));
+ stack->old_label = NULL;
+ stack->new_label = sepgsql_proc_get_domtrans(flinfo->fn_oid);
+ stack->next_private = 0;
+
+ MemoryContextSwitchTo(oldcxt);
+
+ if (strcmp(cur_label, stack->new_label) != 0)
+ {
+ /*
+ * process:transition permission between old and new
+ * label, when user tries to switch security label of the
+ * client on execution of trusted procedure.
+ */
+ sepgsql_check_perms(cur_label, stack->new_label,
+ SEPG_CLASS_PROCESS,
+ SEPG_PROCESS__TRANSITION,
+ NULL, true);
+ }
+
+ *private = PointerGetDatum(stack);
+ }
+ Assert(!stack->old_label);
+ stack->old_label = sepgsql_set_client_label(stack->new_label);
+
+ if (next_fmgr_hook)
+ (*next_fmgr_hook) (event, flinfo, &stack->next_private);
+ break;
+
+ case FHET_END:
+ case FHET_ABORT:
+ stack = (void *) DatumGetPointer(*private);
+
+ if (next_fmgr_hook)
+ (*next_fmgr_hook) (event, flinfo, &stack->next_private);
+
+ sepgsql_set_client_label(stack->old_label);
+ stack->old_label = NULL;
+ break;
+
+ default:
+ elog(ERROR, "unexpected event type: %d", (int) event);
+ break;
+ }
+}
+
+/*
+ * sepgsql_utility_command
+ *
+ * It tries to rough-grained control on utility commands; some of them can
+ * break whole of the things if nefarious user would use.
+ */
+static void
+sepgsql_utility_command(Node *parsetree,
+ const char *queryString,
+ ParamListInfo params,
+ bool isTopLevel,
+ DestReceiver *dest,
+ char *completionTag)
+{
+ if (next_ProcessUtility_hook)
+ (*next_ProcessUtility_hook) (parsetree, queryString, params,
+ isTopLevel, dest, completionTag);
+
+ /*
+ * Check command tag to avoid nefarious operations
+ */
+ switch (nodeTag(parsetree))
+ {
+ case T_LoadStmt:
+
+ /*
+ * We reject LOAD command across the board on enforcing mode,
+ * because a binary module can arbitrarily override hooks.
+ */
+ if (sepgsql_getenforce())
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("SELinux: LOAD is not permitted")));
+ }
+ break;
+ default:
+
+ /*
+ * Right now we don't check any other utility commands, because it
+ * needs more detailed information to make access control decision
+ * here, but we don't want to have two parse and analyze routines
+ * individually.
+ */
+ break;
+ }
+
+ /*
+ * Original implementation
+ */
+ standard_ProcessUtility(parsetree, queryString, params,
+ isTopLevel, dest, completionTag);
+}
+
+/*
+ * Module load/unload callback
+ */
+void
+_PG_init(void)
+{
+ char *context;
+
+ /*
+ * We allow to load the SE-PostgreSQL module on single-user-mode or
+ * shared_preload_libraries settings only.
+ */
+ if (IsUnderPostmaster)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("sepgsql must be loaded via shared_preload_libraries")));
+
+ /*
+ * Check availability of SELinux on the platform. If disabled, we cannot
+ * activate any SE-PostgreSQL features, and we have to skip rest of
+ * initialization.
+ */
+ if (is_selinux_enabled() < 1)
+ {
+ sepgsql_set_mode(SEPGSQL_MODE_DISABLED);
+ return;
+ }
+
+ /*
+ * sepgsql.permissive = (on|off)
+ *
+ * This variable controls performing mode of SE-PostgreSQL on user's
+ * session.
+ */
+ DefineCustomBoolVariable("sepgsql.permissive",
+ "Turn on/off permissive mode in SE-PostgreSQL",
+ NULL,
+ &sepgsql_permissive,
+ false,
+ PGC_SIGHUP,
+ GUC_NOT_IN_SAMPLE,
+ NULL,
+ NULL,
+ NULL);
+
+ /*
+ * sepgsql.debug_audit = (on|off)
+ *
+ * This variable allows users to turn on/off audit logs on access control
+ * decisions, independent from auditallow/auditdeny setting in the
+ * security policy. We intend to use this option for debugging purpose.
+ */
+ DefineCustomBoolVariable("sepgsql.debug_audit",
+ "Turn on/off debug audit messages",
+ NULL,
+ &sepgsql_debug_audit,
+ false,
+ PGC_USERSET,
+ GUC_NOT_IN_SAMPLE,
+ NULL,
+ NULL,
+ NULL);
+
+ /*
+ * Set up dummy client label.
+ *
+ * XXX - note that PostgreSQL launches background worker process like
+ * autovacuum without authentication steps. So, we initialize sepgsql_mode
+ * with SEPGSQL_MODE_INTERNAL, and client_label with the security context
+ * of server process. Later, it also launches background of user session.
+ * In this case, the process is always hooked on post-authentication, and
+ * we can initialize the sepgsql_mode and client_label correctly.
+ */
+ if (getcon_raw(&context) < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux: failed to get server security label: %m")));
+ sepgsql_set_client_label(context);
+
+ /* Security label provider hook */
+ register_label_provider(SEPGSQL_LABEL_TAG,
+ sepgsql_object_relabel);
+
+ /* Client authentication hook */
+ next_client_auth_hook = ClientAuthentication_hook;
+ ClientAuthentication_hook = sepgsql_client_auth;
+
+ /* Object access hook */
+ next_object_access_hook = object_access_hook;
+ object_access_hook = sepgsql_object_access;
+
+ /* DML permission check */
+ next_exec_check_perms_hook = ExecutorCheckPerms_hook;
+ ExecutorCheckPerms_hook = sepgsql_exec_check_perms;
+
+ /* Trusted procedure hooks */
+ next_needs_fmgr_hook = needs_fmgr_hook;
+ needs_fmgr_hook = sepgsql_needs_fmgr_hook;
+
+ next_fmgr_hook = fmgr_hook;
+ fmgr_hook = sepgsql_fmgr_hook;
+
+ /* ProcessUtility hook */
+ next_ProcessUtility_hook = ProcessUtility_hook;
+ ProcessUtility_hook = sepgsql_utility_command;
+}
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
new file mode 100644
index 0000000000..669ee35ac3
--- /dev/null
+++ b/contrib/sepgsql/label.c
@@ -0,0 +1,528 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/label.c
+ *
+ * Routines to support SELinux labels (security context)
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/genam.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+#include "commands/dbcommands.h"
+#include "commands/seclabel.h"
+#include "libpq/libpq-be.h"
+#include "miscadmin.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/tqual.h"
+
+#include "sepgsql.h"
+
+#include <selinux/label.h>
+
+/*
+ * client_label
+ *
+ * security label of the client process
+ */
+static char *client_label = NULL;
+
+char *
+sepgsql_get_client_label(void)
+{
+ return client_label;
+}
+
+char *
+sepgsql_set_client_label(char *new_label)
+{
+ char *old_label = client_label;
+
+ client_label = new_label;
+
+ return old_label;
+}
+
+/*
+ * sepgsql_get_label
+ *
+ * It returns a security context of the specified database object.
+ * If unlabeled or incorrectly labeled, the system "unlabeled" label
+ * shall be returned.
+ */
+char *
+sepgsql_get_label(Oid classId, Oid objectId, int32 subId)
+{
+ ObjectAddress object;
+ char *label;
+
+ object.classId = classId;
+ object.objectId = objectId;
+ object.objectSubId = subId;
+
+ label = GetSecurityLabel(&object, SEPGSQL_LABEL_TAG);
+ if (!label || security_check_context_raw((security_context_t) label))
+ {
+ security_context_t unlabeled;
+
+ if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux: failed to get initial security label: %m")));
+ PG_TRY();
+ {
+ label = pstrdup(unlabeled);
+ }
+ PG_CATCH();
+ {
+ freecon(unlabeled);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+
+ freecon(unlabeled);
+ }
+ return label;
+}
+
+/*
+ * sepgsql_object_relabel
+ *
+ * An entrypoint of SECURITY LABEL statement
+ */
+void
+sepgsql_object_relabel(const ObjectAddress *object, const char *seclabel)
+{
+ /*
+ * validate format of the supplied security label, if it is security
+ * context of selinux.
+ */
+ if (seclabel &&
+ security_check_context_raw((security_context_t) seclabel) < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("SELinux: invalid security label: \"%s\"", seclabel)));
+
+ /*
+ * Do actual permission checks for each object classes
+ */
+ switch (object->classId)
+ {
+ case NamespaceRelationId:
+ sepgsql_schema_relabel(object->objectId, seclabel);
+ break;
+ case RelationRelationId:
+ if (object->objectSubId == 0)
+ sepgsql_relation_relabel(object->objectId,
+ seclabel);
+ else
+ sepgsql_attribute_relabel(object->objectId,
+ object->objectSubId,
+ seclabel);
+ break;
+ case ProcedureRelationId:
+ sepgsql_proc_relabel(object->objectId, seclabel);
+ break;
+
+ default:
+ elog(ERROR, "unsupported object type: %u", object->classId);
+ break;
+ }
+}
+
+/*
+ * TEXT sepgsql_getcon(VOID)
+ *
+ * It returns the security label of the client.
+ */
+PG_FUNCTION_INFO_V1(sepgsql_getcon);
+Datum
+sepgsql_getcon(PG_FUNCTION_ARGS)
+{
+ char *client_label;
+
+ if (!sepgsql_is_enabled())
+ PG_RETURN_NULL();
+
+ client_label = sepgsql_get_client_label();
+
+ PG_RETURN_TEXT_P(cstring_to_text(client_label));
+}
+
+/*
+ * TEXT sepgsql_mcstrans_in(TEXT)
+ *
+ * It translate the given qualified MLS/MCS range into raw format
+ * when mcstrans daemon is working.
+ */
+PG_FUNCTION_INFO_V1(sepgsql_mcstrans_in);
+Datum
+sepgsql_mcstrans_in(PG_FUNCTION_ARGS)
+{
+ text *label = PG_GETARG_TEXT_P(0);
+ char *raw_label;
+ char *result;
+
+ if (!sepgsql_is_enabled())
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("sepgsql is not enabled")));
+
+ if (selinux_trans_to_raw_context(text_to_cstring(label),
+ &raw_label) < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux: could not translate security label: %m")));
+
+ PG_TRY();
+ {
+ result = pstrdup(raw_label);
+ }
+ PG_CATCH();
+ {
+ freecon(raw_label);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+ freecon(raw_label);
+
+ PG_RETURN_TEXT_P(cstring_to_text(result));
+}
+
+/*
+ * TEXT sepgsql_mcstrans_out(TEXT)
+ *
+ * It translate the given raw MLS/MCS range into qualified format
+ * when mcstrans daemon is working.
+ */
+PG_FUNCTION_INFO_V1(sepgsql_mcstrans_out);
+Datum
+sepgsql_mcstrans_out(PG_FUNCTION_ARGS)
+{
+ text *label = PG_GETARG_TEXT_P(0);
+ char *qual_label;
+ char *result;
+
+ if (!sepgsql_is_enabled())
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("sepgsql is not currently enabled")));
+
+ if (selinux_raw_to_trans_context(text_to_cstring(label),
+ &qual_label) < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux: could not translate security label: %m")));
+
+ PG_TRY();
+ {
+ result = pstrdup(qual_label);
+ }
+ PG_CATCH();
+ {
+ freecon(qual_label);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+ freecon(qual_label);
+
+ PG_RETURN_TEXT_P(cstring_to_text(result));
+}
+
+/*
+ * quote_object_names
+ *
+ * It tries to quote the supplied identifiers
+ */
+static char *
+quote_object_name(const char *src1, const char *src2,
+ const char *src3, const char *src4)
+{
+ StringInfoData result;
+ const char *temp;
+
+ initStringInfo(&result);
+
+ if (src1)
+ {
+ temp = quote_identifier(src1);
+ appendStringInfo(&result, "%s", temp);
+ if (src1 != temp)
+ pfree((void *) temp);
+ }
+ if (src2)
+ {
+ temp = quote_identifier(src2);
+ appendStringInfo(&result, ".%s", temp);
+ if (src2 != temp)
+ pfree((void *) temp);
+ }
+ if (src3)
+ {
+ temp = quote_identifier(src3);
+ appendStringInfo(&result, ".%s", temp);
+ if (src3 != temp)
+ pfree((void *) temp);
+ }
+ if (src4)
+ {
+ temp = quote_identifier(src4);
+ appendStringInfo(&result, ".%s", temp);
+ if (src4 != temp)
+ pfree((void *) temp);
+ }
+ return result.data;
+}
+
+/*
+ * exec_object_restorecon
+ *
+ * This routine is a helper called by sepgsql_restorecon; it set up
+ * initial security labels of database objects within the supplied
+ * catalog OID.
+ */
+static void
+exec_object_restorecon(struct selabel_handle * sehnd, Oid catalogId)
+{
+ Relation rel;
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ char *database_name = get_database_name(MyDatabaseId);
+ char *namespace_name;
+ Oid namespace_id;
+ char *relation_name;
+
+ /*
+ * Open the target catalog. We don't want to allow writable accesses by
+ * other session during initial labeling.
+ */
+ rel = heap_open(catalogId, AccessShareLock);
+
+ sscan = systable_beginscan(rel, InvalidOid, false,
+ SnapshotNow, 0, NULL);
+ while (HeapTupleIsValid(tuple = systable_getnext(sscan)))
+ {
+ Form_pg_namespace nspForm;
+ Form_pg_class relForm;
+ Form_pg_attribute attForm;
+ Form_pg_proc proForm;
+ char *objname;
+ int objtype = 1234;
+ ObjectAddress object;
+ security_context_t context;
+
+ /*
+ * The way to determine object name depends on object classes. So, any
+ * branches set up `objtype', `objname' and `object' here.
+ */
+ switch (catalogId)
+ {
+ case NamespaceRelationId:
+ nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
+
+ objtype = SELABEL_DB_SCHEMA;
+
+ objname = quote_object_name(database_name,
+ NameStr(nspForm->nspname),
+ NULL, NULL);
+
+ object.classId = NamespaceRelationId;
+ object.objectId = HeapTupleGetOid(tuple);
+ object.objectSubId = 0;
+ break;
+
+ case RelationRelationId:
+ relForm = (Form_pg_class) GETSTRUCT(tuple);
+
+ if (relForm->relkind == RELKIND_RELATION)
+ objtype = SELABEL_DB_TABLE;
+ else if (relForm->relkind == RELKIND_SEQUENCE)
+ objtype = SELABEL_DB_SEQUENCE;
+ else if (relForm->relkind == RELKIND_VIEW)
+ objtype = SELABEL_DB_VIEW;
+ else
+ continue; /* no need to assign security label */
+
+ namespace_name = get_namespace_name(relForm->relnamespace);
+ objname = quote_object_name(database_name,
+ namespace_name,
+ NameStr(relForm->relname),
+ NULL);
+ pfree(namespace_name);
+
+ object.classId = RelationRelationId;
+ object.objectId = HeapTupleGetOid(tuple);
+ object.objectSubId = 0;
+ break;
+
+ case AttributeRelationId:
+ attForm = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ if (get_rel_relkind(attForm->attrelid) != RELKIND_RELATION)
+ continue; /* no need to assign security label */
+
+ objtype = SELABEL_DB_COLUMN;
+
+ namespace_id = get_rel_namespace(attForm->attrelid);
+ namespace_name = get_namespace_name(namespace_id);
+ relation_name = get_rel_name(attForm->attrelid);
+ objname = quote_object_name(database_name,
+ namespace_name,
+ relation_name,
+ NameStr(attForm->attname));
+ pfree(namespace_name);
+ pfree(relation_name);
+
+ object.classId = RelationRelationId;
+ object.objectId = attForm->attrelid;
+ object.objectSubId = attForm->attnum;
+ break;
+
+ case ProcedureRelationId:
+ proForm = (Form_pg_proc) GETSTRUCT(tuple);
+
+ objtype = SELABEL_DB_PROCEDURE;
+
+ namespace_name = get_namespace_name(proForm->pronamespace);
+ objname = quote_object_name(database_name,
+ namespace_name,
+ NameStr(proForm->proname),
+ NULL);
+ pfree(namespace_name);
+
+ object.classId = ProcedureRelationId;
+ object.objectId = HeapTupleGetOid(tuple);
+ object.objectSubId = 0;
+ break;
+
+ default:
+ elog(ERROR, "unexpected catalog id: %u", catalogId);
+ objname = NULL; /* for compiler quiet */
+ break;
+ }
+
+ if (selabel_lookup_raw(sehnd, &context, objname, objtype) == 0)
+ {
+ PG_TRY();
+ {
+ /*
+ * Check SELinux permission to relabel the fetched object,
+ * then do the actual relabeling.
+ */
+ sepgsql_object_relabel(&object, context);
+
+ SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, context);
+ }
+ PG_CATCH();
+ {
+ freecon(context);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+ freecon(context);
+ }
+ else if (errno == ENOENT)
+ ereport(WARNING,
+ (errmsg("SELinux: no initial label assigned for %s (type=%d), skipping",
+ objname, objtype)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux: could not determine initial security label for %s (type=%d): %m", objname, objtype)));
+
+ pfree(objname);
+ }
+ systable_endscan(sscan);
+
+ heap_close(rel, NoLock);
+}
+
+/*
+ * BOOL sepgsql_restorecon(TEXT specfile)
+ *
+ * This function tries to assign initial security labels on all the object
+ * within the current database, according to the system setting.
+ * It is typically invoked by sepgsql-install script just after initdb, to
+ * assign initial security labels.
+ *
+ * If @specfile is not NULL, it uses explicitly specified specfile, instead
+ * of the system default.
+ */
+PG_FUNCTION_INFO_V1(sepgsql_restorecon);
+Datum
+sepgsql_restorecon(PG_FUNCTION_ARGS)
+{
+ struct selabel_handle *sehnd;
+ struct selinux_opt seopts;
+
+ /*
+ * SELinux has to be enabled on the running platform.
+ */
+ if (!sepgsql_is_enabled())
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("sepgsql is not currently enabled")));
+
+ /*
+ * Check DAC permission. Only superuser can set up initial security
+ * labels, like root-user in filesystems
+ */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("SELinux: must be superuser to restore initial contexts")));
+
+ /*
+ * Open selabel_lookup(3) stuff. It provides a set of mapping between an
+ * initial security label and object class/name due to the system setting.
+ */
+ if (PG_ARGISNULL(0))
+ {
+ seopts.type = SELABEL_OPT_UNUSED;
+ seopts.value = NULL;
+ }
+ else
+ {
+ seopts.type = SELABEL_OPT_PATH;
+ seopts.value = TextDatumGetCString(PG_GETARG_DATUM(0));
+ }
+ sehnd = selabel_open(SELABEL_CTX_DB, &seopts, 1);
+ if (!sehnd)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux: failed to initialize labeling handle: %m")));
+ PG_TRY();
+ {
+ /*
+ * Right now, we have no support labeling on the shared database
+ * objects, such as database, role, or tablespace.
+ */
+ exec_object_restorecon(sehnd, NamespaceRelationId);
+ exec_object_restorecon(sehnd, RelationRelationId);
+ exec_object_restorecon(sehnd, AttributeRelationId);
+ exec_object_restorecon(sehnd, ProcedureRelationId);
+ }
+ PG_CATCH();
+ {
+ selabel_close(sehnd);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+
+ selabel_close(sehnd);
+
+ PG_RETURN_BOOL(true);
+}
diff --git a/contrib/sepgsql/launcher b/contrib/sepgsql/launcher
new file mode 100755
index 0000000000..9e5ecdc400
--- /dev/null
+++ b/contrib/sepgsql/launcher
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# A wrapper script to launch psql command in regression test
+#
+# Copyright (c) 2010-2011, PostgreSQL Global Development Group
+#
+# -------------------------------------------------------------------------
+
+if [ $# -lt 1 ]; then
+ echo "usage: `basename $0` <command> [options...]"
+ exit 1
+fi
+
+RUNCON=`which runcon`
+if [ ! -e "$RUNCON" ]; then
+ echo "runcon command is not found"
+ exit 1
+fi
+
+#
+# Read SQL from stdin
+#
+TEMP=`mktemp`
+CONTEXT=""
+
+while IFS='\\n' read LINE
+do
+ if echo "$LINE" | grep -q "^-- @SECURITY-CONTEXT="; then
+ if [ -s "$TEMP" ]; then
+ if [ -n "$CONTEXT" ]; then
+ "$RUNCON" "$CONTEXT" $* < "$TEMP"
+ else
+ $* < $TEMP
+ fi
+ truncate -s0 $TEMP
+ fi
+ CONTEXT=`echo "$LINE" | sed 's/^-- @SECURITY-CONTEXT=//g'`
+ LINE="SELECT sepgsql_getcon(); -- confirm client privilege"
+ fi
+ echo "$LINE" >> $TEMP
+done
+
+if [ -s "$TEMP" ]; then
+ if [ -n "$CONTEXT" ]; then
+ "$RUNCON" "$CONTEXT" $* < "$TEMP"
+ else
+ $* < $TEMP
+ fi
+fi
+
+# cleanup temp file
+rm -f $TEMP
diff --git a/contrib/sepgsql/proc.c b/contrib/sepgsql/proc.c
new file mode 100644
index 0000000000..3b8bf23ba3
--- /dev/null
+++ b/contrib/sepgsql/proc.c
@@ -0,0 +1,159 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/proc.c
+ *
+ * Routines corresponding to procedure objects
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/sysattr.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+#include "commands/seclabel.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/tqual.h"
+
+#include "sepgsql.h"
+
+/*
+ * sepgsql_proc_post_create
+ *
+ * This routine assigns a default security label on a newly defined
+ * procedure.
+ */
+void
+sepgsql_proc_post_create(Oid functionId)
+{
+ Relation rel;
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ Oid namespaceId;
+ ObjectAddress object;
+ char *scontext;
+ char *tcontext;
+ char *ncontext;
+
+ /*
+ * Fetch namespace of the new procedure. Because pg_proc entry is not
+ * visible right now, we need to scan the catalog using SnapshotSelf.
+ */
+ rel = heap_open(ProcedureRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey,
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(functionId));
+
+ sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
+ SnapshotSelf, 1, &skey);
+
+ tuple = systable_getnext(sscan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "catalog lookup failed for proc %u", functionId);
+
+ namespaceId = ((Form_pg_proc) GETSTRUCT(tuple))->pronamespace;
+
+ systable_endscan(sscan);
+ heap_close(rel, AccessShareLock);
+
+ /*
+ * Compute a default security label when we create a new procedure object
+ * under the specified namespace.
+ */
+ scontext = sepgsql_get_client_label();
+ tcontext = sepgsql_get_label(NamespaceRelationId, namespaceId, 0);
+ ncontext = sepgsql_compute_create(scontext, tcontext,
+ SEPG_CLASS_DB_PROCEDURE);
+
+ /*
+ * Assign the default security label on a new procedure
+ */
+ object.classId = ProcedureRelationId;
+ object.objectId = functionId;
+ object.objectSubId = 0;
+ SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
+
+ pfree(tcontext);
+ pfree(ncontext);
+}
+
+/*
+ * sepgsql_proc_relabel
+ *
+ * It checks privileges to relabel the supplied function
+ * by the `seclabel'.
+ */
+void
+sepgsql_proc_relabel(Oid functionId, const char *seclabel)
+{
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *audit_name;
+
+ audit_name = getObjectDescriptionOids(ProcedureRelationId, functionId);
+
+ /*
+ * check db_procedure:{setattr relabelfrom} permission
+ */
+ tcontext = sepgsql_get_label(ProcedureRelationId, functionId, 0);
+ sepgsql_check_perms(scontext,
+ tcontext,
+ SEPG_CLASS_DB_PROCEDURE,
+ SEPG_DB_PROCEDURE__SETATTR |
+ SEPG_DB_PROCEDURE__RELABELFROM,
+ audit_name,
+ true);
+ pfree(tcontext);
+
+ /*
+ * check db_procedure:{relabelto} permission
+ */
+ sepgsql_check_perms(scontext,
+ seclabel,
+ SEPG_CLASS_DB_PROCEDURE,
+ SEPG_DB_PROCEDURE__RELABELTO,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
+ * sepgsql_proc_get_domtrans
+ *
+ * It computes security label of the client that shall be applied when
+ * the current client invokes the supplied function.
+ * This computed label is either same or different from the current one.
+ * If security policy informed the function is a trusted-procedure,
+ * we need to switch security label of the client during execution of
+ * the function.
+ *
+ * Also note that the translated label shall be allocated using palloc().
+ * So, need to switch memory context, if you want to hold the string in
+ * someone except for CurrentMemoryContext.
+ */
+char *
+sepgsql_proc_get_domtrans(Oid functionId)
+{
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *ncontext;
+
+ tcontext = sepgsql_get_label(ProcedureRelationId, functionId, 0);
+
+ ncontext = sepgsql_compute_create(scontext,
+ tcontext,
+ SEPG_CLASS_PROCESS);
+ pfree(tcontext);
+
+ return ncontext;
+}
diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c
new file mode 100644
index 0000000000..963cfdf9f1
--- /dev/null
+++ b/contrib/sepgsql/relation.c
@@ -0,0 +1,276 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/label.c
+ *
+ * Routines corresponding to relation/attribute objects
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/sysattr.h"
+#include "catalog/indexing.h"
+#include "catalog/dependency.h"
+#include "catalog/pg_attribute.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_namespace.h"
+#include "commands/seclabel.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/tqual.h"
+
+#include "sepgsql.h"
+
+/*
+ * sepgsql_attribute_post_create
+ *
+ * This routine assigns a default security label on a newly defined
+ * column, using ALTER TABLE ... ADD COLUMN.
+ * Note that this routine is not invoked in the case of CREATE TABLE,
+ * although it also defines columns in addition to table.
+ */
+void
+sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum)
+{
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *ncontext;
+ ObjectAddress object;
+
+ /*
+ * Only attributes within regular relation have individual security
+ * labels.
+ */
+ if (get_rel_relkind(relOid) != RELKIND_RELATION)
+ return;
+
+ /*
+ * Compute a default security label when we create a new procedure object
+ * under the specified namespace.
+ */
+ scontext = sepgsql_get_client_label();
+ tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
+ ncontext = sepgsql_compute_create(scontext, tcontext,
+ SEPG_CLASS_DB_COLUMN);
+
+ /*
+ * Assign the default security label on a new procedure
+ */
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = attnum;
+ SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
+
+ pfree(tcontext);
+ pfree(ncontext);
+}
+
+/*
+ * sepgsql_attribute_relabel
+ *
+ * It checks privileges to relabel the supplied column
+ * by the `seclabel'.
+ */
+void
+sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
+ const char *seclabel)
+{
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *audit_name;
+ ObjectAddress object;
+
+ if (get_rel_relkind(relOid) != RELKIND_RELATION)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot set security label on non-regular columns")));
+
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = attnum;
+ audit_name = getObjectDescription(&object);
+
+ /*
+ * check db_column:{setattr relabelfrom} permission
+ */
+ tcontext = sepgsql_get_label(RelationRelationId, relOid, attnum);
+ sepgsql_check_perms(scontext,
+ tcontext,
+ SEPG_CLASS_DB_COLUMN,
+ SEPG_DB_COLUMN__SETATTR |
+ SEPG_DB_COLUMN__RELABELFROM,
+ audit_name,
+ true);
+
+ /*
+ * check db_column:{relabelto} permission
+ */
+ sepgsql_check_perms(scontext,
+ seclabel,
+ SEPG_CLASS_DB_COLUMN,
+ SEPG_DB_PROCEDURE__RELABELTO,
+ audit_name,
+ true);
+
+ pfree(tcontext);
+ pfree(audit_name);
+}
+
+/*
+ * sepgsql_relation_post_create
+ *
+ * The post creation hook of relation/attribute
+ */
+void
+sepgsql_relation_post_create(Oid relOid)
+{
+ Relation rel;
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ Form_pg_class classForm;
+ ObjectAddress object;
+ uint16 tclass;
+ char *scontext; /* subject */
+ char *tcontext; /* schema */
+ char *rcontext; /* relation */
+ char *ccontext; /* column */
+
+ /*
+ * Fetch catalog record of the new relation. Because pg_class entry is not
+ * visible right now, we need to scan the catalog using SnapshotSelf.
+ */
+ rel = heap_open(RelationRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey,
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relOid));
+
+ sscan = systable_beginscan(rel, ClassOidIndexId, true,
+ SnapshotSelf, 1, &skey);
+
+ tuple = systable_getnext(sscan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "catalog lookup failed for relation %u", relOid);
+
+ classForm = (Form_pg_class) GETSTRUCT(tuple);
+
+ if (classForm->relkind == RELKIND_RELATION)
+ tclass = SEPG_CLASS_DB_TABLE;
+ else if (classForm->relkind == RELKIND_SEQUENCE)
+ tclass = SEPG_CLASS_DB_SEQUENCE;
+ else if (classForm->relkind == RELKIND_VIEW)
+ tclass = SEPG_CLASS_DB_VIEW;
+ else
+ goto out; /* No need to assign individual labels */
+
+ /*
+ * Compute a default security label when we create a new relation object
+ * under the specified namespace.
+ */
+ scontext = sepgsql_get_client_label();
+ tcontext = sepgsql_get_label(NamespaceRelationId,
+ classForm->relnamespace, 0);
+ rcontext = sepgsql_compute_create(scontext, tcontext, tclass);
+
+ /*
+ * Assign the default security label on the new relation
+ */
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = 0;
+ SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, rcontext);
+
+ /*
+ * We also assigns a default security label on columns of the new regular
+ * tables.
+ */
+ if (classForm->relkind == RELKIND_RELATION)
+ {
+ AttrNumber index;
+
+ ccontext = sepgsql_compute_create(scontext, rcontext,
+ SEPG_CLASS_DB_COLUMN);
+ for (index = FirstLowInvalidHeapAttributeNumber + 1;
+ index <= classForm->relnatts;
+ index++)
+ {
+ if (index == InvalidAttrNumber)
+ continue;
+
+ if (index == ObjectIdAttributeNumber && !classForm->relhasoids)
+ continue;
+
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = index;
+ SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ccontext);
+ }
+ pfree(ccontext);
+ }
+ pfree(rcontext);
+out:
+ systable_endscan(sscan);
+ heap_close(rel, AccessShareLock);
+}
+
+/*
+ * sepgsql_relation_relabel
+ *
+ * It checks privileges to relabel the supplied relation by the `seclabel'.
+ */
+void
+sepgsql_relation_relabel(Oid relOid, const char *seclabel)
+{
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *audit_name;
+ char relkind;
+ uint16_t tclass = 0;
+
+ relkind = get_rel_relkind(relOid);
+ if (relkind == RELKIND_RELATION)
+ tclass = SEPG_CLASS_DB_TABLE;
+ else if (relkind == RELKIND_SEQUENCE)
+ tclass = SEPG_CLASS_DB_SEQUENCE;
+ else if (relkind == RELKIND_VIEW)
+ tclass = SEPG_CLASS_DB_VIEW;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot set security labels on relations except "
+ "for tables, sequences or views")));
+
+ audit_name = getObjectDescriptionOids(RelationRelationId, relOid);
+
+ /*
+ * check db_xxx:{setattr relabelfrom} permission
+ */
+ tcontext = sepgsql_get_label(RelationRelationId, relOid, 0);
+
+ sepgsql_check_perms(scontext,
+ tcontext,
+ tclass,
+ SEPG_DB_TABLE__SETATTR |
+ SEPG_DB_TABLE__RELABELFROM,
+ audit_name,
+ true);
+
+ /*
+ * check db_xxx:{relabelto} permission
+ */
+ sepgsql_check_perms(scontext,
+ seclabel,
+ tclass,
+ SEPG_DB_TABLE__RELABELTO,
+ audit_name,
+ true);
+
+ pfree(tcontext);
+ pfree(audit_name);
+}
diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c
new file mode 100644
index 0000000000..0de89971fb
--- /dev/null
+++ b/contrib/sepgsql/schema.c
@@ -0,0 +1,99 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/schema.c
+ *
+ * Routines corresponding to schema objects
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/dependency.h"
+#include "catalog/pg_namespace.h"
+#include "commands/seclabel.h"
+#include "utils/lsyscache.h"
+
+#include "sepgsql.h"
+
+/*
+ * sepgsql_schema_post_create
+ *
+ * This routine assigns a default security label on a newly defined
+ * schema.
+ */
+void
+sepgsql_schema_post_create(Oid namespaceId)
+{
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *ncontext;
+ ObjectAddress object;
+
+ /*
+ * FIXME: Right now, we assume pg_database object has a fixed security
+ * label, because pg_seclabel does not support to store label of shared
+ * database objects.
+ */
+ tcontext = "system_u:object_r:sepgsql_db_t:s0";
+
+ /*
+ * Compute a default security label when we create a new schema object
+ * under the working database.
+ */
+ ncontext = sepgsql_compute_create(scontext, tcontext,
+ SEPG_CLASS_DB_SCHEMA);
+
+ /*
+ * Assign the default security label on a new procedure
+ */
+ object.classId = NamespaceRelationId;
+ object.objectId = namespaceId;
+ object.objectSubId = 0;
+ SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
+
+ pfree(ncontext);
+}
+
+/*
+ * sepgsql_schema_relabel
+ *
+ * It checks privileges to relabel the supplied schema
+ * by the `seclabel'.
+ */
+void
+sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
+{
+ char *scontext = sepgsql_get_client_label();
+ char *tcontext;
+ char *audit_name;
+
+ audit_name = getObjectDescriptionOids(NamespaceRelationId, namespaceId);
+
+ /*
+ * check db_schema:{setattr relabelfrom} permission
+ */
+ tcontext = sepgsql_get_label(NamespaceRelationId, namespaceId, 0);
+
+ sepgsql_check_perms(scontext,
+ tcontext,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__SETATTR |
+ SEPG_DB_SCHEMA__RELABELFROM,
+ audit_name,
+ true);
+
+ /*
+ * check db_schema:{relabelto} permission
+ */
+ sepgsql_check_perms(scontext,
+ seclabel,
+ SEPG_CLASS_DB_SCHEMA,
+ SEPG_DB_SCHEMA__RELABELTO,
+ audit_name,
+ true);
+
+ pfree(tcontext);
+ pfree(audit_name);
+}
diff --git a/contrib/sepgsql/selinux.c b/contrib/sepgsql/selinux.c
new file mode 100644
index 0000000000..1f5a97e878
--- /dev/null
+++ b/contrib/sepgsql/selinux.c
@@ -0,0 +1,939 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/selinux.c
+ *
+ * Interactions between userspace and selinux in kernelspace,
+ * using libselinux api.
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "lib/stringinfo.h"
+
+#include "sepgsql.h"
+
+/*
+ * selinux_catalog
+ *
+ * This mapping table enables to translate the name of object classes and
+ * access vectors to/from their own codes.
+ * When we ask SELinux whether the required privileges are allowed or not,
+ * we use security_compute_av(3). It needs us to represent object classes
+ * and access vectors using 'external' codes defined in the security policy.
+ * It is determinded in the runtime, not build time. So, it needs an internal
+ * service to translate object class/access vectors which we want to check
+ * into the code which kernel want to be given.
+ */
+static struct
+{
+ const char *class_name;
+ uint16 class_code;
+ struct
+ {
+ const char *av_name;
+ uint32 av_code;
+ } av[32];
+} selinux_catalog[] =
+
+{
+ {
+ "process", SEPG_CLASS_PROCESS,
+ {
+ {
+ "transition", SEPG_PROCESS__TRANSITION
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "file", SEPG_CLASS_FILE,
+ {
+ {
+ "read", SEPG_FILE__READ
+ },
+ {
+ "write", SEPG_FILE__WRITE
+ },
+ {
+ "create", SEPG_FILE__CREATE
+ },
+ {
+ "getattr", SEPG_FILE__GETATTR
+ },
+ {
+ "unlink", SEPG_FILE__UNLINK
+ },
+ {
+ "rename", SEPG_FILE__RENAME
+ },
+ {
+ "append", SEPG_FILE__APPEND
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "dir", SEPG_CLASS_DIR,
+ {
+ {
+ "read", SEPG_DIR__READ
+ },
+ {
+ "write", SEPG_DIR__WRITE
+ },
+ {
+ "create", SEPG_DIR__CREATE
+ },
+ {
+ "getattr", SEPG_DIR__GETATTR
+ },
+ {
+ "unlink", SEPG_DIR__UNLINK
+ },
+ {
+ "rename", SEPG_DIR__RENAME
+ },
+ {
+ "search", SEPG_DIR__SEARCH
+ },
+ {
+ "add_name", SEPG_DIR__ADD_NAME
+ },
+ {
+ "remove_name", SEPG_DIR__REMOVE_NAME
+ },
+ {
+ "rmdir", SEPG_DIR__RMDIR
+ },
+ {
+ "reparent", SEPG_DIR__REPARENT
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "lnk_file", SEPG_CLASS_LNK_FILE,
+ {
+ {
+ "read", SEPG_LNK_FILE__READ
+ },
+ {
+ "write", SEPG_LNK_FILE__WRITE
+ },
+ {
+ "create", SEPG_LNK_FILE__CREATE
+ },
+ {
+ "getattr", SEPG_LNK_FILE__GETATTR
+ },
+ {
+ "unlink", SEPG_LNK_FILE__UNLINK
+ },
+ {
+ "rename", SEPG_LNK_FILE__RENAME
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "chr_file", SEPG_CLASS_CHR_FILE,
+ {
+ {
+ "read", SEPG_CHR_FILE__READ
+ },
+ {
+ "write", SEPG_CHR_FILE__WRITE
+ },
+ {
+ "create", SEPG_CHR_FILE__CREATE
+ },
+ {
+ "getattr", SEPG_CHR_FILE__GETATTR
+ },
+ {
+ "unlink", SEPG_CHR_FILE__UNLINK
+ },
+ {
+ "rename", SEPG_CHR_FILE__RENAME
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "blk_file", SEPG_CLASS_BLK_FILE,
+ {
+ {
+ "read", SEPG_BLK_FILE__READ
+ },
+ {
+ "write", SEPG_BLK_FILE__WRITE
+ },
+ {
+ "create", SEPG_BLK_FILE__CREATE
+ },
+ {
+ "getattr", SEPG_BLK_FILE__GETATTR
+ },
+ {
+ "unlink", SEPG_BLK_FILE__UNLINK
+ },
+ {
+ "rename", SEPG_BLK_FILE__RENAME
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "sock_file", SEPG_CLASS_SOCK_FILE,
+ {
+ {
+ "read", SEPG_SOCK_FILE__READ
+ },
+ {
+ "write", SEPG_SOCK_FILE__WRITE
+ },
+ {
+ "create", SEPG_SOCK_FILE__CREATE
+ },
+ {
+ "getattr", SEPG_SOCK_FILE__GETATTR
+ },
+ {
+ "unlink", SEPG_SOCK_FILE__UNLINK
+ },
+ {
+ "rename", SEPG_SOCK_FILE__RENAME
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "fifo_file", SEPG_CLASS_FIFO_FILE,
+ {
+ {
+ "read", SEPG_FIFO_FILE__READ
+ },
+ {
+ "write", SEPG_FIFO_FILE__WRITE
+ },
+ {
+ "create", SEPG_FIFO_FILE__CREATE
+ },
+ {
+ "getattr", SEPG_FIFO_FILE__GETATTR
+ },
+ {
+ "unlink", SEPG_FIFO_FILE__UNLINK
+ },
+ {
+ "rename", SEPG_FIFO_FILE__RENAME
+ },
+ {
+ NULL, 0UL
+ }
+ }
+ },
+ {
+ "db_database", SEPG_CLASS_DB_DATABASE,
+ {
+ {
+ "create", SEPG_DB_DATABASE__CREATE
+ },
+ {
+ "drop", SEPG_DB_DATABASE__DROP
+ },
+ {
+ "getattr", SEPG_DB_DATABASE__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_DATABASE__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_DATABASE__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_DATABASE__RELABELTO
+ },
+ {
+ "access", SEPG_DB_DATABASE__ACCESS
+ },
+ {
+ "load_module", SEPG_DB_DATABASE__LOAD_MODULE
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_schema", SEPG_CLASS_DB_SCHEMA,
+ {
+ {
+ "create", SEPG_DB_SCHEMA__CREATE
+ },
+ {
+ "drop", SEPG_DB_SCHEMA__DROP
+ },
+ {
+ "getattr", SEPG_DB_SCHEMA__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_SCHEMA__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_SCHEMA__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_SCHEMA__RELABELTO
+ },
+ {
+ "search", SEPG_DB_SCHEMA__SEARCH
+ },
+ {
+ "add_name", SEPG_DB_SCHEMA__ADD_NAME
+ },
+ {
+ "remove_name", SEPG_DB_SCHEMA__REMOVE_NAME
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_table", SEPG_CLASS_DB_TABLE,
+ {
+ {
+ "create", SEPG_DB_TABLE__CREATE
+ },
+ {
+ "drop", SEPG_DB_TABLE__DROP
+ },
+ {
+ "getattr", SEPG_DB_TABLE__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_TABLE__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_TABLE__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_TABLE__RELABELTO
+ },
+ {
+ "select", SEPG_DB_TABLE__SELECT
+ },
+ {
+ "update", SEPG_DB_TABLE__UPDATE
+ },
+ {
+ "insert", SEPG_DB_TABLE__INSERT
+ },
+ {
+ "delete", SEPG_DB_TABLE__DELETE
+ },
+ {
+ "lock", SEPG_DB_TABLE__LOCK
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_sequence", SEPG_CLASS_DB_SEQUENCE,
+ {
+ {
+ "create", SEPG_DB_SEQUENCE__CREATE
+ },
+ {
+ "drop", SEPG_DB_SEQUENCE__DROP
+ },
+ {
+ "getattr", SEPG_DB_SEQUENCE__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_SEQUENCE__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_SEQUENCE__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_SEQUENCE__RELABELTO
+ },
+ {
+ "get_value", SEPG_DB_SEQUENCE__GET_VALUE
+ },
+ {
+ "next_value", SEPG_DB_SEQUENCE__NEXT_VALUE
+ },
+ {
+ "set_value", SEPG_DB_SEQUENCE__SET_VALUE
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_procedure", SEPG_CLASS_DB_PROCEDURE,
+ {
+ {
+ "create", SEPG_DB_PROCEDURE__CREATE
+ },
+ {
+ "drop", SEPG_DB_PROCEDURE__DROP
+ },
+ {
+ "getattr", SEPG_DB_PROCEDURE__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_PROCEDURE__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_PROCEDURE__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_PROCEDURE__RELABELTO
+ },
+ {
+ "execute", SEPG_DB_PROCEDURE__EXECUTE
+ },
+ {
+ "entrypoint", SEPG_DB_PROCEDURE__ENTRYPOINT
+ },
+ {
+ "install", SEPG_DB_PROCEDURE__INSTALL
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_column", SEPG_CLASS_DB_COLUMN,
+ {
+ {
+ "create", SEPG_DB_COLUMN__CREATE
+ },
+ {
+ "drop", SEPG_DB_COLUMN__DROP
+ },
+ {
+ "getattr", SEPG_DB_COLUMN__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_COLUMN__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_COLUMN__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_COLUMN__RELABELTO
+ },
+ {
+ "select", SEPG_DB_COLUMN__SELECT
+ },
+ {
+ "update", SEPG_DB_COLUMN__UPDATE
+ },
+ {
+ "insert", SEPG_DB_COLUMN__INSERT
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_tuple", SEPG_CLASS_DB_TUPLE,
+ {
+ {
+ "relabelfrom", SEPG_DB_TUPLE__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_TUPLE__RELABELTO
+ },
+ {
+ "select", SEPG_DB_TUPLE__SELECT
+ },
+ {
+ "update", SEPG_DB_TUPLE__UPDATE
+ },
+ {
+ "insert", SEPG_DB_TUPLE__INSERT
+ },
+ {
+ "delete", SEPG_DB_TUPLE__DELETE
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_blob", SEPG_CLASS_DB_BLOB,
+ {
+ {
+ "create", SEPG_DB_BLOB__CREATE
+ },
+ {
+ "drop", SEPG_DB_BLOB__DROP
+ },
+ {
+ "getattr", SEPG_DB_BLOB__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_BLOB__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_BLOB__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_BLOB__RELABELTO
+ },
+ {
+ "read", SEPG_DB_BLOB__READ
+ },
+ {
+ "write", SEPG_DB_BLOB__WRITE
+ },
+ {
+ "import", SEPG_DB_BLOB__IMPORT
+ },
+ {
+ "export", SEPG_DB_BLOB__EXPORT
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_language", SEPG_CLASS_DB_LANGUAGE,
+ {
+ {
+ "create", SEPG_DB_LANGUAGE__CREATE
+ },
+ {
+ "drop", SEPG_DB_LANGUAGE__DROP
+ },
+ {
+ "getattr", SEPG_DB_LANGUAGE__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_LANGUAGE__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_LANGUAGE__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_LANGUAGE__RELABELTO
+ },
+ {
+ "implement", SEPG_DB_LANGUAGE__IMPLEMENT
+ },
+ {
+ "execute", SEPG_DB_LANGUAGE__EXECUTE
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+ {
+ "db_view", SEPG_CLASS_DB_VIEW,
+ {
+ {
+ "create", SEPG_DB_VIEW__CREATE
+ },
+ {
+ "drop", SEPG_DB_VIEW__DROP
+ },
+ {
+ "getattr", SEPG_DB_VIEW__GETATTR
+ },
+ {
+ "setattr", SEPG_DB_VIEW__SETATTR
+ },
+ {
+ "relabelfrom", SEPG_DB_VIEW__RELABELFROM
+ },
+ {
+ "relabelto", SEPG_DB_VIEW__RELABELTO
+ },
+ {
+ "expand", SEPG_DB_VIEW__EXPAND
+ },
+ {
+ NULL, 0UL
+ },
+ }
+ },
+};
+
+/*
+ * sepgsql_mode
+ *
+ * SEPGSQL_MODE_DISABLED: Disabled on runtime
+ * SEPGSQL_MODE_DEFAULT: Same as system settings
+ * SEPGSQL_MODE_PERMISSIVE: Always permissive mode
+ * SEPGSQL_MODE_INTERNAL: Same as permissive, except for no audit logs
+ */
+static int sepgsql_mode = SEPGSQL_MODE_INTERNAL;
+
+/*
+ * sepgsql_is_enabled
+ */
+bool
+sepgsql_is_enabled(void)
+{
+ return (sepgsql_mode != SEPGSQL_MODE_DISABLED ? true : false);
+}
+
+/*
+ * sepgsql_get_mode
+ */
+int
+sepgsql_get_mode(void)
+{
+ return sepgsql_mode;
+}
+
+/*
+ * sepgsql_set_mode
+ */
+int
+sepgsql_set_mode(int new_mode)
+{
+ int old_mode = sepgsql_mode;
+
+ sepgsql_mode = new_mode;
+
+ return old_mode;
+}
+
+/*
+ * sepgsql_getenforce
+ *
+ * It returns whether the current working mode tries to enforce access
+ * control decision, or not. It shall be enforced when sepgsql_mode is
+ * SEPGSQL_MODE_DEFAULT and system is running in enforcing mode.
+ */
+bool
+sepgsql_getenforce(void)
+{
+ if (sepgsql_mode == SEPGSQL_MODE_DEFAULT &&
+ security_getenforce() > 0)
+ return true;
+
+ return false;
+}
+
+/*
+ * sepgsql_audit_log
+ *
+ * It generates a security audit record. In the default, it writes out
+ * audit records into standard PG's logfile. It also allows to set up
+ * external audit log receiver, such as auditd in Linux, using the
+ * sepgsql_audit_hook.
+ *
+ * SELinux can control what should be audited and should not using
+ * "auditdeny" and "auditallow" rules in the security policy. In the
+ * default, all the access violations are audited, and all the access
+ * allowed are not audited. But we can set up the security policy, so
+ * we can have exceptions. So, it is necessary to follow the suggestion
+ * come from the security policy. (av_decision.auditallow and auditdeny)
+ *
+ * Security audit is an important feature, because it enables us to check
+ * what was happen if we have a security incident. In fact, ISO/IEC15408
+ * defines several security functionalities for audit features.
+ */
+void
+sepgsql_audit_log(bool denied,
+ const char *scontext,
+ const char *tcontext,
+ uint16 tclass,
+ uint32 audited,
+ const char *audit_name)
+{
+ StringInfoData buf;
+ const char *class_name;
+ const char *av_name;
+ int i;
+
+ /* lookup name of the object class */
+ Assert(tclass < SEPG_CLASS_MAX);
+ class_name = selinux_catalog[tclass].class_name;
+
+ /* lookup name of the permissions */
+ initStringInfo(&buf);
+ appendStringInfo(&buf, "%s {",
+ (denied ? "denied" : "allowed"));
+ for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
+ {
+ if (audited & (1UL << i))
+ {
+ av_name = selinux_catalog[tclass].av[i].av_name;
+ appendStringInfo(&buf, " %s", av_name);
+ }
+ }
+ appendStringInfo(&buf, " }");
+
+ /*
+ * Call external audit module, if loaded
+ */
+ appendStringInfo(&buf, " scontext=%s tcontext=%s tclass=%s",
+ scontext, tcontext, class_name);
+ if (audit_name)
+ appendStringInfo(&buf, " name=\"%s\"", audit_name);
+
+ ereport(LOG, (errmsg("SELinux: %s", buf.data)));
+}
+
+/*
+ * sepgsql_compute_avd
+ *
+ * It actually asks SELinux what permissions are allowed on a pair of
+ * the security contexts and object class. It also returns what permissions
+ * should be audited on access violation or allowed.
+ * In most cases, subject's security context (scontext) is a client, and
+ * target security context (tcontext) is a database object.
+ *
+ * The access control decision shall be set on the given av_decision.
+ * The av_decision.allowed has a bitmask of SEPG_<class>__<perms>
+ * to suggest a set of allowed actions in this object class.
+ */
+void
+sepgsql_compute_avd(const char *scontext,
+ const char *tcontext,
+ uint16 tclass,
+ struct av_decision * avd)
+{
+ const char *tclass_name;
+ security_class_t tclass_ex;
+ struct av_decision avd_ex;
+ int i,
+ deny_unknown = security_deny_unknown();
+
+ /* Get external code of the object class */
+ Assert(tclass < SEPG_CLASS_MAX);
+ Assert(tclass == selinux_catalog[tclass].class_code);
+
+ tclass_name = selinux_catalog[tclass].class_name;
+ tclass_ex = string_to_security_class(tclass_name);
+
+ if (tclass_ex == 0)
+ {
+ /*
+ * If the current security policy does not support permissions
+ * corresponding to database objects, we fill up them with dummy data.
+ * If security_deny_unknown() returns positive value, undefined
+ * permissions should be denied. Otherwise, allowed
+ */
+ avd->allowed = (security_deny_unknown() > 0 ? 0 : ~0);
+ avd->auditallow = 0U;
+ avd->auditdeny = ~0U;
+ avd->flags = 0;
+
+ return;
+ }
+
+ /*
+ * Ask SELinux what is allowed set of permissions on a pair of the
+ * security contexts and the given object class.
+ */
+ if (security_compute_av_flags_raw((security_context_t) scontext,
+ (security_context_t) tcontext,
+ tclass_ex, 0, &avd_ex) < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux could not compute av_decision: "
+ "scontext=%s tcontext=%s tclass=%s: %m",
+ scontext, tcontext, tclass_name)));
+
+ /*
+ * SELinux returns its access control decision as a set of permissions
+ * represented in external code which depends on run-time environment. So,
+ * we need to translate it to the internal representation before returning
+ * results for the caller.
+ */
+ memset(avd, 0, sizeof(struct av_decision));
+
+ for (i = 0; selinux_catalog[tclass].av[i].av_name; i++)
+ {
+ access_vector_t av_code_ex;
+ const char *av_name = selinux_catalog[tclass].av[i].av_name;
+ uint32 av_code = selinux_catalog[tclass].av[i].av_code;
+
+ av_code_ex = string_to_av_perm(tclass_ex, av_name);
+ if (av_code_ex == 0)
+ {
+ /* fill up undefined permissions */
+ if (!deny_unknown)
+ avd->allowed |= av_code;
+ avd->auditdeny |= av_code;
+
+ continue;
+ }
+
+ if (avd_ex.allowed & av_code_ex)
+ avd->allowed |= av_code;
+ if (avd_ex.auditallow & av_code_ex)
+ avd->auditallow |= av_code;
+ if (avd_ex.auditdeny & av_code_ex)
+ avd->auditdeny |= av_code;
+ }
+
+ return;
+}
+
+/*
+ * sepgsql_compute_create
+ *
+ * It returns a default security context to be assigned on a new database
+ * object. SELinux compute it based on a combination of client, upper object
+ * which owns the new object and object class.
+ *
+ * For example, when a client (staff_u:staff_r:staff_t:s0) tries to create
+ * a new table within a schema (system_u:object_r:sepgsql_schema_t:s0),
+ * SELinux looks-up its security policy. If it has a special rule on the
+ * combination of these security contexts and object class (db_table),
+ * it returns the security context suggested by the special rule.
+ * Otherwise, it returns the security context of schema, as is.
+ *
+ * We expect the caller already applies sanity/validation checks on the
+ * given security context.
+ *
+ * scontext: security context of the subject (mostly, peer process).
+ * tcontext: security context of the the upper database object.
+ * tclass: class code (SEPG_CLASS_*) of the new object in creation
+ */
+char *
+sepgsql_compute_create(const char *scontext,
+ const char *tcontext,
+ uint16 tclass)
+{
+ security_context_t ncontext;
+ security_class_t tclass_ex;
+ const char *tclass_name;
+ char *result;
+
+ /* Get external code of the object class */
+ Assert(tclass < SEPG_CLASS_MAX);
+
+ tclass_name = selinux_catalog[tclass].class_name;
+ tclass_ex = string_to_security_class(tclass_name);
+
+ /*
+ * Ask SELinux what is the default context for the given object class on a
+ * pair of security contexts
+ */
+ if (security_compute_create_raw((security_context_t) scontext,
+ (security_context_t) tcontext,
+ tclass_ex, &ncontext) < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("SELinux could not compute a new context: "
+ "scontext=%s tcontext=%s tclass=%s: %m",
+ scontext, tcontext, tclass_name)));
+
+ /*
+ * libselinux returns malloc()'ed string, so we need to copy it on the
+ * palloc()'ed region.
+ */
+ PG_TRY();
+ {
+ result = pstrdup(ncontext);
+ }
+ PG_CATCH();
+ {
+ freecon(ncontext);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+ freecon(ncontext);
+
+ return result;
+}
+
+/*
+ * sepgsql_check_perms
+ *
+ * It makes access control decision without userspace caching mechanism.
+ * If SELinux denied the required accesses on the pair of security labels,
+ * it raises an error or returns false.
+ *
+ * scontext: security label of the subject (mostly, peer process)
+ * tcontext: security label of the object being referenced
+ * tclass: class code (SEPG_CLASS_*) of the object being referenced
+ * required: a mask of required permissions (SEPG_<class>__<perm>)
+ * audit_name: a human readable object name for audit logs, or NULL.
+ * abort: true, if caller wants to raise an error on access violation
+ */
+bool
+sepgsql_check_perms(const char *scontext,
+ const char *tcontext,
+ uint16 tclass,
+ uint32 required,
+ const char *audit_name,
+ bool abort)
+{
+ struct av_decision avd;
+ uint32 denied;
+ uint32 audited;
+ bool result = true;
+
+ sepgsql_compute_avd(scontext, tcontext, tclass, &avd);
+
+ denied = required & ~avd.allowed;
+
+ if (sepgsql_get_debug_audit())
+ audited = (denied ? denied : required);
+ else
+ audited = (denied ? (denied & avd.auditdeny)
+ : (required & avd.auditallow));
+
+ if (denied &&
+ sepgsql_getenforce() > 0 &&
+ (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE) == 0)
+ result = false;
+
+ /*
+ * It records a security audit for the request, if needed. But, when
+ * SE-PgSQL performs 'internal' mode, it needs to keep silent.
+ */
+ if (audited && sepgsql_mode != SEPGSQL_MODE_INTERNAL)
+ {
+ sepgsql_audit_log(denied,
+ scontext,
+ tcontext,
+ tclass,
+ audited,
+ audit_name);
+ }
+
+ if (!result && abort)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("SELinux: security policy violation")));
+ return result;
+}
diff --git a/contrib/sepgsql/sepgsql-regtest.te b/contrib/sepgsql/sepgsql-regtest.te
new file mode 100644
index 0000000000..3b1def75a5
--- /dev/null
+++ b/contrib/sepgsql/sepgsql-regtest.te
@@ -0,0 +1,85 @@
+policy_module(sepgsql-regtest, 1.02)
+
+gen_require(`
+ all_userspace_class_perms
+')
+
+## <desc>
+## <p>
+## Allow to launch regression test of SE-PostgreSQL
+## Don't switch to TRUE in normal cases
+## </p>
+## </desc>
+gen_tunable(sepgsql_regression_test_mode, false)
+
+#
+# Type definitions for regression test
+#
+type sepgsql_regtest_trusted_proc_exec_t;
+postgresql_procedure_object(sepgsql_regtest_trusted_proc_exec_t)
+
+#
+# Test domains for database administrators
+#
+role sepgsql_regtest_dba_r;
+userdom_base_user_template(sepgsql_regtest_dba)
+userdom_manage_home_role(sepgsql_regtest_dba_r, sepgsql_regtest_dba_t)
+userdom_write_user_tmp_sockets(sepgsql_regtest_user_t)
+optional_policy(`
+ postgresql_admin(sepgsql_regtest_dba_t, sepgsql_regtest_dba_r)
+ postgresql_stream_connect(sepgsql_regtest_dba_t)
+')
+optional_policy(`
+ unconfined_stream_connect(sepgsql_regtest_dba_t)
+ unconfined_rw_pipes(sepgsql_regtest_dba_t)
+')
+
+#
+# Dummy domain for unpriv users
+#
+role sepgsql_regtest_user_r;
+userdom_base_user_template(sepgsql_regtest_user)
+userdom_manage_home_role(sepgsql_regtest_user_r, sepgsql_regtest_user_t)
+userdom_write_user_tmp_sockets(sepgsql_regtest_user_t)
+optional_policy(`
+ postgresql_role(sepgsql_regtest_user_r, sepgsql_regtest_user_t)
+ postgresql_stream_connect(sepgsql_regtest_user_t)
+')
+optional_policy(`
+ unconfined_stream_connect(sepgsql_regtest_user_t)
+ unconfined_rw_pipes(sepgsql_regtest_user_t)
+')
+
+#
+# Rules to launch psql in the dummy domains
+#
+optional_policy(`
+ gen_require(`
+ role unconfined_r;
+ type unconfined_t;
+ type sepgsql_trusted_proc_t;
+ ')
+ tunable_policy(`sepgsql_regression_test_mode',`
+ allow unconfined_t sepgsql_regtest_dba_t : process { transition };
+ allow unconfined_t sepgsql_regtest_user_t : process { transition };
+ ')
+ role unconfined_r types sepgsql_regtest_dba_t;
+ role unconfined_r types sepgsql_regtest_user_t;
+ role unconfined_r types sepgsql_trusted_proc_t;
+')
+
+#
+# Rule to check
+#
+optional_policy(`
+ # These rules intends sepgsql_regtest_user_t domain to translate
+ # sepgsql_regtest_dba_t on execution of procedures labeled as
+ # sepgsql_regtest_trusted_proc_exec_t, but does not allow transition
+ # permission from sepgsql_regtest_user_t to sepgsql_regtest_dba_t.
+ #
+ gen_require(`
+ attribute sepgsql_client_type;
+ ')
+ allow sepgsql_client_type sepgsql_regtest_trusted_proc_exec_t:db_procedure { getattr execute install };
+ type_transition sepgsql_regtest_user_t sepgsql_regtest_trusted_proc_exec_t:process sepgsql_regtest_dba_t;
+')
diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h
new file mode 100644
index 0000000000..71688ab784
--- /dev/null
+++ b/contrib/sepgsql/sepgsql.h
@@ -0,0 +1,291 @@
+/* -------------------------------------------------------------------------
+ *
+ * contrib/sepgsql/sepgsql.h
+ *
+ * Definitions corresponding to SE-PostgreSQL
+ *
+ * Copyright (c) 2010-2011, PostgreSQL Global Development Group
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef SEPGSQL_H
+#define SEPGSQL_H
+
+#include "catalog/objectaddress.h"
+#include "fmgr.h"
+
+#include <selinux/selinux.h>
+
+/*
+ * SE-PostgreSQL Label Tag
+ */
+#define SEPGSQL_LABEL_TAG "selinux"
+
+/*
+ * SE-PostgreSQL performing mode
+ */
+#define SEPGSQL_MODE_DEFAULT 1
+#define SEPGSQL_MODE_PERMISSIVE 2
+#define SEPGSQL_MODE_INTERNAL 3
+#define SEPGSQL_MODE_DISABLED 4
+
+/*
+ * Internally used code of object classes
+ */
+#define SEPG_CLASS_PROCESS 0
+#define SEPG_CLASS_FILE 1
+#define SEPG_CLASS_DIR 2
+#define SEPG_CLASS_LNK_FILE 3
+#define SEPG_CLASS_CHR_FILE 4
+#define SEPG_CLASS_BLK_FILE 5
+#define SEPG_CLASS_SOCK_FILE 6
+#define SEPG_CLASS_FIFO_FILE 7
+#define SEPG_CLASS_DB_DATABASE 8
+#define SEPG_CLASS_DB_SCHEMA 9
+#define SEPG_CLASS_DB_TABLE 10
+#define SEPG_CLASS_DB_SEQUENCE 11
+#define SEPG_CLASS_DB_PROCEDURE 12
+#define SEPG_CLASS_DB_COLUMN 13
+#define SEPG_CLASS_DB_TUPLE 14
+#define SEPG_CLASS_DB_BLOB 15
+#define SEPG_CLASS_DB_LANGUAGE 16
+#define SEPG_CLASS_DB_VIEW 17
+#define SEPG_CLASS_MAX 18
+
+/*
+ * Internally used code of access vectors
+ */
+#define SEPG_PROCESS__TRANSITION (1<<0)
+
+#define SEPG_FILE__READ (1<<0)
+#define SEPG_FILE__WRITE (1<<1)
+#define SEPG_FILE__CREATE (1<<2)
+#define SEPG_FILE__GETATTR (1<<3)
+#define SEPG_FILE__UNLINK (1<<4)
+#define SEPG_FILE__RENAME (1<<5)
+#define SEPG_FILE__APPEND (1<<6)
+
+#define SEPG_DIR__READ (SEPG_FILE__READ)
+#define SEPG_DIR__WRITE (SEPG_FILE__WRITE)
+#define SEPG_DIR__CREATE (SEPG_FILE__CREATE)
+#define SEPG_DIR__GETATTR (SEPG_FILE__GETATTR)
+#define SEPG_DIR__UNLINK (SEPG_FILE__UNLINK)
+#define SEPG_DIR__RENAME (SEPG_FILE__RENAME)
+#define SEPG_DIR__SEARCH (1<<6)
+#define SEPG_DIR__ADD_NAME (1<<7)
+#define SEPG_DIR__REMOVE_NAME (1<<8)
+#define SEPG_DIR__RMDIR (1<<9)
+#define SEPG_DIR__REPARENT (1<<10)
+
+#define SEPG_LNK_FILE__READ (SEPG_FILE__READ)
+#define SEPG_LNK_FILE__WRITE (SEPG_FILE__WRITE)
+#define SEPG_LNK_FILE__CREATE (SEPG_FILE__CREATE)
+#define SEPG_LNK_FILE__GETATTR (SEPG_FILE__GETATTR)
+#define SEPG_LNK_FILE__UNLINK (SEPG_FILE__UNLINK)
+#define SEPG_LNK_FILE__RENAME (SEPG_FILE__RENAME)
+
+#define SEPG_CHR_FILE__READ (SEPG_FILE__READ)
+#define SEPG_CHR_FILE__WRITE (SEPG_FILE__WRITE)
+#define SEPG_CHR_FILE__CREATE (SEPG_FILE__CREATE)
+#define SEPG_CHR_FILE__GETATTR (SEPG_FILE__GETATTR)
+#define SEPG_CHR_FILE__UNLINK (SEPG_FILE__UNLINK)
+#define SEPG_CHR_FILE__RENAME (SEPG_FILE__RENAME)
+
+#define SEPG_BLK_FILE__READ (SEPG_FILE__READ)
+#define SEPG_BLK_FILE__WRITE (SEPG_FILE__WRITE)
+#define SEPG_BLK_FILE__CREATE (SEPG_FILE__CREATE)
+#define SEPG_BLK_FILE__GETATTR (SEPG_FILE__GETATTR)
+#define SEPG_BLK_FILE__UNLINK (SEPG_FILE__UNLINK)
+#define SEPG_BLK_FILE__RENAME (SEPG_FILE__RENAME)
+
+#define SEPG_SOCK_FILE__READ (SEPG_FILE__READ)
+#define SEPG_SOCK_FILE__WRITE (SEPG_FILE__WRITE)
+#define SEPG_SOCK_FILE__CREATE (SEPG_FILE__CREATE)
+#define SEPG_SOCK_FILE__GETATTR (SEPG_FILE__GETATTR)
+#define SEPG_SOCK_FILE__UNLINK (SEPG_FILE__UNLINK)
+#define SEPG_SOCK_FILE__RENAME (SEPG_FILE__RENAME)
+
+#define SEPG_FIFO_FILE__READ (SEPG_FILE__READ)
+#define SEPG_FIFO_FILE__WRITE (SEPG_FILE__WRITE)
+#define SEPG_FIFO_FILE__CREATE (SEPG_FILE__CREATE)
+#define SEPG_FIFO_FILE__GETATTR (SEPG_FILE__GETATTR)
+#define SEPG_FIFO_FILE__UNLINK (SEPG_FILE__UNLINK)
+#define SEPG_FIFO_FILE__RENAME (SEPG_FILE__RENAME)
+
+#define SEPG_DB_DATABASE__CREATE (1<<0)
+#define SEPG_DB_DATABASE__DROP (1<<1)
+#define SEPG_DB_DATABASE__GETATTR (1<<2)
+#define SEPG_DB_DATABASE__SETATTR (1<<3)
+#define SEPG_DB_DATABASE__RELABELFROM (1<<4)
+#define SEPG_DB_DATABASE__RELABELTO (1<<5)
+#define SEPG_DB_DATABASE__ACCESS (1<<6)
+#define SEPG_DB_DATABASE__LOAD_MODULE (1<<7)
+
+#define SEPG_DB_SCHEMA__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_SCHEMA__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_SCHEMA__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_SCHEMA__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_SCHEMA__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_SCHEMA__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_SCHEMA__SEARCH (1<<6)
+#define SEPG_DB_SCHEMA__ADD_NAME (1<<7)
+#define SEPG_DB_SCHEMA__REMOVE_NAME (1<<8)
+
+#define SEPG_DB_TABLE__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_TABLE__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_TABLE__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_TABLE__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_TABLE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_TABLE__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_TABLE__SELECT (1<<6)
+#define SEPG_DB_TABLE__UPDATE (1<<7)
+#define SEPG_DB_TABLE__INSERT (1<<8)
+#define SEPG_DB_TABLE__DELETE (1<<9)
+#define SEPG_DB_TABLE__LOCK (1<<10)
+#define SEPG_DB_TABLE__INDEXON (1<<11)
+
+#define SEPG_DB_SEQUENCE__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_SEQUENCE__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_SEQUENCE__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_SEQUENCE__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_SEQUENCE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_SEQUENCE__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_SEQUENCE__GET_VALUE (1<<6)
+#define SEPG_DB_SEQUENCE__NEXT_VALUE (1<<7)
+#define SEPG_DB_SEQUENCE__SET_VALUE (1<<8)
+
+#define SEPG_DB_PROCEDURE__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_PROCEDURE__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_PROCEDURE__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_PROCEDURE__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_PROCEDURE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_PROCEDURE__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_PROCEDURE__EXECUTE (1<<6)
+#define SEPG_DB_PROCEDURE__ENTRYPOINT (1<<7)
+#define SEPG_DB_PROCEDURE__INSTALL (1<<8)
+
+#define SEPG_DB_COLUMN__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_COLUMN__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_COLUMN__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_COLUMN__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_COLUMN__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_COLUMN__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_COLUMN__SELECT (1<<6)
+#define SEPG_DB_COLUMN__UPDATE (1<<7)
+#define SEPG_DB_COLUMN__INSERT (1<<8)
+
+#define SEPG_DB_TUPLE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_TUPLE__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_TUPLE__SELECT (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_TUPLE__UPDATE (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_TUPLE__INSERT (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_TUPLE__DELETE (SEPG_DB_DATABASE__DROP)
+
+#define SEPG_DB_BLOB__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_BLOB__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_BLOB__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_BLOB__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_BLOB__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_BLOB__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_BLOB__READ (1<<6)
+#define SEPG_DB_BLOB__WRITE (1<<7)
+#define SEPG_DB_BLOB__IMPORT (1<<8)
+#define SEPG_DB_BLOB__EXPORT (1<<9)
+
+#define SEPG_DB_LANGUAGE__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_LANGUAGE__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_LANGUAGE__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_LANGUAGE__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_LANGUAGE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_LANGUAGE__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_LANGUAGE__IMPLEMENT (1<<6)
+#define SEPG_DB_LANGUAGE__EXECUTE (1<<7)
+
+#define SEPG_DB_VIEW__CREATE (SEPG_DB_DATABASE__CREATE)
+#define SEPG_DB_VIEW__DROP (SEPG_DB_DATABASE__DROP)
+#define SEPG_DB_VIEW__GETATTR (SEPG_DB_DATABASE__GETATTR)
+#define SEPG_DB_VIEW__SETATTR (SEPG_DB_DATABASE__SETATTR)
+#define SEPG_DB_VIEW__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM)
+#define SEPG_DB_VIEW__RELABELTO (SEPG_DB_DATABASE__RELABELTO)
+#define SEPG_DB_VIEW__EXPAND (1<<6)
+
+/*
+ * hooks.c
+ */
+extern bool sepgsql_get_permissive(void);
+extern bool sepgsql_get_debug_audit(void);
+
+/*
+ * selinux.c
+ */
+extern bool sepgsql_is_enabled(void);
+extern int sepgsql_get_mode(void);
+extern int sepgsql_set_mode(int new_mode);
+extern bool sepgsql_getenforce(void);
+
+extern void sepgsql_audit_log(bool denied,
+ const char *scontext,
+ const char *tcontext,
+ uint16 tclass,
+ uint32 audited,
+ const char *audit_name);
+
+extern void sepgsql_compute_avd(const char *scontext,
+ const char *tcontext,
+ uint16 tclass,
+ struct av_decision * avd);
+
+extern char *sepgsql_compute_create(const char *scontext,
+ const char *tcontext,
+ uint16 tclass);
+
+extern bool sepgsql_check_perms(const char *scontext,
+ const char *tcontext,
+ uint16 tclass,
+ uint32 required,
+ const char *audit_name,
+ bool abort);
+
+/*
+ * label.c
+ */
+extern char *sepgsql_get_client_label(void);
+extern char *sepgsql_set_client_label(char *new_label);
+extern char *sepgsql_get_label(Oid relOid, Oid objOid, int32 subId);
+
+extern void sepgsql_object_relabel(const ObjectAddress *object,
+ const char *seclabel);
+
+extern Datum sepgsql_getcon(PG_FUNCTION_ARGS);
+extern Datum sepgsql_mcstrans_in(PG_FUNCTION_ARGS);
+extern Datum sepgsql_mcstrans_out(PG_FUNCTION_ARGS);
+extern Datum sepgsql_restorecon(PG_FUNCTION_ARGS);
+
+/*
+ * dml.c
+ */
+extern bool sepgsql_dml_privileges(List *rangeTabls, bool abort);
+
+/*
+ * schema.c
+ */
+extern void sepgsql_schema_post_create(Oid namespaceId);
+extern void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel);
+
+/*
+ * relation.c
+ */
+extern void sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum);
+extern void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
+ const char *seclabel);
+extern void sepgsql_relation_post_create(Oid relOid);
+extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel);
+
+/*
+ * proc.c
+ */
+extern void sepgsql_proc_post_create(Oid functionId);
+extern void sepgsql_proc_relabel(Oid functionId, const char *seclabel);
+extern char *sepgsql_proc_get_domtrans(Oid functionId);
+
+#endif /* SEPGSQL_H */
diff --git a/contrib/sepgsql/sepgsql.sql.in b/contrib/sepgsql/sepgsql.sql.in
new file mode 100644
index 0000000000..45ffe31e6b
--- /dev/null
+++ b/contrib/sepgsql/sepgsql.sql.in
@@ -0,0 +1,36 @@
+--
+-- contrib/sepgsql/sepgsql.sql
+--
+-- [Step to install]
+--
+-- 1. Run initdb
+-- to set up a new database cluster.
+--
+-- 2. Edit $PGDATA/postgresql.conf
+-- to add 'MODULE_PATHNAME' to shared_preload_libraries.
+--
+-- Example)
+-- shared_preload_libraries = 'MODULE_PATHNAME'
+--
+-- 3. Run this script for each databases
+-- This script installs corresponding functions, and assigns initial
+-- security labels on target database objects.
+-- It can be run both single-user mode and multi-user mode, according
+-- to your preference.
+--
+-- Example)
+-- $ for DBNAME in template0 template1 postgres; \
+-- do \
+-- postgres --single -F -c exit_on_error=true -D $PGDATA $DBNAME \
+-- < /path/to/script/sepgsql.sql > /dev/null \
+-- done
+--
+-- 4. Start postmaster,
+-- if you initialized the database in single-user mode.
+--
+LOAD 'MODULE_PATHNAME';
+CREATE OR REPLACE FUNCTION pg_catalog.sepgsql_getcon() RETURNS text AS 'MODULE_PATHNAME', 'sepgsql_getcon' LANGUAGE C;
+CREATE OR REPLACE FUNCTION pg_catalog.sepgsql_mcstrans_in(text) RETURNS text AS 'MODULE_PATHNAME', 'sepgsql_mcstrans_in' LANGUAGE C STRICT;
+CREATE OR REPLACE FUNCTION pg_catalog.sepgsql_mcstrans_out(text) RETURNS text AS 'MODULE_PATHNAME', 'sepgsql_mcstrans_out' LANGUAGE C STRICT;
+CREATE OR REPLACE FUNCTION pg_catalog.sepgsql_restorecon(text) RETURNS bool AS 'MODULE_PATHNAME', 'sepgsql_restorecon' LANGUAGE C;
+SELECT sepgsql_restorecon(NULL);
diff --git a/contrib/sepgsql/sql/dml.sql b/contrib/sepgsql/sql/dml.sql
new file mode 100644
index 0000000000..94bf31a97a
--- /dev/null
+++ b/contrib/sepgsql/sql/dml.sql
@@ -0,0 +1,119 @@
+--
+-- Regression Test for DML Permissions
+--
+
+--
+-- Setup
+--
+CREATE TABLE t1 (a int, b text);
+SECURITY LABEL ON TABLE t1 IS 'system_u:object_r:sepgsql_table_t:s0';
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+
+CREATE TABLE t2 (x int, y text);
+SECURITY LABEL ON TABLE t2 IS 'system_u:object_r:sepgsql_ro_table_t:s0';
+INSERT INTO t2 VALUES (1, 'xxx'), (2, 'yyy'), (3, 'zzz');
+
+CREATE TABLE t3 (s int, t text);
+SECURITY LABEL ON TABLE t3 IS 'system_u:object_r:sepgsql_fixed_table_t:s0';
+INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu');
+
+CREATE TABLE t4 (m int, n text);
+SECURITY LABEL ON TABLE t4 IS 'system_u:object_r:sepgsql_secret_table_t:s0';
+INSERT INTO t4 VALUES (1, 'mmm'), (2, 'nnn'), (3, 'ooo');
+
+CREATE TABLE t5 (e text, f text, g text);
+SECURITY LABEL ON TABLE t5 IS 'system_u:object_r:sepgsql_table_t:s0';
+SECURITY LABEL ON COLUMN t5.e IS 'system_u:object_r:sepgsql_table_t:s0';
+SECURITY LABEL ON COLUMN t5.f IS 'system_u:object_r:sepgsql_ro_table_t:s0';
+SECURITY LABEL ON COLUMN t5.g IS 'system_u:object_r:sepgsql_secret_table_t:s0';
+
+CREATE TABLE customer (cid int primary key, cname text, ccredit text);
+SECURITY LABEL ON COLUMN customer.ccredit IS 'system_u:object_r:sepgsql_secret_table_t:s0';
+INSERT INTO customer VALUES (1, 'Taro', '1111-2222-3333-4444'),
+ (2, 'Hanako', '5555-6666-7777-8888');
+CREATE FUNCTION customer_credit(int) RETURNS text
+ AS 'SELECT regexp_replace(ccredit, ''-[0-9]+$'', ''-????'') FROM customer WHERE cid = $1'
+ LANGUAGE sql;
+SECURITY LABEL ON FUNCTION customer_credit(int)
+ IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
+
+SELECT objtype, objname, label FROM pg_seclabels
+ WHERE provider = 'selinux'
+ AND objtype in ('table', 'column')
+ AND objname in ('t1', 't2', 't3', 't4', 't5', 't5.e', 't5.f', 't5.g')
+ORDER BY objname;
+
+-- Hardwired Rules
+UPDATE pg_attribute SET attisdropped = true
+ WHERE attrelid = 't5'::regclass AND attname = 'f'; -- failed
+
+--
+-- Simple DML statements
+--
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+
+SELECT * FROM t1; -- ok
+SELECT * FROM t2; -- ok
+SELECT * FROM t3; -- ok
+SELECT * FROM t4; -- failed
+SELECT * FROM t5; -- failed
+SELECT e,f FROM t5; -- ok
+
+SELECT * FROM customer; -- failed
+SELECT cid, cname, customer_credit(cid) FROM customer; -- ok
+
+SELECT count(*) FROM t5; -- ok
+SELECT count(*) FROM t5 WHERE g IS NULL; -- failed
+
+INSERT INTO t1 VALUES (4, 'abc'); -- ok
+INSERT INTO t2 VALUES (4, 'xyz'); -- failed
+INSERT INTO t3 VALUES (4, 'stu'); -- ok
+INSERT INTO t4 VALUES (4, 'mno'); -- failed
+INSERT INTO t5 VALUES (1,2,3); -- failed
+INSERT INTO t5 (e,f) VALUES ('abc', 'def'); -- failed
+INSERT INTO t5 (e) VALUES ('abc'); -- ok
+
+UPDATE t1 SET b = b || '_upd'; -- ok
+UPDATE t2 SET y = y || '_upd'; -- failed
+UPDATE t3 SET t = t || '_upd'; -- failed
+UPDATE t4 SET n = n || '_upd'; -- failed
+UPDATE t5 SET e = 'xyz'; -- ok
+UPDATE t5 SET e = f || '_upd'; -- ok
+UPDATE t5 SET e = g || '_upd'; -- failed
+
+DELETE FROM t1; -- ok
+DELETE FROM t2; -- failed
+DELETE FROM t3; -- failed
+DELETE FROM t4; -- failed
+DELETE FROM t5; -- ok
+DELETE FROM t5 WHERE f IS NULL; -- ok
+DELETE FROM t5 WHERE g IS NULL; -- failed
+
+--
+-- COPY TO/FROM statements
+--
+COPY t1 TO '/dev/null'; -- ok
+COPY t2 TO '/dev/null'; -- ok
+COPY t3 TO '/dev/null'; -- ok
+COPY t4 TO '/dev/null'; -- failed
+COPY t5 TO '/dev/null'; -- failed
+COPY t5(e,f) TO '/dev/null'; -- ok
+
+COPY t1 FROM '/dev/null'; -- ok
+COPY t2 FROM '/dev/null'; -- failed
+COPY t3 FROM '/dev/null'; -- ok
+COPY t4 FROM '/dev/null'; -- failed
+COPY t5 FROM '/dev/null'; -- failed
+COPY t5 (e,f) FROM '/dev/null'; -- failed
+COPY t5 (e) FROM '/dev/null'; -- ok
+
+--
+-- Clean up
+--
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c255
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE IF EXISTS t5 CASCADE;
+DROP TABLE IF EXISTS customer CASCADE;
diff --git a/contrib/sepgsql/sql/label.sql b/contrib/sepgsql/sql/label.sql
new file mode 100644
index 0000000000..2b1841281c
--- /dev/null
+++ b/contrib/sepgsql/sql/label.sql
@@ -0,0 +1,81 @@
+--
+-- Regression Tests for Label Management
+--
+
+--
+-- Setup
+--
+CREATE TABLE t1 (a int, b text);
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+SELECT * INTO t2 FROM t1 WHERE a % 2 = 0;
+
+CREATE FUNCTION f1 () RETURNS text
+ AS 'SELECT sepgsql_getcon()'
+ LANGUAGE sql;
+
+CREATE FUNCTION f2 () RETURNS text
+ AS 'SELECT sepgsql_getcon()'
+ LANGUAGE sql;
+SECURITY LABEL ON FUNCTION f2()
+ IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
+
+CREATE FUNCTION f3 () RETURNS text
+ AS 'BEGIN
+ RAISE EXCEPTION ''an exception from f3()'';
+ RETURN NULL;
+ END;' LANGUAGE plpgsql;
+SECURITY LABEL ON FUNCTION f3()
+ IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
+
+CREATE FUNCTION f4 () RETURNS text
+ AS 'SELECT sepgsql_getcon()'
+ LANGUAGE sql;
+SECURITY LABEL ON FUNCTION f4()
+ IS 'system_u:object_r:sepgsql_regtest_trusted_proc_exec_t:s0';
+
+--
+-- Tests for default labeling behavior
+--
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+CREATE TABLE t3 (s int, t text);
+INSERT INTO t3 VALUES (1, 'sss'), (2, 'ttt'), (3, 'uuu');
+
+SELECT objtype, objname, label FROM pg_seclabels
+ WHERE provider = 'selinux'
+ AND objtype in ('table', 'column')
+ AND objname in ('t1', 't2', 't3');
+
+--
+-- Tests for SECURITY LABEL
+--
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:sepgsql_regtest_dba_t:s0
+SECURITY LABEL ON TABLE t1
+ IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok
+SECURITY LABEL ON TABLE t2
+ IS 'invalid security context'; -- be failed
+SECURITY LABEL ON COLUMN t2
+ IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- be failed
+SECURITY LABEL ON COLUMN t2.b
+ IS 'system_u:object_r:sepgsql_ro_table_t:s0'; -- ok
+
+--
+-- Tests for Trusted Procedures
+--
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:sepgsql_regtest_user_t:s0
+SELECT f1(); -- normal procedure
+SELECT f2(); -- trusted procedure
+SELECT f3(); -- trusted procedure that raises an error
+SELECT f4(); -- failed on domain transition
+SELECT sepgsql_getcon(); -- client's label must be restored
+
+--
+-- Clean up
+--
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c255
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP FUNCTION IF EXISTS f1() CASCADE;
+DROP FUNCTION IF EXISTS f2() CASCADE;
+DROP FUNCTION IF EXISTS f3() CASCADE;
+DROP FUNCTION IF EXISTS f4() CASCADE;
diff --git a/contrib/sepgsql/sql/misc.sql b/contrib/sepgsql/sql/misc.sql
new file mode 100644
index 0000000000..a46d8a6b5c
--- /dev/null
+++ b/contrib/sepgsql/sql/misc.sql
@@ -0,0 +1,5 @@
+--
+-- Regression Test for Misc Permission Checks
+--
+
+LOAD '$libdir/sepgsql'; -- failed
diff --git a/contrib/spi/Makefile b/contrib/spi/Makefile
index 7a078a9b0e..0c11bfcbbd 100644
--- a/contrib/spi/Makefile
+++ b/contrib/spi/Makefile
@@ -1,7 +1,15 @@
-# $PostgreSQL: pgsql/contrib/spi/Makefile,v 1.29 2010/07/05 23:15:56 tgl Exp $
+# contrib/spi/Makefile
MODULES = autoinc insert_username moddatetime refint timetravel
-DATA_built = $(addsuffix .sql, $(MODULES))
+
+EXTENSION = autoinc insert_username moddatetime refint timetravel
+
+DATA = autoinc--1.0.sql autoinc--unpackaged--1.0.sql \
+ insert_username--1.0.sql insert_username--unpackaged--1.0.sql \
+ moddatetime--1.0.sql moddatetime--unpackaged--1.0.sql \
+ refint--1.0.sql refint--unpackaged--1.0.sql \
+ timetravel--1.0.sql timetravel--unpackaged--1.0.sql
+
DOCS = $(addsuffix .example, $(MODULES))
# this is needed for the regression tests;
diff --git a/contrib/spi/autoinc--1.0.sql b/contrib/spi/autoinc--1.0.sql
new file mode 100644
index 0000000000..9c9df9ce0b
--- /dev/null
+++ b/contrib/spi/autoinc--1.0.sql
@@ -0,0 +1,6 @@
+/* contrib/spi/autoinc--1.0.sql */
+
+CREATE FUNCTION autoinc()
+RETURNS trigger
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
diff --git a/contrib/spi/autoinc--unpackaged--1.0.sql b/contrib/spi/autoinc--unpackaged--1.0.sql
new file mode 100644
index 0000000000..232e9170fc
--- /dev/null
+++ b/contrib/spi/autoinc--unpackaged--1.0.sql
@@ -0,0 +1,3 @@
+/* contrib/spi/autoinc--unpackaged--1.0.sql */
+
+ALTER EXTENSION autoinc ADD function autoinc();
diff --git a/contrib/spi/autoinc.c b/contrib/spi/autoinc.c
index f79317a1b1..9b38493a33 100644
--- a/contrib/spi/autoinc.c
+++ b/contrib/spi/autoinc.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/spi/autoinc.c,v 1.17 2009/06/11 14:48:52 momjian Exp $
+ * contrib/spi/autoinc.c
*/
#include "postgres.h"
@@ -35,10 +35,10 @@ autoinc(PG_FUNCTION_ARGS)
if (!CALLED_AS_TRIGGER(fcinfo))
/* internal error */
elog(ERROR, "not fired by trigger manager");
- if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+ if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
/* internal error */
- elog(ERROR, "cannot process STATEMENT events");
- if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
+ elog(ERROR, "must be fired for row");
+ if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
/* internal error */
elog(ERROR, "must be fired before event");
diff --git a/contrib/spi/autoinc.control b/contrib/spi/autoinc.control
new file mode 100644
index 0000000000..1d7a8e53d4
--- /dev/null
+++ b/contrib/spi/autoinc.control
@@ -0,0 +1,5 @@
+# autoinc extension
+comment = 'functions for autoincrementing fields'
+default_version = '1.0'
+module_pathname = '$libdir/autoinc'
+relocatable = true
diff --git a/contrib/spi/autoinc.example b/contrib/spi/autoinc.example
index a2f470dc2d..08880ce5fa 100644
--- a/contrib/spi/autoinc.example
+++ b/contrib/spi/autoinc.example
@@ -8,9 +8,9 @@ CREATE TABLE ids (
idesc text
);
-CREATE TRIGGER ids_nextid
+CREATE TRIGGER ids_nextid
BEFORE INSERT OR UPDATE ON ids
- FOR EACH ROW
+ FOR EACH ROW
EXECUTE PROCEDURE autoinc (id, next_id);
INSERT INTO ids VALUES (0, 'first (-2 ?)');
@@ -19,11 +19,11 @@ INSERT INTO ids(idesc) VALUES ('third (1 ?!)');
SELECT * FROM ids;
-UPDATE ids SET id = null, idesc = 'first: -2 --> 2'
+UPDATE ids SET id = null, idesc = 'first: -2 --> 2'
WHERE idesc = 'first (-2 ?)';
-UPDATE ids SET id = 0, idesc = 'second: -1 --> 3'
+UPDATE ids SET id = 0, idesc = 'second: -1 --> 3'
WHERE id = -1;
-UPDATE ids SET id = 4, idesc = 'third: 1 --> 4'
+UPDATE ids SET id = 4, idesc = 'third: 1 --> 4'
WHERE id = 1;
SELECT * FROM ids;
diff --git a/contrib/spi/autoinc.sql.in b/contrib/spi/autoinc.sql.in
deleted file mode 100644
index 5daed21140..0000000000
--- a/contrib/spi/autoinc.sql.in
+++ /dev/null
@@ -1,9 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/spi/autoinc.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION autoinc()
-RETURNS trigger
-AS 'MODULE_PATHNAME'
-LANGUAGE C;
diff --git a/contrib/spi/insert_username--1.0.sql b/contrib/spi/insert_username--1.0.sql
new file mode 100644
index 0000000000..bd854587e0
--- /dev/null
+++ b/contrib/spi/insert_username--1.0.sql
@@ -0,0 +1,6 @@
+/* contrib/spi/insert_username--1.0.sql */
+
+CREATE FUNCTION insert_username()
+RETURNS trigger
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
diff --git a/contrib/spi/insert_username--unpackaged--1.0.sql b/contrib/spi/insert_username--unpackaged--1.0.sql
new file mode 100644
index 0000000000..f53cb690f1
--- /dev/null
+++ b/contrib/spi/insert_username--unpackaged--1.0.sql
@@ -0,0 +1,3 @@
+/* contrib/spi/insert_username--unpackaged--1.0.sql */
+
+ALTER EXTENSION insert_username ADD function insert_username();
diff --git a/contrib/spi/insert_username.c b/contrib/spi/insert_username.c
index 377284a613..18a13344cf 100644
--- a/contrib/spi/insert_username.c
+++ b/contrib/spi/insert_username.c
@@ -1,7 +1,7 @@
/*
* insert_username.c
* $Modified: Thu Oct 16 08:13:42 1997 by brook $
- * $PostgreSQL: pgsql/contrib/spi/insert_username.c,v 1.17 2009/01/07 13:44:36 tgl Exp $
+ * contrib/spi/insert_username.c
*
* insert user name in response to a trigger
* usage: insert_username (column_name)
@@ -38,10 +38,10 @@ insert_username(PG_FUNCTION_ARGS)
if (!CALLED_AS_TRIGGER(fcinfo))
/* internal error */
elog(ERROR, "insert_username: not fired by trigger manager");
- if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+ if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
/* internal error */
- elog(ERROR, "insert_username: cannot process STATEMENT events");
- if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
+ elog(ERROR, "insert_username: must be fired for row");
+ if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
/* internal error */
elog(ERROR, "insert_username: must be fired before event");
diff --git a/contrib/spi/insert_username.control b/contrib/spi/insert_username.control
new file mode 100644
index 0000000000..9d110643ee
--- /dev/null
+++ b/contrib/spi/insert_username.control
@@ -0,0 +1,5 @@
+# insert_username extension
+comment = 'functions for tracking who changed a table'
+default_version = '1.0'
+module_pathname = '$libdir/insert_username'
+relocatable = true
diff --git a/contrib/spi/insert_username.example b/contrib/spi/insert_username.example
index 41e69bcbf2..2c1eeb0e0d 100644
--- a/contrib/spi/insert_username.example
+++ b/contrib/spi/insert_username.example
@@ -7,7 +7,7 @@ CREATE TABLE username_test (
CREATE TRIGGER insert_usernames
BEFORE INSERT OR UPDATE ON username_test
- FOR EACH ROW
+ FOR EACH ROW
EXECUTE PROCEDURE insert_username (username);
INSERT INTO username_test VALUES ('nothing');
@@ -18,4 +18,3 @@ INSERT INTO username_test VALUES ('tab', ' ');
INSERT INTO username_test VALUES ('name', 'name');
SELECT * FROM username_test;
-
diff --git a/contrib/spi/insert_username.sql.in b/contrib/spi/insert_username.sql.in
deleted file mode 100644
index 4d73d9b546..0000000000
--- a/contrib/spi/insert_username.sql.in
+++ /dev/null
@@ -1,9 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/spi/insert_username.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION insert_username()
-RETURNS trigger
-AS 'MODULE_PATHNAME'
-LANGUAGE C;
diff --git a/contrib/spi/moddatetime--1.0.sql b/contrib/spi/moddatetime--1.0.sql
new file mode 100644
index 0000000000..97cc63289f
--- /dev/null
+++ b/contrib/spi/moddatetime--1.0.sql
@@ -0,0 +1,6 @@
+/* contrib/spi/moddatetime--1.0.sql */
+
+CREATE FUNCTION moddatetime()
+RETURNS trigger
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
diff --git a/contrib/spi/moddatetime--unpackaged--1.0.sql b/contrib/spi/moddatetime--unpackaged--1.0.sql
new file mode 100644
index 0000000000..f3a0a96837
--- /dev/null
+++ b/contrib/spi/moddatetime--unpackaged--1.0.sql
@@ -0,0 +1,3 @@
+/* contrib/spi/moddatetime--unpackaged--1.0.sql */
+
+ALTER EXTENSION moddatetime ADD function moddatetime();
diff --git a/contrib/spi/moddatetime.c b/contrib/spi/moddatetime.c
index 0b4d3ba351..d02560c298 100644
--- a/contrib/spi/moddatetime.c
+++ b/contrib/spi/moddatetime.c
@@ -1,7 +1,7 @@
/*
moddatetime.c
-$PostgreSQL: pgsql/contrib/spi/moddatetime.c,v 1.15 2009/01/07 13:44:36 tgl Exp $
+contrib/spi/moddatetime.c
What is this?
It is a function to be called from a trigger for the purpose of updating
@@ -32,6 +32,7 @@ moddatetime(PG_FUNCTION_ARGS)
Trigger *trigger; /* to get trigger name */
int nargs; /* # of arguments */
int attnum; /* positional number of field to change */
+ Oid atttypid; /* type OID of field to change */
Datum newdt; /* The current datetime. */
char **args; /* arguments */
char *relname; /* triggered relation name */
@@ -43,17 +44,17 @@ moddatetime(PG_FUNCTION_ARGS)
/* internal error */
elog(ERROR, "moddatetime: not fired by trigger manager");
- if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+ if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
/* internal error */
- elog(ERROR, "moddatetime: cannot process STATEMENT events");
+ elog(ERROR, "moddatetime: must be fired for row");
- if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
+ if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
/* internal error */
elog(ERROR, "moddatetime: must be fired before event");
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
/* internal error */
- elog(ERROR, "moddatetime: must be fired before event");
+ elog(ERROR, "moddatetime: cannot process INSERT events");
else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
rettuple = trigdata->tg_newtuple;
else
@@ -75,12 +76,6 @@ moddatetime(PG_FUNCTION_ARGS)
/* must be the field layout? */
tupdesc = rel->rd_att;
- /* Get the current datetime. */
- newdt = DirectFunctionCall3(timestamp_in,
- CStringGetDatum("now"),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1));
-
/*
* This gets the position in the tuple of the field we want. args[0] being
* the name of the field to update, as passed in from the trigger.
@@ -88,8 +83,8 @@ moddatetime(PG_FUNCTION_ARGS)
attnum = SPI_fnumber(tupdesc, args[0]);
/*
- * This is were we check to see if the field we are supposed to update
- * even exits. The above function must return -1 if name not found?
+ * This is where we check to see if the field we are supposed to update
+ * even exists. The above function must return -1 if name not found?
*/
if (attnum < 0)
ereport(ERROR,
@@ -98,20 +93,33 @@ moddatetime(PG_FUNCTION_ARGS)
relname, args[0])));
/*
- * OK, this is where we make sure the timestamp field that we are
- * modifying is really a timestamp field. Hay, error checking, what a
- * novel idea !-)
+ * Check the target field has an allowed type, and get the current
+ * datetime as a value of that type.
*/
- if (SPI_gettypeid(tupdesc, attnum) != TIMESTAMPOID)
+ atttypid = SPI_gettypeid(tupdesc, attnum);
+ if (atttypid == TIMESTAMPOID)
+ newdt = DirectFunctionCall3(timestamp_in,
+ CStringGetDatum("now"),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1));
+ else if (atttypid == TIMESTAMPTZOID)
+ newdt = DirectFunctionCall3(timestamptz_in,
+ CStringGetDatum("now"),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1));
+ else
+ {
ereport(ERROR,
(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
- errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP",
+ errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP or TIMESTAMPTZ",
args[0], relname)));
+ newdt = (Datum) 0; /* keep compiler quiet */
+ }
/* 1 is the number of items in the arrays attnum and newdt.
attnum is the positional number of the field to be updated.
newdt is the new datetime stamp.
- NOTE that attnum and newdt are not arrays, but then a 1 ellement array
+ NOTE that attnum and newdt are not arrays, but then a 1 element array
is not an array any more then they are. Thus, they can be considered a
one element array.
*/
diff --git a/contrib/spi/moddatetime.control b/contrib/spi/moddatetime.control
new file mode 100644
index 0000000000..93dfac589a
--- /dev/null
+++ b/contrib/spi/moddatetime.control
@@ -0,0 +1,5 @@
+# moddatetime extension
+comment = 'functions for tracking last modification time'
+default_version = '1.0'
+module_pathname = '$libdir/moddatetime'
+relocatable = true
diff --git a/contrib/spi/moddatetime.example b/contrib/spi/moddatetime.example
index e4a713c12a..65af388214 100644
--- a/contrib/spi/moddatetime.example
+++ b/contrib/spi/moddatetime.example
@@ -8,7 +8,7 @@ CREATE TABLE mdt (
CREATE TRIGGER mdt_moddatetime
BEFORE UPDATE ON mdt
- FOR EACH ROW
+ FOR EACH ROW
EXECUTE PROCEDURE moddatetime (moddate);
INSERT INTO mdt VALUES (1, 'first');
diff --git a/contrib/spi/moddatetime.sql.in b/contrib/spi/moddatetime.sql.in
deleted file mode 100644
index 793c703ac0..0000000000
--- a/contrib/spi/moddatetime.sql.in
+++ /dev/null
@@ -1,9 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/spi/moddatetime.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION moddatetime()
-RETURNS trigger
-AS 'MODULE_PATHNAME'
-LANGUAGE C;
diff --git a/contrib/spi/refint--1.0.sql b/contrib/spi/refint--1.0.sql
new file mode 100644
index 0000000000..9e5d931df5
--- /dev/null
+++ b/contrib/spi/refint--1.0.sql
@@ -0,0 +1,11 @@
+/* contrib/spi/refint--1.0.sql */
+
+CREATE FUNCTION check_primary_key()
+RETURNS trigger
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+CREATE FUNCTION check_foreign_key()
+RETURNS trigger
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
diff --git a/contrib/spi/refint--unpackaged--1.0.sql b/contrib/spi/refint--unpackaged--1.0.sql
new file mode 100644
index 0000000000..54fece055a
--- /dev/null
+++ b/contrib/spi/refint--unpackaged--1.0.sql
@@ -0,0 +1,4 @@
+/* contrib/spi/refint--unpackaged--1.0.sql */
+
+ALTER EXTENSION refint ADD function check_primary_key();
+ALTER EXTENSION refint ADD function check_foreign_key();
diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c
index 5a446c3709..36f9ee421e 100644
--- a/contrib/spi/refint.c
+++ b/contrib/spi/refint.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/spi/refint.c,v 1.35 2009/06/11 14:48:52 momjian Exp $
+ * contrib/spi/refint.c
*
*
* refint.c -- set of functions to define referential integrity
@@ -79,9 +79,9 @@ check_primary_key(PG_FUNCTION_ARGS)
elog(ERROR, "check_primary_key: not fired by trigger manager");
/* Should be called for ROW trigger */
- if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+ if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
/* internal error */
- elog(ERROR, "check_primary_key: cannot process STATEMENT events");
+ elog(ERROR, "check_primary_key: must be fired for row");
/* If INSERTion then must check Tuple to being inserted */
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
@@ -279,9 +279,9 @@ check_foreign_key(PG_FUNCTION_ARGS)
elog(ERROR, "check_foreign_key: not fired by trigger manager");
/* Should be called for ROW trigger */
- if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+ if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
/* internal error */
- elog(ERROR, "check_foreign_key: cannot process STATEMENT events");
+ elog(ERROR, "check_foreign_key: must be fired for row");
/* Not should be called for INSERT */
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
diff --git a/contrib/spi/refint.control b/contrib/spi/refint.control
new file mode 100644
index 0000000000..cbede45784
--- /dev/null
+++ b/contrib/spi/refint.control
@@ -0,0 +1,5 @@
+# refint extension
+comment = 'functions for implementing referential integrity (obsolete)'
+default_version = '1.0'
+module_pathname = '$libdir/refint'
+relocatable = true
diff --git a/contrib/spi/refint.example b/contrib/spi/refint.example
index 1300e81654..d0ff744164 100644
--- a/contrib/spi/refint.example
+++ b/contrib/spi/refint.example
@@ -20,11 +20,11 @@ CREATE INDEX CI ON C (REFC);
--Trigger for table A:
CREATE TRIGGER AT BEFORE DELETE OR UPDATE ON A FOR EACH ROW
-EXECUTE PROCEDURE
+EXECUTE PROCEDURE
check_foreign_key (2, 'cascade', 'ID', 'B', 'REFB', 'C', 'REFC');
/*
2 - means that check must be performed for foreign keys of 2 tables.
-cascade - defines that corresponding keys must be deleted.
+cascade - defines that corresponding keys must be deleted.
ID - name of primary key column in triggered table (A). You may
use as many columns as you need.
B - name of (first) table with foreign keys.
@@ -38,11 +38,11 @@ REFC - name of foreign key column in this table.
--Trigger for table B:
CREATE TRIGGER BT BEFORE INSERT OR UPDATE ON B FOR EACH ROW
-EXECUTE PROCEDURE
+EXECUTE PROCEDURE
check_primary_key ('REFB', 'A', 'ID');
/*
-REFB - name of foreign key column in triggered (B) table. You may use as
+REFB - name of foreign key column in triggered (B) table. You may use as
many columns as you need, but number of key columns in referenced
table must be the same.
A - referenced table name.
@@ -52,7 +52,7 @@ ID - name of primary key column in referenced table.
--Trigger for table C:
CREATE TRIGGER CT BEFORE INSERT OR UPDATE ON C FOR EACH ROW
-EXECUTE PROCEDURE
+EXECUTE PROCEDURE
check_primary_key ('REFC', 'A', 'ID');
-- Now try
diff --git a/contrib/spi/refint.sql.in b/contrib/spi/refint.sql.in
deleted file mode 100644
index 08ee7f98cf..0000000000
--- a/contrib/spi/refint.sql.in
+++ /dev/null
@@ -1,14 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/spi/refint.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION check_primary_key()
-RETURNS trigger
-AS 'MODULE_PATHNAME'
-LANGUAGE C;
-
-CREATE OR REPLACE FUNCTION check_foreign_key()
-RETURNS trigger
-AS 'MODULE_PATHNAME'
-LANGUAGE C;
diff --git a/contrib/spi/timetravel--1.0.sql b/contrib/spi/timetravel--1.0.sql
new file mode 100644
index 0000000000..b68cf2f247
--- /dev/null
+++ b/contrib/spi/timetravel--1.0.sql
@@ -0,0 +1,16 @@
+/* contrib/spi/timetravel--1.0.sql */
+
+CREATE FUNCTION timetravel()
+RETURNS trigger
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+CREATE FUNCTION set_timetravel(name, int4)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C RETURNS NULL ON NULL INPUT;
+
+CREATE FUNCTION get_timetravel(name)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C RETURNS NULL ON NULL INPUT;
diff --git a/contrib/spi/timetravel--unpackaged--1.0.sql b/contrib/spi/timetravel--unpackaged--1.0.sql
new file mode 100644
index 0000000000..e3716afe95
--- /dev/null
+++ b/contrib/spi/timetravel--unpackaged--1.0.sql
@@ -0,0 +1,5 @@
+/* contrib/spi/timetravel--unpackaged--1.0.sql */
+
+ALTER EXTENSION timetravel ADD function timetravel();
+ALTER EXTENSION timetravel ADD function set_timetravel(name,integer);
+ALTER EXTENSION timetravel ADD function get_timetravel(name);
diff --git a/contrib/spi/timetravel.c b/contrib/spi/timetravel.c
index 577767d81f..3d05cc505c 100644
--- a/contrib/spi/timetravel.c
+++ b/contrib/spi/timetravel.c
@@ -1,11 +1,11 @@
/*
- * $PostgreSQL: pgsql/contrib/spi/timetravel.c,v 1.31 2009/06/11 14:48:52 momjian Exp $
+ * contrib/spi/timetravel.c
*
*
* timetravel.c -- function to get time travel feature
* using general triggers.
*
- * Modified by BÖJTHE Zoltán, Hungary, mailto:urdesobt@axelero.hu
+ * Modified by BÖJTHE Zoltán, Hungary, mailto:urdesobt@axelero.hu
*/
#include "postgres.h"
@@ -118,11 +118,11 @@ timetravel(PG_FUNCTION_ARGS)
elog(ERROR, "timetravel: not fired by trigger manager");
/* Should be called for ROW trigger */
- if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
- elog(ERROR, "timetravel: cannot process STATEMENT events");
+ if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
+ elog(ERROR, "timetravel: must be fired for row");
/* Should be called BEFORE */
- if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
+ if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event))
elog(ERROR, "timetravel: must be fired before event");
/* INSERT ? */
diff --git a/contrib/spi/timetravel.control b/contrib/spi/timetravel.control
new file mode 100644
index 0000000000..9b4bb6ba04
--- /dev/null
+++ b/contrib/spi/timetravel.control
@@ -0,0 +1,5 @@
+# timetravel extension
+comment = 'functions for implementing time travel'
+default_version = '1.0'
+module_pathname = '$libdir/timetravel'
+relocatable = true
diff --git a/contrib/spi/timetravel.example b/contrib/spi/timetravel.example
index 1769e48154..35a7f65408 100644
--- a/contrib/spi/timetravel.example
+++ b/contrib/spi/timetravel.example
@@ -1,8 +1,8 @@
drop table tttest;
create table tttest (
- price_id int4,
- price_val int4,
+ price_id int4,
+ price_val int4,
price_on abstime,
price_off abstime
);
@@ -12,17 +12,17 @@ alter table tttest add column q1 text;
alter table tttest add column q2 int;
alter table tttest drop column q1;
-create trigger timetravel
+create trigger timetravel
before insert or delete or update on tttest
- for each row
- execute procedure
+ for each row
+ execute procedure
timetravel (price_on, price_off);
insert into tttest values (1, 1, null, null);
insert into tttest(price_id, price_val) values (2, 2);
insert into tttest(price_id, price_val,price_off) values (3, 3, 'infinity');
-insert into tttest(price_id, price_val,price_off) values (4, 4,
+insert into tttest(price_id, price_val,price_off) values (4, 4,
abstime('now'::timestamp - '100 days'::interval));
insert into tttest(price_id, price_val,price_on) values (3, 3, 'infinity'); -- duplicate key
@@ -62,7 +62,7 @@ select set_timetravel('tttest', 1); -- turn TT ON!
select get_timetravel('tttest'); -- check status
-- we want to correct some date
-update tttest set price_on = 'Jan-01-1990 00:00:01' where price_id = 5 and
+update tttest set price_on = 'Jan-01-1990 00:00:01' where price_id = 5 and
price_off <> 'infinity';
-- but this doesn't work
@@ -71,11 +71,11 @@ select set_timetravel('tttest', 0); -- turn TT OFF!
select get_timetravel('tttest'); -- check status
-update tttest set price_on = '01-Jan-1990 00:00:01' where price_id = 5 and
+update tttest set price_on = '01-Jan-1990 00:00:01' where price_id = 5 and
price_off <> 'infinity';
select * from tttest;
-- isn't it what we need ?
-- get price for price_id == 5 as it was '10-Jan-1990'
-select * from tttest where price_id = 5 and
+select * from tttest where price_id = 5 and
price_on <= '10-Jan-1990' and price_off > '10-Jan-1990';
diff --git a/contrib/spi/timetravel.sql.in b/contrib/spi/timetravel.sql.in
deleted file mode 100644
index a78b1d52cf..0000000000
--- a/contrib/spi/timetravel.sql.in
+++ /dev/null
@@ -1,19 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/spi/timetravel.sql.in,v 1.8 2007/11/13 04:24:28 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION timetravel()
-RETURNS trigger
-AS 'MODULE_PATHNAME'
-LANGUAGE C;
-
-CREATE OR REPLACE FUNCTION set_timetravel(name, int4)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C RETURNS NULL ON NULL INPUT;
-
-CREATE OR REPLACE FUNCTION get_timetravel(name)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C RETURNS NULL ON NULL INPUT;
diff --git a/contrib/sslinfo/Makefile b/contrib/sslinfo/Makefile
index 722eacd349..0dee6ed2f7 100644
--- a/contrib/sslinfo/Makefile
+++ b/contrib/sslinfo/Makefile
@@ -1,9 +1,10 @@
-# $PostgreSQL: pgsql/contrib/sslinfo/Makefile,v 1.10 2007/11/10 23:59:51 momjian Exp $
+# contrib/sslinfo/Makefile
MODULE_big = sslinfo
OBJS = sslinfo.o
-DATA_built = sslinfo.sql
-DATA = uninstall_sslinfo.sql
+
+EXTENSION = sslinfo
+DATA = sslinfo--1.0.sql sslinfo--unpackaged--1.0.sql
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/sslinfo/sslinfo--1.0.sql b/contrib/sslinfo/sslinfo--1.0.sql
new file mode 100644
index 0000000000..ef745a0a2e
--- /dev/null
+++ b/contrib/sslinfo/sslinfo--1.0.sql
@@ -0,0 +1,37 @@
+/* contrib/sslinfo/sslinfo--1.0.sql */
+
+CREATE FUNCTION ssl_client_serial() RETURNS numeric
+AS 'MODULE_PATHNAME', 'ssl_client_serial'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_is_used() RETURNS boolean
+AS 'MODULE_PATHNAME', 'ssl_is_used'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_version() RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_version'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_cipher() RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_cipher'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_client_cert_present() RETURNS boolean
+AS 'MODULE_PATHNAME', 'ssl_client_cert_present'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_client_dn_field(text) RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_client_dn_field'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_issuer_field(text) RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_issuer_field'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_client_dn() RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_client_dn'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_issuer_dn() RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_issuer_dn'
+LANGUAGE C STRICT;
diff --git a/contrib/sslinfo/sslinfo--unpackaged--1.0.sql b/contrib/sslinfo/sslinfo--unpackaged--1.0.sql
new file mode 100644
index 0000000000..befa96e908
--- /dev/null
+++ b/contrib/sslinfo/sslinfo--unpackaged--1.0.sql
@@ -0,0 +1,19 @@
+/* contrib/sslinfo/sslinfo--unpackaged--1.0.sql */
+
+ALTER EXTENSION sslinfo ADD function ssl_client_serial();
+ALTER EXTENSION sslinfo ADD function ssl_is_used();
+ALTER EXTENSION sslinfo ADD function ssl_client_cert_present();
+ALTER EXTENSION sslinfo ADD function ssl_client_dn_field(text);
+ALTER EXTENSION sslinfo ADD function ssl_issuer_field(text);
+ALTER EXTENSION sslinfo ADD function ssl_client_dn();
+ALTER EXTENSION sslinfo ADD function ssl_issuer_dn();
+
+-- These functions were not in 9.0:
+
+CREATE FUNCTION ssl_version() RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_version'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION ssl_cipher() RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_cipher'
+LANGUAGE C STRICT;
diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c
index a8145653c0..b5fd7ec987 100644
--- a/contrib/sslinfo/sslinfo.c
+++ b/contrib/sslinfo/sslinfo.c
@@ -4,7 +4,7 @@
* Written by Victor B. Wagner <vitus@cryptocom.ru>, Cryptocom LTD
* This file is distributed under BSD-style license.
*
- * $PostgreSQL: pgsql/contrib/sslinfo/sslinfo.c,v 1.8 2008/11/10 14:57:38 tgl Exp $
+ * contrib/sslinfo/sslinfo.c
*/
#include "postgres.h"
@@ -23,6 +23,8 @@ PG_MODULE_MAGIC;
Datum ssl_is_used(PG_FUNCTION_ARGS);
+Datum ssl_version(PG_FUNCTION_ARGS);
+Datum ssl_cipher(PG_FUNCTION_ARGS);
Datum ssl_client_cert_present(PG_FUNCTION_ARGS);
Datum ssl_client_serial(PG_FUNCTION_ARGS);
Datum ssl_client_dn_field(PG_FUNCTION_ARGS);
@@ -49,6 +51,32 @@ ssl_is_used(PG_FUNCTION_ARGS)
/*
+ * Returns SSL cipher currently in use.
+ */
+PG_FUNCTION_INFO_V1(ssl_version);
+Datum
+ssl_version(PG_FUNCTION_ARGS)
+{
+ if (MyProcPort->ssl == NULL)
+ PG_RETURN_NULL();
+ PG_RETURN_TEXT_P(cstring_to_text(SSL_get_version(MyProcPort->ssl)));
+}
+
+
+/*
+ * Returns SSL cipher currently in use.
+ */
+PG_FUNCTION_INFO_V1(ssl_cipher);
+Datum
+ssl_cipher(PG_FUNCTION_ARGS)
+{
+ if (MyProcPort->ssl == NULL)
+ PG_RETURN_NULL();
+ PG_RETURN_TEXT_P(cstring_to_text(SSL_get_cipher(MyProcPort->ssl)));
+}
+
+
+/*
* Indicates whether current client have provided a certificate
*
* Function has no arguments. Returns bool. True if current session
diff --git a/contrib/sslinfo/sslinfo.control b/contrib/sslinfo/sslinfo.control
new file mode 100644
index 0000000000..1d2f058f6e
--- /dev/null
+++ b/contrib/sslinfo/sslinfo.control
@@ -0,0 +1,5 @@
+# sslinfo extension
+comment = 'information about SSL certificates'
+default_version = '1.0'
+module_pathname = '$libdir/sslinfo'
+relocatable = true
diff --git a/contrib/sslinfo/sslinfo.sql.in b/contrib/sslinfo/sslinfo.sql.in
deleted file mode 100644
index 53c30afd36..0000000000
--- a/contrib/sslinfo/sslinfo.sql.in
+++ /dev/null
@@ -1,32 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/sslinfo/sslinfo.sql.in,v 1.4 2007/11/13 04:24:29 momjian Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION ssl_client_serial() RETURNS numeric
-AS 'MODULE_PATHNAME', 'ssl_client_serial'
-LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION ssl_is_used() RETURNS boolean
-AS 'MODULE_PATHNAME', 'ssl_is_used'
-LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION ssl_client_cert_present() RETURNS boolean
-AS 'MODULE_PATHNAME', 'ssl_client_cert_present'
-LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION ssl_client_dn_field(text) RETURNS text
-AS 'MODULE_PATHNAME', 'ssl_client_dn_field'
-LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION ssl_issuer_field(text) RETURNS text
-AS 'MODULE_PATHNAME', 'ssl_issuer_field'
-LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION ssl_client_dn() RETURNS text
-AS 'MODULE_PATHNAME', 'ssl_client_dn'
-LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION ssl_issuer_dn() RETURNS text
-AS 'MODULE_PATHNAME', 'ssl_issuer_dn'
-LANGUAGE C STRICT;
diff --git a/contrib/sslinfo/uninstall_sslinfo.sql b/contrib/sslinfo/uninstall_sslinfo.sql
deleted file mode 100644
index 1bc98df050..0000000000
--- a/contrib/sslinfo/uninstall_sslinfo.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/sslinfo/uninstall_sslinfo.sql,v 1.3 2007/11/13 04:24:29 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION ssl_client_serial();
-DROP FUNCTION ssl_is_used();
-DROP FUNCTION ssl_client_cert_present();
-DROP FUNCTION ssl_client_dn_field(text);
-DROP FUNCTION ssl_issuer_field(text);
-DROP FUNCTION ssl_client_dn();
-DROP FUNCTION ssl_issuer_dn();
diff --git a/contrib/start-scripts/freebsd b/contrib/start-scripts/freebsd
index e7338c0332..758574b427 100644
--- a/contrib/start-scripts/freebsd
+++ b/contrib/start-scripts/freebsd
@@ -6,7 +6,7 @@
# Created through merger of the Linux start script by Ryan Kirkpatrick
# and the script in the FreeBSD ports collection.
-# $PostgreSQL: pgsql/contrib/start-scripts/freebsd,v 1.7 2010/02/23 22:17:25 momjian Exp $
+# contrib/start-scripts/freebsd
## EDIT FROM HERE
diff --git a/contrib/start-scripts/linux b/contrib/start-scripts/linux
index dd73e42d17..4ad66917e6 100644
--- a/contrib/start-scripts/linux
+++ b/contrib/start-scripts/linux
@@ -24,7 +24,7 @@
# Original author: Ryan Kirkpatrick <pgsql@rkirkpat.net>
-# $PostgreSQL: pgsql/contrib/start-scripts/linux,v 1.11 2010/02/23 22:15:35 momjian Exp $
+# contrib/start-scripts/linux
## EDIT FROM HERE
diff --git a/contrib/start-scripts/osx/PostgreSQL b/contrib/start-scripts/osx/PostgreSQL
index 65150d0fd5..58e69bc784 100755
--- a/contrib/start-scripts/osx/PostgreSQL
+++ b/contrib/start-scripts/osx/PostgreSQL
@@ -30,9 +30,9 @@
#
# Created by David Wheeler, 2002.
-# modified by Ray Aspeitia 12-03-2003 :
+# modified by Ray Aspeitia 12-03-2003 :
# added log rotation script to db startup
-# modified StartupParameters.plist "Provides" parameter to make it easier to
+# modified StartupParameters.plist "Provides" parameter to make it easier to
# start and stop with the SystemStarter utitlity
# use the below command in order to correctly start/stop/restart PG with log rotation script:
diff --git a/contrib/tablefunc/.gitignore b/contrib/tablefunc/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/tablefunc/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/tablefunc/Makefile b/contrib/tablefunc/Makefile
index 1207c62ef7..eb108931ec 100644
--- a/contrib/tablefunc/Makefile
+++ b/contrib/tablefunc/Makefile
@@ -1,8 +1,10 @@
-# $PostgreSQL: pgsql/contrib/tablefunc/Makefile,v 1.10 2010/07/05 23:15:56 tgl Exp $
+# contrib/tablefunc/Makefile
MODULES = tablefunc
-DATA_built = tablefunc.sql
-DATA = uninstall_tablefunc.sql
+
+EXTENSION = tablefunc
+DATA = tablefunc--1.0.sql tablefunc--unpackaged--1.0.sql
+
REGRESS = tablefunc
LDFLAGS_SL += $(filter -lm, $(LIBS))
diff --git a/contrib/tablefunc/expected/tablefunc.out b/contrib/tablefunc/expected/tablefunc.out
index 15ef758ed7..7ad4336ada 100644
--- a/contrib/tablefunc/expected/tablefunc.out
+++ b/contrib/tablefunc/expected/tablefunc.out
@@ -1,10 +1,4 @@
---
--- first, define the functions. Turn off echoing so that expected file
--- does not depend on contents of tablefunc.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION tablefunc;
--
-- normal_rand()
-- no easy way to do this for regression testing
diff --git a/contrib/tablefunc/sql/tablefunc.sql b/contrib/tablefunc/sql/tablefunc.sql
index 9f559b3977..bf874f26ad 100644
--- a/contrib/tablefunc/sql/tablefunc.sql
+++ b/contrib/tablefunc/sql/tablefunc.sql
@@ -1,12 +1,4 @@
---
--- first, define the functions. Turn off echoing so that expected file
--- does not depend on contents of tablefunc.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i tablefunc.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION tablefunc;
--
-- normal_rand()
@@ -196,4 +188,3 @@ INSERT INTO connectby_int VALUES(111,11);
INSERT INTO connectby_int VALUES(1,111);
-- this should not fail due to recursion detection
SELECT * FROM connectby('connectby_int', 'keyid', 'parent_keyid', '11', 0, '-') AS t(keyid int, parent_keyid int, level int, branch text);
-
diff --git a/contrib/tablefunc/tablefunc.sql.in b/contrib/tablefunc/tablefunc--1.0.sql
index f4864c4558..7bf117cb5c 100644
--- a/contrib/tablefunc/tablefunc.sql.in
+++ b/contrib/tablefunc/tablefunc--1.0.sql
@@ -1,15 +1,12 @@
-/* $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.sql.in,v 1.12 2007/11/13 04:24:29 momjian Exp $ */
+/* contrib/tablefunc/tablefunc--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION normal_rand(int4, float8, float8)
+CREATE FUNCTION normal_rand(int4, float8, float8)
RETURNS setof float8
AS 'MODULE_PATHNAME','normal_rand'
LANGUAGE C VOLATILE STRICT;
-- the generic crosstab function:
-CREATE OR REPLACE FUNCTION crosstab(text)
+CREATE FUNCTION crosstab(text)
RETURNS setof record
AS 'MODULE_PATHNAME','crosstab'
LANGUAGE C STABLE STRICT;
@@ -39,50 +36,50 @@ CREATE TYPE tablefunc_crosstab_4 AS
category_4 TEXT
);
-CREATE OR REPLACE FUNCTION crosstab2(text)
+CREATE FUNCTION crosstab2(text)
RETURNS setof tablefunc_crosstab_2
AS 'MODULE_PATHNAME','crosstab'
LANGUAGE C STABLE STRICT;
-CREATE OR REPLACE FUNCTION crosstab3(text)
+CREATE FUNCTION crosstab3(text)
RETURNS setof tablefunc_crosstab_3
AS 'MODULE_PATHNAME','crosstab'
LANGUAGE C STABLE STRICT;
-CREATE OR REPLACE FUNCTION crosstab4(text)
+CREATE FUNCTION crosstab4(text)
RETURNS setof tablefunc_crosstab_4
AS 'MODULE_PATHNAME','crosstab'
LANGUAGE C STABLE STRICT;
-- obsolete:
-CREATE OR REPLACE FUNCTION crosstab(text,int)
+CREATE FUNCTION crosstab(text,int)
RETURNS setof record
AS 'MODULE_PATHNAME','crosstab'
LANGUAGE C STABLE STRICT;
-CREATE OR REPLACE FUNCTION crosstab(text,text)
+CREATE FUNCTION crosstab(text,text)
RETURNS setof record
AS 'MODULE_PATHNAME','crosstab_hash'
LANGUAGE C STABLE STRICT;
-CREATE OR REPLACE FUNCTION connectby(text,text,text,text,int,text)
+CREATE FUNCTION connectby(text,text,text,text,int,text)
RETURNS setof record
AS 'MODULE_PATHNAME','connectby_text'
LANGUAGE C STABLE STRICT;
-CREATE OR REPLACE FUNCTION connectby(text,text,text,text,int)
+CREATE FUNCTION connectby(text,text,text,text,int)
RETURNS setof record
AS 'MODULE_PATHNAME','connectby_text'
LANGUAGE C STABLE STRICT;
-- These 2 take the name of a field to ORDER BY as 4th arg (for sorting siblings)
-CREATE OR REPLACE FUNCTION connectby(text,text,text,text,text,int,text)
+CREATE FUNCTION connectby(text,text,text,text,text,int,text)
RETURNS setof record
AS 'MODULE_PATHNAME','connectby_text_serial'
LANGUAGE C STABLE STRICT;
-CREATE OR REPLACE FUNCTION connectby(text,text,text,text,text,int)
+CREATE FUNCTION connectby(text,text,text,text,text,int)
RETURNS setof record
AS 'MODULE_PATHNAME','connectby_text_serial'
LANGUAGE C STABLE STRICT;
diff --git a/contrib/tablefunc/tablefunc--unpackaged--1.0.sql b/contrib/tablefunc/tablefunc--unpackaged--1.0.sql
new file mode 100644
index 0000000000..20e09816e9
--- /dev/null
+++ b/contrib/tablefunc/tablefunc--unpackaged--1.0.sql
@@ -0,0 +1,16 @@
+/* contrib/tablefunc/tablefunc--unpackaged--1.0.sql */
+
+ALTER EXTENSION tablefunc ADD function normal_rand(integer,double precision,double precision);
+ALTER EXTENSION tablefunc ADD function crosstab(text);
+ALTER EXTENSION tablefunc ADD type tablefunc_crosstab_2;
+ALTER EXTENSION tablefunc ADD type tablefunc_crosstab_3;
+ALTER EXTENSION tablefunc ADD type tablefunc_crosstab_4;
+ALTER EXTENSION tablefunc ADD function crosstab2(text);
+ALTER EXTENSION tablefunc ADD function crosstab3(text);
+ALTER EXTENSION tablefunc ADD function crosstab4(text);
+ALTER EXTENSION tablefunc ADD function crosstab(text,integer);
+ALTER EXTENSION tablefunc ADD function crosstab(text,text);
+ALTER EXTENSION tablefunc ADD function connectby(text,text,text,text,integer,text);
+ALTER EXTENSION tablefunc ADD function connectby(text,text,text,text,integer);
+ALTER EXTENSION tablefunc ADD function connectby(text,text,text,text,text,integer,text);
+ALTER EXTENSION tablefunc ADD function connectby(text,text,text,text,text,integer);
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 609ab48c7c..4ef9b00a6d 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.c,v 1.62 2010/01/02 16:57:32 momjian Exp $
+ * contrib/tablefunc/tablefunc.c
*
*
* tablefunc
@@ -10,7 +10,7 @@
* And contributors:
* Nabil Sayegh <postgresql@e-trolley.de>
*
- * Copyright (c) 2002-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2002-2011, PostgreSQL Global Development Group
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without a written agreement
@@ -85,7 +85,6 @@ static Tuplestorestate *build_tuplestore_recursively(char *key_fld,
MemoryContext per_query_ctx,
AttInMetadata *attinmeta,
Tuplestorestate *tupstore);
-static char *quote_literal_cstr(char *rawstr);
typedef struct
{
@@ -1564,22 +1563,3 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc)
/* OK, the two tupdescs are compatible for our purposes */
return true;
}
-
-/*
- * Return a properly quoted literal value.
- * Uses quote_literal in quote.c
- */
-static char *
-quote_literal_cstr(char *rawstr)
-{
- text *rawstr_text;
- text *result_text;
- char *result;
-
- rawstr_text = cstring_to_text(rawstr);
- result_text = DatumGetTextP(DirectFunctionCall1(quote_literal,
- PointerGetDatum(rawstr_text)));
- result = text_to_cstring(result_text);
-
- return result;
-}
diff --git a/contrib/tablefunc/tablefunc.control b/contrib/tablefunc/tablefunc.control
new file mode 100644
index 0000000000..248b0a77a2
--- /dev/null
+++ b/contrib/tablefunc/tablefunc.control
@@ -0,0 +1,5 @@
+# tablefunc extension
+comment = 'functions that manipulate whole tables, including crosstab'
+default_version = '1.0'
+module_pathname = '$libdir/tablefunc'
+relocatable = true
diff --git a/contrib/tablefunc/tablefunc.h b/contrib/tablefunc/tablefunc.h
index 2870299bd4..a0e03e285d 100644
--- a/contrib/tablefunc/tablefunc.h
+++ b/contrib/tablefunc/tablefunc.h
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.h,v 1.17 2010/01/02 16:57:32 momjian Exp $
+ * contrib/tablefunc/tablefunc.h
*
*
* tablefunc
@@ -10,7 +10,7 @@
* And contributors:
* Nabil Sayegh <postgresql@e-trolley.de>
*
- * Copyright (c) 2002-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2002-2011, PostgreSQL Global Development Group
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without a written agreement
diff --git a/contrib/tablefunc/uninstall_tablefunc.sql b/contrib/tablefunc/uninstall_tablefunc.sql
deleted file mode 100644
index cb58df89bb..0000000000
--- a/contrib/tablefunc/uninstall_tablefunc.sql
+++ /dev/null
@@ -1,32 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/tablefunc/uninstall_tablefunc.sql,v 1.3 2007/11/13 04:24:29 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION connectby(text,text,text,text,text,int);
-
-DROP FUNCTION connectby(text,text,text,text,text,int,text);
-
-DROP FUNCTION connectby(text,text,text,text,int);
-
-DROP FUNCTION connectby(text,text,text,text,int,text);
-
-DROP FUNCTION crosstab(text,text);
-
-DROP FUNCTION crosstab(text,int);
-
-DROP FUNCTION crosstab4(text);
-
-DROP FUNCTION crosstab3(text);
-
-DROP FUNCTION crosstab2(text);
-
-DROP TYPE tablefunc_crosstab_4;
-
-DROP TYPE tablefunc_crosstab_3;
-
-DROP TYPE tablefunc_crosstab_2;
-
-DROP FUNCTION crosstab(text);
-
-DROP FUNCTION normal_rand(int4, float8, float8);
diff --git a/contrib/test_parser/.gitignore b/contrib/test_parser/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/test_parser/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/test_parser/Makefile b/contrib/test_parser/Makefile
index 4499069548..b9766cb023 100644
--- a/contrib/test_parser/Makefile
+++ b/contrib/test_parser/Makefile
@@ -1,9 +1,11 @@
-# $PostgreSQL: pgsql/contrib/test_parser/Makefile,v 1.2 2007/12/03 04:22:54 tgl Exp $
+# contrib/test_parser/Makefile
MODULE_big = test_parser
OBJS = test_parser.o
-DATA_built = test_parser.sql
-DATA = uninstall_test_parser.sql
+
+EXTENSION = test_parser
+DATA = test_parser--1.0.sql test_parser--unpackaged--1.0.sql
+
REGRESS = test_parser
ifdef USE_PGXS
diff --git a/contrib/test_parser/expected/test_parser.out b/contrib/test_parser/expected/test_parser.out
index 600086c4ae..8a49bc01e3 100644
--- a/contrib/test_parser/expected/test_parser.out
+++ b/contrib/test_parser/expected/test_parser.out
@@ -1,10 +1,4 @@
---
--- first, define the parser. Turn off echoing so that expected file
--- does not depend on contents of this file.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+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;
@@ -41,7 +35,7 @@ SELECT to_tsquery('testcfg', 'star');
'star'
(1 row)
-SELECT ts_headline('testcfg','Supernovae stars are the brightest phenomena in galaxies',
+SELECT ts_headline('testcfg','Supernovae stars are the brightest phenomena in galaxies',
to_tsquery('testcfg', 'stars'));
ts_headline
-----------------------------------------------------------------
diff --git a/contrib/test_parser/sql/test_parser.sql b/contrib/test_parser/sql/test_parser.sql
index f43d4c7e09..1f21504602 100644
--- a/contrib/test_parser/sql/test_parser.sql
+++ b/contrib/test_parser/sql/test_parser.sql
@@ -1,12 +1,4 @@
---
--- first, define the parser. Turn off echoing so that expected file
--- does not depend on contents of this file.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i test_parser.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION test_parser;
-- make test configuration using parser
@@ -22,5 +14,5 @@ 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',
+SELECT ts_headline('testcfg','Supernovae stars are the brightest phenomena in galaxies',
to_tsquery('testcfg', 'stars'));
diff --git a/contrib/test_parser/test_parser.sql.in b/contrib/test_parser/test_parser--1.0.sql
index 4fd9b0796e..5b8b04bb05 100644
--- a/contrib/test_parser/test_parser.sql.in
+++ b/contrib/test_parser/test_parser--1.0.sql
@@ -1,24 +1,21 @@
-/* $PostgreSQL: pgsql/contrib/test_parser/test_parser.sql.in,v 1.3 2007/11/13 04:24:29 momjian Exp $ */
+/* contrib/test_parser/test_parser--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION testprs_start(internal, int4)
+CREATE FUNCTION testprs_start(internal, int4)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION testprs_getlexeme(internal, internal, internal)
+CREATE FUNCTION testprs_getlexeme(internal, internal, internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION testprs_end(internal)
+CREATE FUNCTION testprs_end(internal)
RETURNS void
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION testprs_lextype(internal)
+CREATE FUNCTION testprs_lextype(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;
diff --git a/contrib/test_parser/test_parser--unpackaged--1.0.sql b/contrib/test_parser/test_parser--unpackaged--1.0.sql
new file mode 100644
index 0000000000..e240ab2b5b
--- /dev/null
+++ b/contrib/test_parser/test_parser--unpackaged--1.0.sql
@@ -0,0 +1,7 @@
+/* contrib/test_parser/test_parser--unpackaged--1.0.sql */
+
+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;
diff --git a/contrib/test_parser/test_parser.c b/contrib/test_parser/test_parser.c
index da4f9be781..8e4c7a32d9 100644
--- a/contrib/test_parser/test_parser.c
+++ b/contrib/test_parser/test_parser.c
@@ -3,10 +3,10 @@
* test_parser.c
* Simple example of a text search parser
*
- * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2007-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/test_parser/test_parser.c,v 1.7 2010/01/02 16:57:32 momjian Exp $
+ * contrib/test_parser/test_parser.c
*
*-------------------------------------------------------------------------
*/
diff --git a/contrib/test_parser/test_parser.control b/contrib/test_parser/test_parser.control
new file mode 100644
index 0000000000..36b26b2087
--- /dev/null
+++ b/contrib/test_parser/test_parser.control
@@ -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
diff --git a/contrib/test_parser/uninstall_test_parser.sql b/contrib/test_parser/uninstall_test_parser.sql
deleted file mode 100644
index 66686d2004..0000000000
--- a/contrib/test_parser/uninstall_test_parser.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/test_parser/uninstall_test_parser.sql,v 1.3 2007/11/13 04:24:29 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP TEXT SEARCH PARSER testparser;
-
-DROP FUNCTION testprs_start(internal, int4);
-
-DROP FUNCTION testprs_getlexeme(internal, internal, internal);
-
-DROP FUNCTION testprs_end(internal);
-
-DROP FUNCTION testprs_lextype(internal);
diff --git a/contrib/tsearch2/.gitignore b/contrib/tsearch2/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/tsearch2/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/tsearch2/Makefile b/contrib/tsearch2/Makefile
index 8ab634323f..d260fd0030 100644
--- a/contrib/tsearch2/Makefile
+++ b/contrib/tsearch2/Makefile
@@ -1,8 +1,10 @@
-# $PostgreSQL: pgsql/contrib/tsearch2/Makefile,v 1.20 2007/11/13 21:02:28 tgl Exp $
+# contrib/tsearch2/Makefile
MODULES = tsearch2
-DATA_built = tsearch2.sql
-DATA = uninstall_tsearch2.sql
+
+EXTENSION = tsearch2
+DATA = tsearch2--1.0.sql tsearch2--unpackaged--1.0.sql
+
REGRESS = tsearch2
ifdef USE_PGXS
diff --git a/contrib/tsearch2/expected/tsearch2.out b/contrib/tsearch2/expected/tsearch2.out
index 8674337e52..972f764c14 100644
--- a/contrib/tsearch2/expected/tsearch2.out
+++ b/contrib/tsearch2/expected/tsearch2.out
@@ -1,10 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of tsearch2.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION tsearch2;
--tsvector
SELECT '1'::tsvector;
tsvector
@@ -815,13 +809,13 @@ SELECT length(to_tsvector('english', '345 qwe@efd.r '' http://www.com/ http://ae
53
(1 row)
-select to_tsquery('english', 'qwe & sKies ');
+select to_tsquery('english', 'qwe & sKies ');
to_tsquery
---------------
'qwe' & 'sky'
(1 row)
-select to_tsquery('simple', 'qwe & sKies ');
+select to_tsquery('simple', 'qwe & sKies ');
to_tsquery
-----------------
'qwe' & 'skies'
@@ -2337,7 +2331,6 @@ Upon a woman s face. E. J. Pratt (1882 1964)
The granite features of this cliff
(1 row)
-
select headline('Erosion It took the sea a thousand years,
A thousand years to trace
The granite features of this cliff
@@ -2354,7 +2347,6 @@ Upon a woman s face. E. J. Pratt (1882 1964)
The <b>granite</b> features of this cliff
(1 row)
-
select headline('Erosion It took the sea a thousand years,
A thousand years to trace
The granite features of this cliff
@@ -2382,7 +2374,7 @@ ff-bg
document.write(15);
</script>
</body>
-</html>',
+</html>',
to_tsquery('sea&foo'), 'HighlightAll=true');
headline
-----------------------------------------------------------------------------
diff --git a/contrib/tsearch2/expected/tsearch2_1.out b/contrib/tsearch2/expected/tsearch2_1.out
index a26c5162d1..349733b6fd 100644
--- a/contrib/tsearch2/expected/tsearch2_1.out
+++ b/contrib/tsearch2/expected/tsearch2_1.out
@@ -1,10 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of tsearch2.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION tsearch2;
--tsvector
SELECT '1'::tsvector;
tsvector
@@ -815,13 +809,13 @@ SELECT length(to_tsvector('english', '345 qwe@efd.r '' http://www.com/ http://ae
53
(1 row)
-select to_tsquery('english', 'qwe & sKies ');
+select to_tsquery('english', 'qwe & sKies ');
to_tsquery
---------------
'qwe' & 'sky'
(1 row)
-select to_tsquery('simple', 'qwe & sKies ');
+select to_tsquery('simple', 'qwe & sKies ');
to_tsquery
-----------------
'qwe' & 'skies'
@@ -2337,7 +2331,6 @@ Upon a woman s face. E. J. Pratt (1882 1964)
The granite features of this cliff
(1 row)
-
select headline('Erosion It took the sea a thousand years,
A thousand years to trace
The granite features of this cliff
@@ -2354,7 +2347,6 @@ Upon a woman s face. E. J. Pratt (1882 1964)
The <b>granite</b> features of this cliff
(1 row)
-
select headline('Erosion It took the sea a thousand years,
A thousand years to trace
The granite features of this cliff
@@ -2382,7 +2374,7 @@ ff-bg
document.write(15);
</script>
</body>
-</html>',
+</html>',
to_tsquery('sea&foo'), 'HighlightAll=true');
headline
-----------------------------------------------------------------------------
diff --git a/contrib/tsearch2/sql/tsearch2.sql b/contrib/tsearch2/sql/tsearch2.sql
index b20055c45c..665882ff88 100644
--- a/contrib/tsearch2/sql/tsearch2.sql
+++ b/contrib/tsearch2/sql/tsearch2.sql
@@ -1,12 +1,4 @@
---
--- first, define the datatype. Turn off echoing so that expected file
--- does not depend on contents of tsearch2.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i tsearch2.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION tsearch2;
--tsvector
SELECT '1'::tsvector;
@@ -168,8 +160,8 @@ SELECT length(to_tsvector('english', '345 qwe@efd.r '' http://www.com/ http://ae
<i <b> wow < jqw <> qwerty'));
-select to_tsquery('english', 'qwe & sKies ');
-select to_tsquery('simple', 'qwe & sKies ');
+select to_tsquery('english', 'qwe & sKies ');
+select to_tsquery('simple', 'qwe & sKies ');
select to_tsquery('english', '''the wether'':dc & '' sKies '':BC ');
select to_tsquery('english', 'asd&(and|fghj)');
select to_tsquery('english', '(asd&and)|fghj');
@@ -288,7 +280,7 @@ An hour of storm to place
The sculpture of these granite seams,
Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('sea&thousand&years'));
-
+
select headline('Erosion It took the sea a thousand years,
A thousand years to trace
The granite features of this cliff
@@ -298,7 +290,7 @@ An hour of storm to place
The sculpture of these granite seams,
Upon a woman s face. E. J. Pratt (1882 1964)
', to_tsquery('granite&sea'));
-
+
select headline('Erosion It took the sea a thousand years,
A thousand years to trace
The granite features of this cliff
@@ -321,7 +313,7 @@ ff-bg
document.write(15);
</script>
</body>
-</html>',
+</html>',
to_tsquery('sea&foo'), 'HighlightAll=true');
--check debug
select * from public.ts_debug('Tsearch module for PostgreSQL 7.3.3');
@@ -340,4 +332,3 @@ SELECT count(*) FROM test_tsvector WHERE a @@ 'eq&yt';
SELECT count(*) FROM test_tsvector WHERE a @@ 'eq|yt';
SELECT count(*) FROM test_tsvector WHERE a @@ '(eq&yt)|(wr&qh)';
SELECT count(*) FROM test_tsvector WHERE a @@ '(eq|yt)&(wr|qh)';
-
diff --git a/contrib/tsearch2/tsearch2.sql.in b/contrib/tsearch2/tsearch2--1.0.sql
index fc19037578..369507e8f5 100644
--- a/contrib/tsearch2/tsearch2.sql.in
+++ b/contrib/tsearch2/tsearch2--1.0.sql
@@ -1,7 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.sql.in,v 1.7 2009/03/25 22:19:01 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
+/* contrib/tsearch2/tsearch2--1.0.sql */
-- These domains are just to catch schema-qualified references to the
-- old data types.
@@ -11,7 +8,7 @@ CREATE DOMAIN gtsvector AS pg_catalog.gtsvector;
CREATE DOMAIN gtsq AS pg_catalog.text;
--dict interface
-CREATE FUNCTION lexize(oid, text)
+CREATE FUNCTION lexize(oid, text)
RETURNS _text
as 'ts_lexize'
LANGUAGE INTERNAL
@@ -44,7 +41,7 @@ CREATE FUNCTION set_curdict(text)
--built-in dictionaries
CREATE FUNCTION dex_init(internal)
RETURNS internal
- as 'MODULE_PATHNAME', 'tsa_dex_init'
+ as 'MODULE_PATHNAME', 'tsa_dex_init'
LANGUAGE C;
CREATE FUNCTION dex_lexize(internal,internal,int4)
@@ -66,7 +63,7 @@ CREATE FUNCTION snb_lexize(internal,internal,int4)
CREATE FUNCTION snb_ru_init_koi8(internal)
RETURNS internal
- as 'MODULE_PATHNAME', 'tsa_snb_ru_init_koi8'
+ as 'MODULE_PATHNAME', 'tsa_snb_ru_init_koi8'
LANGUAGE C;
CREATE FUNCTION snb_ru_init_utf8(internal)
@@ -81,7 +78,7 @@ CREATE FUNCTION snb_ru_init(internal)
CREATE FUNCTION spell_init(internal)
RETURNS internal
- as 'MODULE_PATHNAME', 'tsa_spell_init'
+ as 'MODULE_PATHNAME', 'tsa_spell_init'
LANGUAGE C;
CREATE FUNCTION spell_lexize(internal,internal,int4)
@@ -92,7 +89,7 @@ CREATE FUNCTION spell_lexize(internal,internal,int4)
CREATE FUNCTION syn_init(internal)
RETURNS internal
- as 'MODULE_PATHNAME', 'tsa_syn_init'
+ as 'MODULE_PATHNAME', 'tsa_syn_init'
LANGUAGE C;
CREATE FUNCTION syn_lexize(internal,internal,int4)
@@ -113,8 +110,8 @@ CREATE FUNCTION thesaurus_lexize(internal,internal,int4,internal)
RETURNS NULL ON NULL INPUT;
--sql-level interface
-CREATE TYPE tokentype
- as (tokid int4, alias text, descr text);
+CREATE TYPE tokentype
+ as (tokid int4, alias text, descr text);
CREATE FUNCTION token_type(int4)
RETURNS setof tokentype
@@ -149,7 +146,7 @@ CREATE FUNCTION set_curprs(text)
LANGUAGE C
RETURNS NULL ON NULL INPUT;
-CREATE TYPE tokenout
+CREATE TYPE tokenout
as (tokid int4, token text);
CREATE FUNCTION parse(oid,text)
@@ -157,19 +154,19 @@ CREATE FUNCTION parse(oid,text)
as 'ts_parse_byid'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT;
-
+
CREATE FUNCTION parse(text,text)
RETURNS setof tokenout
as 'ts_parse_byname'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT;
-
+
CREATE FUNCTION parse(text)
RETURNS setof tokenout
as 'MODULE_PATHNAME', 'tsa_parse_current'
LANGUAGE C
RETURNS NULL ON NULL INPUT;
-
+
--default parser
CREATE FUNCTION prsd_start(internal,int4)
RETURNS internal
@@ -399,7 +396,7 @@ AS
STORAGE gtsvector;
--stat info
-CREATE TYPE statinfo
+CREATE TYPE statinfo
as (word text, ndoc int4, nentry int4);
CREATE FUNCTION stat(text)
@@ -438,7 +435,7 @@ create type tsdebug as (
"tsvector" tsvector
);
-CREATE or replace FUNCTION _get_parser_from_curcfg()
+CREATE FUNCTION _get_parser_from_curcfg()
RETURNS text as
$$select prsname::text from pg_catalog.pg_ts_parser p join pg_ts_config c on cfgparser = p.oid where c.oid = show_curcfg();$$
LANGUAGE SQL RETURNS NULL ON NULL INPUT IMMUTABLE;
@@ -464,25 +461,25 @@ where
t.tokid = p.tokid
$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT;
-CREATE OR REPLACE FUNCTION numnode(tsquery)
+CREATE FUNCTION numnode(tsquery)
RETURNS int4
as 'tsquery_numnode'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT IMMUTABLE;
-CREATE OR REPLACE FUNCTION tsquery_and(tsquery,tsquery)
+CREATE FUNCTION tsquery_and(tsquery,tsquery)
RETURNS tsquery
as 'tsquery_and'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT IMMUTABLE;
-CREATE OR REPLACE FUNCTION tsquery_or(tsquery,tsquery)
+CREATE FUNCTION tsquery_or(tsquery,tsquery)
RETURNS tsquery
as 'tsquery_or'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT IMMUTABLE;
-CREATE OR REPLACE FUNCTION tsquery_not(tsquery)
+CREATE FUNCTION tsquery_not(tsquery)
RETURNS tsquery
as 'tsquery_not'
LANGUAGE INTERNAL
@@ -490,24 +487,24 @@ CREATE OR REPLACE FUNCTION tsquery_not(tsquery)
--------------rewrite subsystem
-CREATE OR REPLACE FUNCTION rewrite(tsquery, text)
+CREATE FUNCTION rewrite(tsquery, text)
RETURNS tsquery
as 'tsquery_rewrite_query'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT IMMUTABLE;
-CREATE OR REPLACE FUNCTION rewrite(tsquery, tsquery, tsquery)
+CREATE FUNCTION rewrite(tsquery, tsquery, tsquery)
RETURNS tsquery
as 'tsquery_rewrite'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT IMMUTABLE;
-CREATE OR REPLACE FUNCTION rewrite_accum(tsquery,tsquery[])
+CREATE FUNCTION rewrite_accum(tsquery,tsquery[])
RETURNS tsquery
AS 'MODULE_PATHNAME', 'tsa_rewrite_accum'
LANGUAGE C;
-CREATE OR REPLACE FUNCTION rewrite_finish(tsquery)
+CREATE FUNCTION rewrite_finish(tsquery)
RETURNS tsquery
as 'MODULE_PATHNAME', 'tsa_rewrite_finish'
LANGUAGE C;
@@ -519,13 +516,13 @@ CREATE AGGREGATE rewrite (
FINALFUNC = rewrite_finish
);
-CREATE OR REPLACE FUNCTION tsq_mcontains(tsquery, tsquery)
+CREATE FUNCTION tsq_mcontains(tsquery, tsquery)
RETURNS bool
as 'tsq_mcontains'
LANGUAGE INTERNAL
RETURNS NULL ON NULL INPUT IMMUTABLE;
-CREATE OR REPLACE FUNCTION tsq_mcontained(tsquery, tsquery)
+CREATE FUNCTION tsq_mcontained(tsquery, tsquery)
RETURNS bool
as 'tsq_mcontained'
LANGUAGE INTERNAL
@@ -551,16 +548,16 @@ AS
OPERATOR 1 @@ (tsvector, tsquery),
OPERATOR 2 @@@ (tsvector, tsquery),
FUNCTION 1 bttextcmp(text, text),
- FUNCTION 2 gin_extract_tsvector(tsvector,internal),
- FUNCTION 3 gin_extract_tsquery(tsquery,internal,smallint,internal,internal),
- FUNCTION 4 gin_tsquery_consistent(internal,smallint,tsquery,int,internal,internal),
+ FUNCTION 2 gin_extract_tsvector(tsvector,internal,internal),
+ FUNCTION 3 gin_extract_tsquery(tsquery,internal,smallint,internal,internal,internal,internal),
+ FUNCTION 4 gin_tsquery_consistent(internal,smallint,tsquery,int,internal,internal,internal,internal),
FUNCTION 5 gin_cmp_prefix(text,text,smallint,internal),
STORAGE text;
CREATE OPERATOR CLASS tsvector_ops
FOR TYPE tsvector USING btree AS
OPERATOR 1 < ,
- OPERATOR 2 <= ,
+ OPERATOR 2 <= ,
OPERATOR 3 = ,
OPERATOR 4 >= ,
OPERATOR 5 > ,
diff --git a/contrib/tsearch2/tsearch2--unpackaged--1.0.sql b/contrib/tsearch2/tsearch2--unpackaged--1.0.sql
new file mode 100644
index 0000000000..d04d5aa57e
--- /dev/null
+++ b/contrib/tsearch2/tsearch2--unpackaged--1.0.sql
@@ -0,0 +1,141 @@
+/* contrib/tsearch2/tsearch2--unpackaged--1.0.sql */
+
+ALTER EXTENSION tsearch2 ADD type @extschema@.tsvector;
+ALTER EXTENSION tsearch2 ADD type @extschema@.tsquery;
+ALTER EXTENSION tsearch2 ADD type @extschema@.gtsvector;
+ALTER EXTENSION tsearch2 ADD type gtsq;
+ALTER EXTENSION tsearch2 ADD function lexize(oid,text);
+ALTER EXTENSION tsearch2 ADD function lexize(text,text);
+ALTER EXTENSION tsearch2 ADD function lexize(text);
+ALTER EXTENSION tsearch2 ADD function set_curdict(integer);
+ALTER EXTENSION tsearch2 ADD function set_curdict(text);
+ALTER EXTENSION tsearch2 ADD function dex_init(internal);
+ALTER EXTENSION tsearch2 ADD function dex_lexize(internal,internal,integer);
+ALTER EXTENSION tsearch2 ADD function snb_en_init(internal);
+ALTER EXTENSION tsearch2 ADD function snb_lexize(internal,internal,integer);
+ALTER EXTENSION tsearch2 ADD function snb_ru_init_koi8(internal);
+ALTER EXTENSION tsearch2 ADD function snb_ru_init_utf8(internal);
+ALTER EXTENSION tsearch2 ADD function snb_ru_init(internal);
+ALTER EXTENSION tsearch2 ADD function spell_init(internal);
+ALTER EXTENSION tsearch2 ADD function spell_lexize(internal,internal,integer);
+ALTER EXTENSION tsearch2 ADD function syn_init(internal);
+ALTER EXTENSION tsearch2 ADD function syn_lexize(internal,internal,integer);
+ALTER EXTENSION tsearch2 ADD function @extschema@.thesaurus_init(internal);
+ALTER EXTENSION tsearch2 ADD function thesaurus_lexize(internal,internal,integer,internal);
+ALTER EXTENSION tsearch2 ADD type tokentype;
+ALTER EXTENSION tsearch2 ADD function token_type(integer);
+ALTER EXTENSION tsearch2 ADD function token_type(text);
+ALTER EXTENSION tsearch2 ADD function token_type();
+ALTER EXTENSION tsearch2 ADD function set_curprs(integer);
+ALTER EXTENSION tsearch2 ADD function set_curprs(text);
+ALTER EXTENSION tsearch2 ADD type tokenout;
+ALTER EXTENSION tsearch2 ADD function parse(oid,text);
+ALTER EXTENSION tsearch2 ADD function parse(text,text);
+ALTER EXTENSION tsearch2 ADD function parse(text);
+ALTER EXTENSION tsearch2 ADD function @extschema@.prsd_start(internal,integer);
+ALTER EXTENSION tsearch2 ADD function prsd_getlexeme(internal,internal,internal);
+ALTER EXTENSION tsearch2 ADD function @extschema@.prsd_end(internal);
+ALTER EXTENSION tsearch2 ADD function @extschema@.prsd_lextype(internal);
+ALTER EXTENSION tsearch2 ADD function prsd_headline(internal,internal,internal);
+ALTER EXTENSION tsearch2 ADD function set_curcfg(integer);
+ALTER EXTENSION tsearch2 ADD function set_curcfg(text);
+ALTER EXTENSION tsearch2 ADD function show_curcfg();
+ALTER EXTENSION tsearch2 ADD function @extschema@.length(tsvector);
+ALTER EXTENSION tsearch2 ADD function to_tsvector(oid,text);
+ALTER EXTENSION tsearch2 ADD function to_tsvector(text,text);
+ALTER EXTENSION tsearch2 ADD function @extschema@.to_tsvector(text);
+ALTER EXTENSION tsearch2 ADD function @extschema@.strip(tsvector);
+ALTER EXTENSION tsearch2 ADD function @extschema@.setweight(tsvector,"char");
+ALTER EXTENSION tsearch2 ADD function concat(tsvector,tsvector);
+ALTER EXTENSION tsearch2 ADD function @extschema@.querytree(tsquery);
+ALTER EXTENSION tsearch2 ADD function to_tsquery(oid,text);
+ALTER EXTENSION tsearch2 ADD function to_tsquery(text,text);
+ALTER EXTENSION tsearch2 ADD function @extschema@.to_tsquery(text);
+ALTER EXTENSION tsearch2 ADD function plainto_tsquery(oid,text);
+ALTER EXTENSION tsearch2 ADD function plainto_tsquery(text,text);
+ALTER EXTENSION tsearch2 ADD function @extschema@.plainto_tsquery(text);
+ALTER EXTENSION tsearch2 ADD function tsearch2();
+ALTER EXTENSION tsearch2 ADD function rank(real[],tsvector,tsquery);
+ALTER EXTENSION tsearch2 ADD function rank(real[],tsvector,tsquery,integer);
+ALTER EXTENSION tsearch2 ADD function rank(tsvector,tsquery);
+ALTER EXTENSION tsearch2 ADD function rank(tsvector,tsquery,integer);
+ALTER EXTENSION tsearch2 ADD function rank_cd(real[],tsvector,tsquery);
+ALTER EXTENSION tsearch2 ADD function rank_cd(real[],tsvector,tsquery,integer);
+ALTER EXTENSION tsearch2 ADD function rank_cd(tsvector,tsquery);
+ALTER EXTENSION tsearch2 ADD function rank_cd(tsvector,tsquery,integer);
+ALTER EXTENSION tsearch2 ADD function headline(oid,text,tsquery,text);
+ALTER EXTENSION tsearch2 ADD function headline(oid,text,tsquery);
+ALTER EXTENSION tsearch2 ADD function headline(text,text,tsquery,text);
+ALTER EXTENSION tsearch2 ADD function headline(text,text,tsquery);
+ALTER EXTENSION tsearch2 ADD function headline(text,tsquery,text);
+ALTER EXTENSION tsearch2 ADD function headline(text,tsquery);
+ALTER EXTENSION tsearch2 ADD operator family gist_tsvector_ops using gist;
+ALTER EXTENSION tsearch2 ADD operator class gist_tsvector_ops using gist;
+ALTER EXTENSION tsearch2 ADD type statinfo;
+ALTER EXTENSION tsearch2 ADD function stat(text);
+ALTER EXTENSION tsearch2 ADD function stat(text,text);
+ALTER EXTENSION tsearch2 ADD function reset_tsearch();
+ALTER EXTENSION tsearch2 ADD function get_covers(tsvector,tsquery);
+ALTER EXTENSION tsearch2 ADD type tsdebug;
+ALTER EXTENSION tsearch2 ADD function _get_parser_from_curcfg();
+ALTER EXTENSION tsearch2 ADD function @extschema@.ts_debug(text);
+ALTER EXTENSION tsearch2 ADD function @extschema@.numnode(tsquery);
+ALTER EXTENSION tsearch2 ADD function @extschema@.tsquery_and(tsquery,tsquery);
+ALTER EXTENSION tsearch2 ADD function @extschema@.tsquery_or(tsquery,tsquery);
+ALTER EXTENSION tsearch2 ADD function @extschema@.tsquery_not(tsquery);
+ALTER EXTENSION tsearch2 ADD function rewrite(tsquery,text);
+ALTER EXTENSION tsearch2 ADD function rewrite(tsquery,tsquery,tsquery);
+ALTER EXTENSION tsearch2 ADD function rewrite_accum(tsquery,tsquery[]);
+ALTER EXTENSION tsearch2 ADD function rewrite_finish(tsquery);
+ALTER EXTENSION tsearch2 ADD function rewrite(tsquery[]);
+ALTER EXTENSION tsearch2 ADD function @extschema@.tsq_mcontains(tsquery,tsquery);
+ALTER EXTENSION tsearch2 ADD function @extschema@.tsq_mcontained(tsquery,tsquery);
+ALTER EXTENSION tsearch2 ADD operator family gist_tp_tsquery_ops using gist;
+ALTER EXTENSION tsearch2 ADD operator class gist_tp_tsquery_ops using gist;
+ALTER EXTENSION tsearch2 ADD operator family gin_tsvector_ops using gin;
+ALTER EXTENSION tsearch2 ADD operator class gin_tsvector_ops using gin;
+ALTER EXTENSION tsearch2 ADD operator family @extschema@.tsvector_ops using btree;
+ALTER EXTENSION tsearch2 ADD operator class @extschema@.tsvector_ops using btree;
+ALTER EXTENSION tsearch2 ADD operator family @extschema@.tsquery_ops using btree;
+ALTER EXTENSION tsearch2 ADD operator class @extschema@.tsquery_ops using btree;
+
+-- tsearch2 relies on the core functions gin_extract_tsvector,
+-- gin_extract_tsquery, and gin_tsquery_consistent, which changed signature in
+-- 9.1. To support upgrading, pg_catalog contains entries for these functions
+-- with both the old and new signatures, and the former is what would have
+-- been added to our opclass during initial restore of a 9.0 dump script.
+-- Avert your eyes while we hack the pg_amproc entries to make them link to
+-- the new forms ...
+
+UPDATE pg_catalog.pg_amproc
+SET amproc = 'pg_catalog.gin_extract_tsvector(pg_catalog.tsvector,internal,internal)'::pg_catalog.regprocedure
+WHERE amprocfamily =
+ (SELECT oid FROM pg_catalog.pg_opfamily WHERE opfname = 'gin_tsvector_ops' AND
+ opfnamespace = (SELECT oid FROM pg_catalog.pg_namespace
+ WHERE nspname = '@extschema@'))
+ AND amproclefttype = 'pg_catalog.tsvector'::pg_catalog.regtype
+ AND amprocrighttype = 'pg_catalog.tsvector'::pg_catalog.regtype
+ AND amprocnum = 2
+ AND amproc = 'pg_catalog.gin_extract_tsvector(pg_catalog.tsvector,internal)'::pg_catalog.regprocedure;
+
+UPDATE pg_catalog.pg_amproc
+SET amproc = 'pg_catalog.gin_extract_tsquery(pg_catalog.tsquery,internal,smallint,internal,internal,internal,internal)'::pg_catalog.regprocedure
+WHERE amprocfamily =
+ (SELECT oid FROM pg_catalog.pg_opfamily WHERE opfname = 'gin_tsvector_ops' AND
+ opfnamespace = (SELECT oid FROM pg_catalog.pg_namespace
+ WHERE nspname = '@extschema@'))
+ AND amproclefttype = 'pg_catalog.tsvector'::pg_catalog.regtype
+ AND amprocrighttype = 'pg_catalog.tsvector'::pg_catalog.regtype
+ AND amprocnum = 3
+ AND amproc = 'pg_catalog.gin_extract_tsquery(pg_catalog.tsquery,internal,smallint,internal,internal)'::pg_catalog.regprocedure;
+
+UPDATE pg_catalog.pg_amproc
+SET amproc = 'pg_catalog.gin_tsquery_consistent(internal,smallint,pg_catalog.tsquery,integer,internal,internal,internal,internal)'::pg_catalog.regprocedure
+WHERE amprocfamily =
+ (SELECT oid FROM pg_catalog.pg_opfamily WHERE opfname = 'gin_tsvector_ops' AND
+ opfnamespace = (SELECT oid FROM pg_catalog.pg_namespace
+ WHERE nspname = '@extschema@'))
+ AND amproclefttype = 'pg_catalog.tsvector'::pg_catalog.regtype
+ AND amprocrighttype = 'pg_catalog.tsvector'::pg_catalog.regtype
+ AND amprocnum = 4
+ AND amproc = 'pg_catalog.gin_tsquery_consistent(internal,smallint,pg_catalog.tsquery,integer,internal,internal)'::pg_catalog.regprocedure;
diff --git a/contrib/tsearch2/tsearch2.c b/contrib/tsearch2/tsearch2.c
index 63fba13329..c6ced6396c 100644
--- a/contrib/tsearch2/tsearch2.c
+++ b/contrib/tsearch2/tsearch2.c
@@ -3,11 +3,11 @@
* tsearch2.c
* Backwards-compatibility package for old contrib/tsearch2 API
*
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.c,v 1.12 2010/02/08 20:39:51 tgl Exp $
+ * contrib/tsearch2/tsearch2.c
*
*-------------------------------------------------------------------------
*/
@@ -190,7 +190,7 @@ tsa_set_curdict_byname(PG_FUNCTION_ARGS)
text *name = PG_GETARG_TEXT_PP(0);
Oid dict_oid;
- dict_oid = TSDictionaryGetDictid(stringToQualifiedNameList(text_to_cstring(name)), false);
+ dict_oid = get_ts_dict_oid(stringToQualifiedNameList(text_to_cstring(name)), false);
current_dictionary_oid = dict_oid;
@@ -229,7 +229,7 @@ tsa_set_curprs_byname(PG_FUNCTION_ARGS)
text *name = PG_GETARG_TEXT_PP(0);
Oid parser_oid;
- parser_oid = TSParserGetPrsid(stringToQualifiedNameList(text_to_cstring(name)), false);
+ parser_oid = get_ts_parser_oid(stringToQualifiedNameList(text_to_cstring(name)), false);
current_parser_oid = parser_oid;
@@ -562,6 +562,6 @@ static Oid
GetCurrentParser(void)
{
if (current_parser_oid == InvalidOid)
- current_parser_oid = TSParserGetPrsid(stringToQualifiedNameList("pg_catalog.default"), false);
+ current_parser_oid = get_ts_parser_oid(stringToQualifiedNameList("pg_catalog.default"), false);
return current_parser_oid;
}
diff --git a/contrib/tsearch2/tsearch2.control b/contrib/tsearch2/tsearch2.control
new file mode 100644
index 0000000000..3e11bcfbe8
--- /dev/null
+++ b/contrib/tsearch2/tsearch2.control
@@ -0,0 +1,7 @@
+# tsearch2 extension
+comment = 'compatibility package for pre-8.3 text search functions'
+default_version = '1.0'
+module_pathname = '$libdir/tsearch2'
+# this is not relocatable because the tsearch2--unpackaged--1.0.sql script
+# has to use @extschema@ to avoid conflict with items in pg_catalog
+relocatable = false
diff --git a/contrib/tsearch2/uninstall_tsearch2.sql b/contrib/tsearch2/uninstall_tsearch2.sql
deleted file mode 100644
index 180b021d2c..0000000000
--- a/contrib/tsearch2/uninstall_tsearch2.sql
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/tsearch2/uninstall_tsearch2.sql,v 1.2 2007/11/16 00:34:54 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public, pg_catalog;
-
-DROP DOMAIN tsvector CASCADE;
-DROP DOMAIN tsquery CASCADE;
-DROP DOMAIN gtsvector CASCADE;
-DROP DOMAIN gtsq CASCADE;
-
-DROP TYPE tokentype CASCADE;
-DROP TYPE tokenout CASCADE;
-DROP TYPE statinfo CASCADE;
-DROP TYPE tsdebug CASCADE;
-
-DROP OPERATOR CLASS tsquery_ops USING btree CASCADE;
-
-DROP OPERATOR CLASS tsvector_ops USING btree CASCADE;
-
-DROP OPERATOR CLASS gin_tsvector_ops USING gin CASCADE;
-
-DROP OPERATOR CLASS gist_tp_tsquery_ops USING gist CASCADE;
-
-DROP OPERATOR CLASS gist_tsvector_ops USING gist CASCADE;
-
-DROP FUNCTION lexize(oid, text) ;
-DROP FUNCTION lexize(text, text);
-DROP FUNCTION lexize(text);
-DROP FUNCTION set_curdict(int);
-DROP FUNCTION set_curdict(text);
-DROP FUNCTION dex_init(internal);
-DROP FUNCTION dex_lexize(internal,internal,int4);
-DROP FUNCTION snb_en_init(internal);
-DROP FUNCTION snb_lexize(internal,internal,int4);
-DROP FUNCTION snb_ru_init_koi8(internal);
-DROP FUNCTION snb_ru_init_utf8(internal);
-DROP FUNCTION snb_ru_init(internal);
-DROP FUNCTION spell_init(internal);
-DROP FUNCTION spell_lexize(internal,internal,int4);
-DROP FUNCTION syn_init(internal);
-DROP FUNCTION syn_lexize(internal,internal,int4);
-DROP FUNCTION thesaurus_init(internal);
-DROP FUNCTION thesaurus_lexize(internal,internal,int4,internal);
-DROP FUNCTION set_curprs(int);
-DROP FUNCTION set_curprs(text);
-DROP FUNCTION prsd_start(internal,int4);
-DROP FUNCTION prsd_getlexeme(internal,internal,internal);
-DROP FUNCTION prsd_end(internal);
-DROP FUNCTION prsd_lextype(internal);
-DROP FUNCTION prsd_headline(internal,internal,internal);
-DROP FUNCTION set_curcfg(int);
-DROP FUNCTION set_curcfg(text);
-DROP FUNCTION show_curcfg();
-DROP FUNCTION length(tsvector);
-DROP FUNCTION to_tsvector(oid, text);
-DROP FUNCTION to_tsvector(text, text);
-DROP FUNCTION to_tsvector(text);
-DROP FUNCTION strip(tsvector);
-DROP FUNCTION setweight(tsvector,"char");
-DROP FUNCTION concat(tsvector,tsvector);
-DROP FUNCTION querytree(tsquery);
-DROP FUNCTION to_tsquery(oid, text);
-DROP FUNCTION to_tsquery(text, text);
-DROP FUNCTION to_tsquery(text);
-DROP FUNCTION plainto_tsquery(oid, text);
-DROP FUNCTION plainto_tsquery(text, text);
-DROP FUNCTION plainto_tsquery(text);
-DROP FUNCTION tsearch2() CASCADE;
-DROP FUNCTION rank(float4[], tsvector, tsquery);
-DROP FUNCTION rank(float4[], tsvector, tsquery, int4);
-DROP FUNCTION rank(tsvector, tsquery);
-DROP FUNCTION rank(tsvector, tsquery, int4);
-DROP FUNCTION rank_cd(float4[], tsvector, tsquery);
-DROP FUNCTION rank_cd(float4[], tsvector, tsquery, int4);
-DROP FUNCTION rank_cd(tsvector, tsquery);
-DROP FUNCTION rank_cd(tsvector, tsquery, int4);
-DROP FUNCTION headline(oid, text, tsquery, text);
-DROP FUNCTION headline(oid, text, tsquery);
-DROP FUNCTION headline(text, text, tsquery, text);
-DROP FUNCTION headline(text, text, tsquery);
-DROP FUNCTION headline(text, tsquery, text);
-DROP FUNCTION headline(text, tsquery);
-DROP FUNCTION get_covers(tsvector,tsquery);
-DROP FUNCTION _get_parser_from_curcfg();
-DROP FUNCTION numnode(tsquery);
-DROP FUNCTION tsquery_and(tsquery,tsquery);
-DROP FUNCTION tsquery_or(tsquery,tsquery);
-DROP FUNCTION tsquery_not(tsquery);
-DROP FUNCTION rewrite(tsquery, text);
-DROP FUNCTION rewrite(tsquery, tsquery, tsquery);
-DROP AGGREGATE rewrite (tsquery[]);
-DROP FUNCTION rewrite_accum(tsquery,tsquery[]);
-DROP FUNCTION rewrite_finish(tsquery);
-DROP FUNCTION tsq_mcontains(tsquery, tsquery);
-DROP FUNCTION tsq_mcontained(tsquery, tsquery);
-DROP FUNCTION reset_tsearch();
diff --git a/contrib/unaccent/.gitignore b/contrib/unaccent/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/unaccent/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/unaccent/Makefile b/contrib/unaccent/Makefile
index 401f523283..f0be62db53 100644
--- a/contrib/unaccent/Makefile
+++ b/contrib/unaccent/Makefile
@@ -1,15 +1,17 @@
-# $PostgreSQL: pgsql/contrib/unaccent/Makefile,v 1.2 2009/08/18 15:51:16 tgl Exp $
+# contrib/unaccent/Makefile
MODULE_big = unaccent
OBJS = unaccent.o
-DATA_built = unaccent.sql
-DATA = uninstall_unaccent.sql
+EXTENSION = unaccent
+DATA = unaccent--1.0.sql unaccent--unpackaged--1.0.sql
DATA_TSEARCH = unaccent.rules
+
REGRESS = unaccent
-# Adjust REGRESS_OPTS because we need a UTF8 database
-REGRESS_OPTS = --dbname=$(CONTRIB_TESTDB) --multibyte=UTF8 --no-locale
+# We need a UTF8 database
+ENCODING = UTF8
+NO_LOCALE = 1
ifdef USE_PGXS
PG_CONFIG = pg_config
diff --git a/contrib/unaccent/expected/unaccent.out b/contrib/unaccent/expected/unaccent.out
index a09e00fe5b..b93105e9c7 100644
--- a/contrib/unaccent/expected/unaccent.out
+++ b/contrib/unaccent/expected/unaccent.out
@@ -1,6 +1,4 @@
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION unaccent;
-- must have a UTF8 database
SELECT getdatabaseencoding();
getdatabaseencoding
diff --git a/contrib/unaccent/sql/unaccent.sql b/contrib/unaccent/sql/unaccent.sql
index ede938d479..310213994f 100644
--- a/contrib/unaccent/sql/unaccent.sql
+++ b/contrib/unaccent/sql/unaccent.sql
@@ -1,8 +1,4 @@
-SET client_min_messages = warning;
-\set ECHO none
-\i unaccent.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION unaccent;
-- must have a UTF8 database
SELECT getdatabaseencoding();
diff --git a/contrib/unaccent/unaccent--1.0.sql b/contrib/unaccent/unaccent--1.0.sql
new file mode 100644
index 0000000000..b5909e0b55
--- /dev/null
+++ b/contrib/unaccent/unaccent--1.0.sql
@@ -0,0 +1,31 @@
+/* contrib/unaccent/unaccent--1.0.sql */
+
+CREATE FUNCTION unaccent(regdictionary, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME', 'unaccent_dict'
+ LANGUAGE C STABLE STRICT;
+
+CREATE FUNCTION unaccent(text)
+ RETURNS text
+ AS 'MODULE_PATHNAME', 'unaccent_dict'
+ LANGUAGE C STABLE STRICT;
+
+CREATE FUNCTION unaccent_init(internal)
+ RETURNS internal
+ AS 'MODULE_PATHNAME', 'unaccent_init'
+ LANGUAGE C;
+
+CREATE FUNCTION unaccent_lexize(internal,internal,internal,internal)
+ RETURNS internal
+ AS 'MODULE_PATHNAME', 'unaccent_lexize'
+ LANGUAGE C;
+
+CREATE TEXT SEARCH TEMPLATE unaccent (
+ INIT = unaccent_init,
+ LEXIZE = unaccent_lexize
+);
+
+CREATE TEXT SEARCH DICTIONARY unaccent (
+ TEMPLATE = unaccent,
+ RULES = 'unaccent'
+);
diff --git a/contrib/unaccent/unaccent--unpackaged--1.0.sql b/contrib/unaccent/unaccent--unpackaged--1.0.sql
new file mode 100644
index 0000000000..eeb9c532f9
--- /dev/null
+++ b/contrib/unaccent/unaccent--unpackaged--1.0.sql
@@ -0,0 +1,13 @@
+/* contrib/unaccent/unaccent--unpackaged--1.0.sql */
+
+ALTER EXTENSION unaccent ADD function unaccent(regdictionary,text);
+ALTER EXTENSION unaccent ADD function unaccent(text);
+ALTER EXTENSION unaccent ADD function unaccent_init(internal);
+ALTER EXTENSION unaccent ADD function unaccent_lexize(internal,internal,internal,internal);
+ALTER EXTENSION unaccent ADD text search template unaccent;
+ALTER EXTENSION unaccent ADD text search dictionary unaccent;
+
+-- These functions are marked as stable in 9.1, were not before:
+
+ALTER FUNCTION unaccent(regdictionary, text) STABLE;
+ALTER FUNCTION unaccent(text) STABLE;
diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c
index 8e012ac172..709f4c4492 100644
--- a/contrib/unaccent/unaccent.c
+++ b/contrib/unaccent/unaccent.c
@@ -3,10 +3,10 @@
* unaccent.c
* Text search unaccent dictionary
*
- * Copyright (c) 2009-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2009-2011, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/unaccent/unaccent.c,v 1.5 2010/02/26 02:00:32 momjian Exp $
+ * contrib/unaccent/unaccent.c
*
*-------------------------------------------------------------------------
*/
@@ -279,7 +279,7 @@ unaccent_dict(PG_FUNCTION_ARGS)
if (PG_NARGS() == 1)
{
- dictOid = TSDictionaryGetDictid(stringToQualifiedNameList("unaccent"), false);
+ dictOid = get_ts_dict_oid(stringToQualifiedNameList("unaccent"), false);
strArg = 0;
}
else
diff --git a/contrib/unaccent/unaccent.control b/contrib/unaccent/unaccent.control
new file mode 100644
index 0000000000..200d2ae7bb
--- /dev/null
+++ b/contrib/unaccent/unaccent.control
@@ -0,0 +1,5 @@
+# unaccent extension
+comment = 'text search dictionary that removes accents'
+default_version = '1.0'
+module_pathname = '$libdir/unaccent'
+relocatable = true
diff --git a/contrib/unaccent/unaccent.sql.in b/contrib/unaccent/unaccent.sql.in
deleted file mode 100644
index 1f3c3c8a4a..0000000000
--- a/contrib/unaccent/unaccent.sql.in
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/unaccent/unaccent.sql.in,v 1.2 2009/11/14 18:24:32 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION unaccent(regdictionary, text)
- RETURNS text
- AS 'MODULE_PATHNAME', 'unaccent_dict'
- LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION unaccent(text)
- RETURNS text
- AS 'MODULE_PATHNAME', 'unaccent_dict'
- LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION unaccent_init(internal)
- RETURNS internal
- AS 'MODULE_PATHNAME', 'unaccent_init'
- LANGUAGE C;
-
-CREATE OR REPLACE FUNCTION unaccent_lexize(internal,internal,internal,internal)
- RETURNS internal
- AS 'MODULE_PATHNAME', 'unaccent_lexize'
- LANGUAGE C;
-
-CREATE TEXT SEARCH TEMPLATE unaccent (
- INIT = unaccent_init,
- LEXIZE = unaccent_lexize
-);
-
-CREATE TEXT SEARCH DICTIONARY unaccent (
- TEMPLATE = unaccent,
- RULES = 'unaccent'
-);
diff --git a/contrib/unaccent/uninstall_unaccent.sql b/contrib/unaccent/uninstall_unaccent.sql
deleted file mode 100644
index f60ab564da..0000000000
--- a/contrib/unaccent/uninstall_unaccent.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/unaccent/uninstall_unaccent.sql,v 1.2 2009/11/14 18:24:32 tgl Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION unaccent(regdictionary, text);
-DROP FUNCTION unaccent(text);
-DROP TEXT SEARCH DICTIONARY unaccent;
-DROP TEXT SEARCH TEMPLATE unaccent;
-DROP FUNCTION unaccent_init(internal);
-DROP FUNCTION unaccent_lexize(internal,internal,internal,internal);
diff --git a/contrib/uuid-ossp/Makefile b/contrib/uuid-ossp/Makefile
index 4ed83537dd..9b2d2e3ff9 100644
--- a/contrib/uuid-ossp/Makefile
+++ b/contrib/uuid-ossp/Makefile
@@ -1,9 +1,10 @@
-# $PostgreSQL: pgsql/contrib/uuid-ossp/Makefile,v 1.4 2007/11/13 00:13:19 tgl Exp $
+# contrib/uuid-ossp/Makefile
MODULE_big = uuid-ossp
OBJS = uuid-ossp.o
-DATA_built = uuid-ossp.sql
-DATA = uninstall_uuid-ossp.sql
+
+EXTENSION = uuid-ossp
+DATA = uuid-ossp--1.0.sql uuid-ossp--unpackaged--1.0.sql
SHLIB_LINK += $(OSSP_UUID_LIBS)
diff --git a/contrib/uuid-ossp/uninstall_uuid-ossp.sql b/contrib/uuid-ossp/uninstall_uuid-ossp.sql
deleted file mode 100644
index 75c9f3678f..0000000000
--- a/contrib/uuid-ossp/uninstall_uuid-ossp.sql
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/uuid-ossp/uninstall_uuid-ossp.sql,v 1.3 2007/11/13 04:24:29 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION uuid_nil();
-DROP FUNCTION uuid_ns_dns();
-DROP FUNCTION uuid_ns_url();
-DROP FUNCTION uuid_ns_oid();
-DROP FUNCTION uuid_ns_x500();
-
-DROP FUNCTION uuid_generate_v1();
-DROP FUNCTION uuid_generate_v1mc();
-DROP FUNCTION uuid_generate_v3(namespace uuid, name text);
-DROP FUNCTION uuid_generate_v4();
-DROP FUNCTION uuid_generate_v5(namespace uuid, name text);
diff --git a/contrib/uuid-ossp/uuid-ossp.sql.in b/contrib/uuid-ossp/uuid-ossp--1.0.sql
index e59882f456..43ae0b38a0 100644
--- a/contrib/uuid-ossp/uuid-ossp.sql.in
+++ b/contrib/uuid-ossp/uuid-ossp--1.0.sql
@@ -1,54 +1,51 @@
-/* $PostgreSQL: pgsql/contrib/uuid-ossp/uuid-ossp.sql.in,v 1.6 2007/11/13 04:24:29 momjian Exp $ */
+/* contrib/uuid-ossp/uuid-ossp--1.0.sql */
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
-CREATE OR REPLACE FUNCTION uuid_nil()
+CREATE FUNCTION uuid_nil()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_nil'
IMMUTABLE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_ns_dns()
+CREATE FUNCTION uuid_ns_dns()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_ns_dns'
IMMUTABLE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_ns_url()
+CREATE FUNCTION uuid_ns_url()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_ns_url'
IMMUTABLE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_ns_oid()
+CREATE FUNCTION uuid_ns_oid()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_ns_oid'
IMMUTABLE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_ns_x500()
+CREATE FUNCTION uuid_ns_x500()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_ns_x500'
IMMUTABLE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_generate_v1()
+CREATE FUNCTION uuid_generate_v1()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_generate_v1'
VOLATILE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_generate_v1mc()
+CREATE FUNCTION uuid_generate_v1mc()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_generate_v1mc'
VOLATILE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_generate_v3(namespace uuid, name text)
+CREATE FUNCTION uuid_generate_v3(namespace uuid, name text)
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_generate_v3'
IMMUTABLE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_generate_v4()
+CREATE FUNCTION uuid_generate_v4()
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_generate_v4'
VOLATILE STRICT LANGUAGE C;
-CREATE OR REPLACE FUNCTION uuid_generate_v5(namespace uuid, name text)
+CREATE FUNCTION uuid_generate_v5(namespace uuid, name text)
RETURNS uuid
AS 'MODULE_PATHNAME', 'uuid_generate_v5'
IMMUTABLE STRICT LANGUAGE C;
diff --git a/contrib/uuid-ossp/uuid-ossp--unpackaged--1.0.sql b/contrib/uuid-ossp/uuid-ossp--unpackaged--1.0.sql
new file mode 100644
index 0000000000..bc984dd8c0
--- /dev/null
+++ b/contrib/uuid-ossp/uuid-ossp--unpackaged--1.0.sql
@@ -0,0 +1,12 @@
+/* contrib/uuid-ossp/uuid-ossp--unpackaged--1.0.sql */
+
+ALTER EXTENSION "uuid-ossp" ADD function uuid_nil();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_ns_dns();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_ns_url();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_ns_oid();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_ns_x500();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_generate_v1();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_generate_v1mc();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_generate_v3(namespace uuid, name text);
+ALTER EXTENSION "uuid-ossp" ADD function uuid_generate_v4();
+ALTER EXTENSION "uuid-ossp" ADD function uuid_generate_v5(namespace uuid, name text);
diff --git a/contrib/uuid-ossp/uuid-ossp.c b/contrib/uuid-ossp/uuid-ossp.c
index a7d8f509bc..2be278d489 100644
--- a/contrib/uuid-ossp/uuid-ossp.c
+++ b/contrib/uuid-ossp/uuid-ossp.c
@@ -2,9 +2,9 @@
*
* UUID generation functions using the OSSP UUID library
*
- * Copyright (c) 2007-2010, PostgreSQL Global Development Group
+ * Copyright (c) 2007-2011, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/contrib/uuid-ossp/uuid-ossp.c,v 1.12 2010/01/02 16:57:33 momjian Exp $
+ * contrib/uuid-ossp/uuid-ossp.c
*
*-------------------------------------------------------------------------
*/
diff --git a/contrib/uuid-ossp/uuid-ossp.control b/contrib/uuid-ossp/uuid-ossp.control
new file mode 100644
index 0000000000..f52ae99d41
--- /dev/null
+++ b/contrib/uuid-ossp/uuid-ossp.control
@@ -0,0 +1,5 @@
+# uuid-ossp extension
+comment = 'generate universally unique identifiers (UUIDs)'
+default_version = '1.0'
+module_pathname = '$libdir/uuid-ossp'
+relocatable = true
diff --git a/contrib/vacuumlo/.gitignore b/contrib/vacuumlo/.gitignore
new file mode 100644
index 0000000000..07f6ab4fd7
--- /dev/null
+++ b/contrib/vacuumlo/.gitignore
@@ -0,0 +1 @@
+/vacuumlo
diff --git a/contrib/vacuumlo/Makefile b/contrib/vacuumlo/Makefile
index 4c68e69578..b658f9bf6f 100644
--- a/contrib/vacuumlo/Makefile
+++ b/contrib/vacuumlo/Makefile
@@ -1,7 +1,7 @@
-# $PostgreSQL: pgsql/contrib/vacuumlo/Makefile,v 1.18 2010/05/12 11:33:08 momjian Exp $
+# contrib/vacuumlo/Makefile
PGFILEDESC = "vacuumlo - removes orphaned large objects"
-PGAPPICON=win32
+PGAPPICON = win32
PROGRAM = vacuumlo
OBJS = vacuumlo.o
diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c
index 2ed1cbeb93..f6e2a28cf3 100644
--- a/contrib/vacuumlo/vacuumlo.c
+++ b/contrib/vacuumlo/vacuumlo.c
@@ -3,12 +3,12 @@
* vacuumlo.c
* This removes orphaned large objects from a database.
*
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/vacuumlo/vacuumlo.c,v 1.45 2010/02/17 04:19:37 tgl Exp $
+ * contrib/vacuumlo/vacuumlo.c
*
*-------------------------------------------------------------------------
*/
diff --git a/contrib/xml2/.gitignore b/contrib/xml2/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/contrib/xml2/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/xml2/Makefile b/contrib/xml2/Makefile
index dd45a914c9..ad325723c9 100644
--- a/contrib/xml2/Makefile
+++ b/contrib/xml2/Makefile
@@ -1,15 +1,15 @@
-# $PostgreSQL: pgsql/contrib/xml2/Makefile,v 1.14 2010/03/01 18:07:59 tgl Exp $
+# contrib/xml2/Makefile
MODULE_big = pgxml
-
OBJS = xpath.o xslt_proc.o
-SHLIB_LINK += $(filter -lxslt, $(LIBS)) $(filter -lxml2, $(LIBS))
+EXTENSION = xml2
+DATA = xml2--1.0.sql xml2--unpackaged--1.0.sql
-DATA_built = pgxml.sql
-DATA = uninstall_pgxml.sql
REGRESS = xml2
+SHLIB_LINK += $(filter -lxslt, $(LIBS)) $(filter -lxml2, $(LIBS))
+
ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
diff --git a/contrib/xml2/expected/xml2.out b/contrib/xml2/expected/xml2.out
index 74896b0802..3bf676fb40 100644
--- a/contrib/xml2/expected/xml2.out
+++ b/contrib/xml2/expected/xml2.out
@@ -1,10 +1,4 @@
---
--- first, define the functions. Turn off echoing so that expected file
--- does not depend on contents of pgxml.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION xml2;
select query_to_xml('select 1 as x',true,false,'');
query_to_xml
---------------------------------------------------------------
@@ -18,7 +12,7 @@ select query_to_xml('select 1 as x',true,false,'');
(1 row)
-select xslt_process( query_to_xml('select x from generate_series(1,5) as
+select xslt_process( query_to_xml('select x from generate_series(1,5) as
x',true,false,'')::text,
$$<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
@@ -145,3 +139,71 @@ values
Value</attribute></attributes>');
create index idx_xpath on t1 ( xpath_string
('/attributes/attribute[@name="attr_1"]/text()', xml_data::text));
+SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></employee>'::text, $$<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
+ <xsl:strip-space elements="*"/>
+ <xsl:param name="n1"/>
+ <xsl:param name="n2"/>
+ <xsl:param name="n3"/>
+ <xsl:param name="n4"/>
+ <xsl:param name="n5" select="'me'"/>
+ <xsl:template match="*">
+ <xsl:element name="samples">
+ <xsl:element name="sample">
+ <xsl:value-of select="$n1"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n2"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n3"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n4"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n5"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n6"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n7"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n8"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n9"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n10"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n11"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n12"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+</xsl:stylesheet>$$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text);
+ xslt_process
+------------------------
+ <samples> +
+ <sample>v1</sample> +
+ <sample>v2</sample> +
+ <sample>v3</sample> +
+ <sample>v4</sample> +
+ <sample>v5</sample> +
+ <sample>v6</sample> +
+ <sample>v7</sample> +
+ <sample>v8</sample> +
+ <sample>v9</sample> +
+ <sample>v10</sample>+
+ <sample>v11</sample>+
+ <sample>v12</sample>+
+ </samples> +
+
+(1 row)
+
diff --git a/contrib/xml2/expected/xml2_1.out b/contrib/xml2/expected/xml2_1.out
index 083fc3b2ca..fda626e08c 100644
--- a/contrib/xml2/expected/xml2_1.out
+++ b/contrib/xml2/expected/xml2_1.out
@@ -1,10 +1,4 @@
---
--- first, define the functions. Turn off echoing so that expected file
--- does not depend on contents of pgxml.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-RESET client_min_messages;
+CREATE EXTENSION xml2;
select query_to_xml('select 1 as x',true,false,'');
query_to_xml
---------------------------------------------------------------
@@ -18,7 +12,7 @@ select query_to_xml('select 1 as x',true,false,'');
(1 row)
-select xslt_process( query_to_xml('select x from generate_series(1,5) as
+select xslt_process( query_to_xml('select x from generate_series(1,5) as
x',true,false,'')::text,
$$<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
@@ -107,3 +101,53 @@ values
Value</attribute></attributes>');
create index idx_xpath on t1 ( xpath_string
('/attributes/attribute[@name="attr_1"]/text()', xml_data::text));
+SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></employee>'::text, $$<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
+ <xsl:strip-space elements="*"/>
+ <xsl:param name="n1"/>
+ <xsl:param name="n2"/>
+ <xsl:param name="n3"/>
+ <xsl:param name="n4"/>
+ <xsl:param name="n5" select="'me'"/>
+ <xsl:template match="*">
+ <xsl:element name="samples">
+ <xsl:element name="sample">
+ <xsl:value-of select="$n1"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n2"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n3"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n4"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n5"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n6"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n7"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n8"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n9"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n10"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n11"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n12"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+</xsl:stylesheet>$$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text);
+ERROR: xslt_process() is not available without libxslt
diff --git a/contrib/xml2/pgxml.sql.in b/contrib/xml2/pgxml.sql.in
deleted file mode 100644
index 98d8f81b57..0000000000
--- a/contrib/xml2/pgxml.sql.in
+++ /dev/null
@@ -1,77 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/xml2/pgxml.sql.in,v 1.12 2010/03/01 18:07:59 tgl Exp $ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
---SQL for XML parser
-
-CREATE OR REPLACE FUNCTION xml_is_well_formed(text) RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
--- deprecated old name for xml_is_well_formed
-CREATE OR REPLACE FUNCTION xml_valid(text) RETURNS bool
-AS 'MODULE_PATHNAME', 'xml_is_well_formed'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xml_encode_special_chars(text) RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_string(text,text) RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text,text) RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_number(text,text) RETURNS float4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_bool(text,text) RETURNS boolean
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
--- List function
-
-CREATE OR REPLACE FUNCTION xpath_list(text,text,text) RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_list(text,text) RETURNS text
-AS 'SELECT xpath_list($1,$2,'','')'
-LANGUAGE SQL STRICT IMMUTABLE;
-
--- Wrapper functions for nodeset where no tags needed
-
-CREATE OR REPLACE FUNCTION xpath_nodeset(text,text)
-RETURNS text
-AS 'SELECT xpath_nodeset($1,$2,'''','''')'
-LANGUAGE SQL STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text)
-RETURNS text
-AS 'SELECT xpath_nodeset($1,$2,'''',$3)'
-LANGUAGE SQL STRICT IMMUTABLE;
-
--- Table function
-
-CREATE OR REPLACE FUNCTION xpath_table(text,text,text,text,text)
-RETURNS setof record
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT STABLE;
-
--- XSLT functions
-
-CREATE OR REPLACE FUNCTION xslt_process(text,text,text)
-RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT VOLATILE;
-
--- the function checks for the correct argument count
-CREATE OR REPLACE FUNCTION xslt_process(text,text)
-RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
diff --git a/contrib/xml2/sql/xml2.sql b/contrib/xml2/sql/xml2.sql
index 73723b6be1..4a996af716 100644
--- a/contrib/xml2/sql/xml2.sql
+++ b/contrib/xml2/sql/xml2.sql
@@ -1,16 +1,8 @@
---
--- first, define the functions. Turn off echoing so that expected file
--- does not depend on contents of pgxml.sql.
---
-SET client_min_messages = warning;
-\set ECHO none
-\i pgxml.sql
-\set ECHO all
-RESET client_min_messages;
+CREATE EXTENSION xml2;
select query_to_xml('select 1 as x',true,false,'');
-select xslt_process( query_to_xml('select x from generate_series(1,5) as
+select xslt_process( query_to_xml('select x from generate_series(1,5) as
x',true,false,'')::text,
$$<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
@@ -80,3 +72,53 @@ Value</attribute></attributes>');
create index idx_xpath on t1 ( xpath_string
('/attributes/attribute[@name="attr_1"]/text()', xml_data::text));
+
+SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></employee>'::text, $$<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
+ <xsl:strip-space elements="*"/>
+ <xsl:param name="n1"/>
+ <xsl:param name="n2"/>
+ <xsl:param name="n3"/>
+ <xsl:param name="n4"/>
+ <xsl:param name="n5" select="'me'"/>
+ <xsl:template match="*">
+ <xsl:element name="samples">
+ <xsl:element name="sample">
+ <xsl:value-of select="$n1"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n2"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n3"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n4"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n5"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n6"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n7"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n8"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n9"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n10"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n11"/>
+ </xsl:element>
+ <xsl:element name="sample">
+ <xsl:value-of select="$n12"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+</xsl:stylesheet>$$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text);
diff --git a/contrib/xml2/uninstall_pgxml.sql b/contrib/xml2/uninstall_pgxml.sql
deleted file mode 100644
index 09441ef01f..0000000000
--- a/contrib/xml2/uninstall_pgxml.sql
+++ /dev/null
@@ -1,33 +0,0 @@
-/* $PostgreSQL: pgsql/contrib/xml2/uninstall_pgxml.sql,v 1.4 2007/11/13 04:24:29 momjian Exp $ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION xslt_process(text,text);
-
-DROP FUNCTION xslt_process(text,text,text);
-
-DROP FUNCTION xpath_table(text,text,text,text,text);
-
-DROP FUNCTION xpath_nodeset(text,text,text);
-
-DROP FUNCTION xpath_nodeset(text,text);
-
-DROP FUNCTION xpath_list(text,text);
-
-DROP FUNCTION xpath_list(text,text,text);
-
-DROP FUNCTION xpath_bool(text,text);
-
-DROP FUNCTION xpath_number(text,text);
-
-DROP FUNCTION xpath_nodeset(text,text,text,text);
-
-DROP FUNCTION xpath_string(text,text);
-
-DROP FUNCTION xml_encode_special_chars(text);
-
--- deprecated old name for xml_is_well_formed
-DROP FUNCTION xml_valid(text);
-
-DROP FUNCTION xml_is_well_formed(text);
diff --git a/contrib/xml2/xml2--1.0.sql b/contrib/xml2/xml2--1.0.sql
new file mode 100644
index 0000000000..bc27dc89ca
--- /dev/null
+++ b/contrib/xml2/xml2--1.0.sql
@@ -0,0 +1,70 @@
+/* contrib/xml2/xml2--1.0.sql */
+
+--SQL for XML parser
+
+-- deprecated old name for xml_is_well_formed
+CREATE FUNCTION xml_valid(text) RETURNS bool
+AS 'xml_is_well_formed'
+LANGUAGE INTERNAL STRICT STABLE;
+
+CREATE FUNCTION xml_encode_special_chars(text) RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION xpath_string(text,text) RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION xpath_nodeset(text,text,text,text) RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION xpath_number(text,text) RETURNS float4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION xpath_bool(text,text) RETURNS boolean
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+-- List function
+
+CREATE FUNCTION xpath_list(text,text,text) RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION xpath_list(text,text) RETURNS text
+AS 'SELECT xpath_list($1,$2,'','')'
+LANGUAGE SQL STRICT IMMUTABLE;
+
+-- Wrapper functions for nodeset where no tags needed
+
+CREATE FUNCTION xpath_nodeset(text,text)
+RETURNS text
+AS 'SELECT xpath_nodeset($1,$2,'''','''')'
+LANGUAGE SQL STRICT IMMUTABLE;
+
+CREATE FUNCTION xpath_nodeset(text,text,text)
+RETURNS text
+AS 'SELECT xpath_nodeset($1,$2,'''',$3)'
+LANGUAGE SQL STRICT IMMUTABLE;
+
+-- Table function
+
+CREATE FUNCTION xpath_table(text,text,text,text,text)
+RETURNS setof record
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT STABLE;
+
+-- XSLT functions
+
+CREATE FUNCTION xslt_process(text,text,text)
+RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT VOLATILE;
+
+-- the function checks for the correct argument count
+CREATE FUNCTION xslt_process(text,text)
+RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
diff --git a/contrib/xml2/xml2--unpackaged--1.0.sql b/contrib/xml2/xml2--unpackaged--1.0.sql
new file mode 100644
index 0000000000..1aa894a619
--- /dev/null
+++ b/contrib/xml2/xml2--unpackaged--1.0.sql
@@ -0,0 +1,26 @@
+/* contrib/xml2/xml2--unpackaged--1.0.sql */
+
+ALTER EXTENSION xml2 ADD function xslt_process(text,text);
+ALTER EXTENSION xml2 ADD function xslt_process(text,text,text);
+ALTER EXTENSION xml2 ADD function xpath_table(text,text,text,text,text);
+ALTER EXTENSION xml2 ADD function xpath_nodeset(text,text,text);
+ALTER EXTENSION xml2 ADD function xpath_nodeset(text,text);
+ALTER EXTENSION xml2 ADD function xpath_list(text,text);
+ALTER EXTENSION xml2 ADD function xpath_list(text,text,text);
+ALTER EXTENSION xml2 ADD function xpath_bool(text,text);
+ALTER EXTENSION xml2 ADD function xpath_number(text,text);
+ALTER EXTENSION xml2 ADD function xpath_nodeset(text,text,text,text);
+ALTER EXTENSION xml2 ADD function xpath_string(text,text);
+ALTER EXTENSION xml2 ADD function xml_encode_special_chars(text);
+ALTER EXTENSION xml2 ADD function xml_valid(text);
+
+-- xml_valid is now an alias for core xml_is_well_formed()
+
+CREATE OR REPLACE FUNCTION xml_valid(text) RETURNS bool
+AS 'xml_is_well_formed'
+LANGUAGE INTERNAL STRICT STABLE;
+
+-- xml_is_well_formed is now in core, not needed in extension.
+-- be careful to drop extension's copy not core's.
+
+DROP FUNCTION @extschema@.xml_is_well_formed(text);
diff --git a/contrib/xml2/xml2.control b/contrib/xml2/xml2.control
new file mode 100644
index 0000000000..51de678d5f
--- /dev/null
+++ b/contrib/xml2/xml2.control
@@ -0,0 +1,6 @@
+# xml2 extension
+comment = 'XPath querying and XSLT'
+default_version = '1.0'
+module_pathname = '$libdir/pgxml'
+# non-relocatable because xml2--unpackaged--1.0.sql needs to use @extschema@
+relocatable = false
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index dbf0b76f92..44c600e134 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.30 2010/07/06 19:18:55 momjian Exp $
+ * contrib/xml2/xpath.c
*
* Parser interface for DOM-based parser (libxml) rather than
* stream-based SAX-type parser
@@ -40,6 +40,15 @@ Datum xpath_table(PG_FUNCTION_ARGS);
void pgxml_parser_init(void);
+/* workspace for pgxml_xpath() */
+
+typedef struct
+{
+ xmlDocPtr doctree;
+ xmlXPathContextPtr ctxt;
+ xmlXPathObjectPtr res;
+} xpath_workspace;
+
/* local declarations */
static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
@@ -51,7 +60,10 @@ static text *pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar *toptag,
static xmlChar *pgxml_texttoxmlchar(text *textstring);
-static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath);
+static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath,
+ xpath_workspace *workspace);
+
+static void cleanup_workspace(xpath_workspace *workspace);
/*
@@ -71,7 +83,14 @@ pgxml_parser_init(void)
}
-/* Returns true if document is well-formed */
+/*
+ * Returns true if document is well-formed
+ *
+ * Note: this has been superseded by a core function. We still have to
+ * have it in the contrib module so that existing SQL-level references
+ * to the function won't fail; but in normal usage with up-to-date SQL
+ * definitions for the contrib module, this won't be called.
+ */
PG_FUNCTION_INFO_V1(xml_is_well_formed);
@@ -214,25 +233,22 @@ PG_FUNCTION_INFO_V1(xpath_nodeset);
Datum
xpath_nodeset(PG_FUNCTION_ARGS)
{
- xmlChar *xpath,
- *toptag,
- *septag;
- int32 pathsize;
- text *xpathsupp,
- *xpres;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
+ text *document = PG_GETARG_TEXT_P(0);
+ text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
+ xmlChar *toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
+ xmlChar *septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
+ xmlChar *xpath;
+ text *xpres;
+ xmlXPathObjectPtr res;
+ xpath_workspace workspace;
- toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
- septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
+ xpath = pgxml_texttoxmlchar(xpathsupp);
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
+ res = pgxml_xpath(document, xpath, &workspace);
- xpath = pgxml_texttoxmlchar(xpathsupp);
+ xpres = pgxml_result_to_text(res, toptag, septag, NULL);
- xpres = pgxml_result_to_text(pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
- toptag, septag, NULL);
+ cleanup_workspace(&workspace);
pfree(xpath);
@@ -250,23 +266,21 @@ PG_FUNCTION_INFO_V1(xpath_list);
Datum
xpath_list(PG_FUNCTION_ARGS)
{
- xmlChar *xpath,
- *plainsep;
- int32 pathsize;
- text *xpathsupp,
- *xpres;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
+ text *document = PG_GETARG_TEXT_P(0);
+ text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
+ xmlChar *plainsep = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
+ xmlChar *xpath;
+ text *xpres;
+ xmlXPathObjectPtr res;
+ xpath_workspace workspace;
- plainsep = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
+ xpath = pgxml_texttoxmlchar(xpathsupp);
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
+ res = pgxml_xpath(document, xpath, &workspace);
- xpath = pgxml_texttoxmlchar(xpathsupp);
+ xpres = pgxml_result_to_text(res, NULL, NULL, plainsep);
- xpres = pgxml_result_to_text(pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
- NULL, NULL, plainsep);
+ cleanup_workspace(&workspace);
pfree(xpath);
@@ -281,13 +295,13 @@ PG_FUNCTION_INFO_V1(xpath_string);
Datum
xpath_string(PG_FUNCTION_ARGS)
{
+ text *document = PG_GETARG_TEXT_P(0);
+ text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
xmlChar *xpath;
int32 pathsize;
- text *xpathsupp,
- *xpres;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
+ text *xpres;
+ xmlXPathObjectPtr res;
+ xpath_workspace workspace;
pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
@@ -298,13 +312,16 @@ xpath_string(PG_FUNCTION_ARGS)
/* We could try casting to string using the libxml function? */
xpath = (xmlChar *) palloc(pathsize + 9);
- memcpy((char *) (xpath + 7), VARDATA(xpathsupp), pathsize);
strncpy((char *) xpath, "string(", 7);
+ memcpy((char *) (xpath + 7), VARDATA(xpathsupp), pathsize);
xpath[pathsize + 7] = ')';
xpath[pathsize + 8] = '\0';
- xpres = pgxml_result_to_text(pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
- NULL, NULL, NULL);
+ res = pgxml_xpath(document, xpath, &workspace);
+
+ xpres = pgxml_result_to_text(res, NULL, NULL, NULL);
+
+ cleanup_workspace(&workspace);
pfree(xpath);
@@ -319,21 +336,17 @@ PG_FUNCTION_INFO_V1(xpath_number);
Datum
xpath_number(PG_FUNCTION_ARGS)
{
+ text *document = PG_GETARG_TEXT_P(0);
+ text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
xmlChar *xpath;
- int32 pathsize;
- text *xpathsupp;
float4 fRes;
-
xmlXPathObjectPtr res;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
-
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
+ xpath_workspace workspace;
xpath = pgxml_texttoxmlchar(xpathsupp);
- res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath);
+ res = pgxml_xpath(document, xpath, &workspace);
+
pfree(xpath);
if (res == NULL)
@@ -341,6 +354,8 @@ xpath_number(PG_FUNCTION_ARGS)
fRes = xmlXPathCastToNumber(res);
+ cleanup_workspace(&workspace);
+
if (xmlXPathIsNaN(fRes))
PG_RETURN_NULL();
@@ -353,21 +368,17 @@ PG_FUNCTION_INFO_V1(xpath_bool);
Datum
xpath_bool(PG_FUNCTION_ARGS)
{
+ text *document = PG_GETARG_TEXT_P(0);
+ text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
xmlChar *xpath;
- int32 pathsize;
- text *xpathsupp;
int bRes;
-
xmlXPathObjectPtr res;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
-
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
+ xpath_workspace workspace;
xpath = pgxml_texttoxmlchar(xpathsupp);
- res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath);
+ res = pgxml_xpath(document, xpath, &workspace);
+
pfree(xpath);
if (res == NULL)
@@ -375,6 +386,8 @@ xpath_bool(PG_FUNCTION_ARGS)
bRes = xmlXPathCastToBoolean(res);
+ cleanup_workspace(&workspace);
+
PG_RETURN_BOOL(bRes);
}
@@ -383,49 +396,61 @@ xpath_bool(PG_FUNCTION_ARGS)
/* Core function to evaluate XPath query */
static xmlXPathObjectPtr
-pgxml_xpath(text *document, xmlChar *xpath)
+pgxml_xpath(text *document, xmlChar *xpath, xpath_workspace *workspace)
{
- xmlDocPtr doctree;
- xmlXPathContextPtr ctxt;
+ int32 docsize = VARSIZE(document) - VARHDRSZ;
xmlXPathObjectPtr res;
xmlXPathCompExprPtr comppath;
- int32 docsize;
- docsize = VARSIZE(document) - VARHDRSZ;
+ workspace->doctree = NULL;
+ workspace->ctxt = NULL;
+ workspace->res = NULL;
pgxml_parser_init();
- doctree = xmlParseMemory((char *) VARDATA(document), docsize);
- if (doctree == NULL)
+ workspace->doctree = xmlParseMemory((char *) VARDATA(document), docsize);
+ if (workspace->doctree == NULL)
return NULL; /* not well-formed */
- ctxt = xmlXPathNewContext(doctree);
- ctxt->node = xmlDocGetRootElement(doctree);
+ workspace->ctxt = xmlXPathNewContext(workspace->doctree);
+ workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
/* compile the path */
comppath = xmlXPathCompile(xpath);
if (comppath == NULL)
{
- xmlFreeDoc(doctree);
+ cleanup_workspace(workspace);
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"XPath Syntax Error");
}
/* Now evaluate the path expression. */
- res = xmlXPathCompiledEval(comppath, ctxt);
+ res = xmlXPathCompiledEval(comppath, workspace->ctxt);
+ workspace->res = res;
+
xmlXPathFreeCompExpr(comppath);
if (res == NULL)
- {
- xmlXPathFreeContext(ctxt);
- xmlFreeDoc(doctree);
+ cleanup_workspace(workspace);
- return NULL;
- }
- /* xmlFreeDoc(doctree); */
return res;
}
+/* Clean up after processing the result of pgxml_xpath() */
+static void
+cleanup_workspace(xpath_workspace *workspace)
+{
+ if (workspace->res)
+ xmlXPathFreeObject(workspace->res);
+ workspace->res = NULL;
+ if (workspace->ctxt)
+ xmlXPathFreeContext(workspace->ctxt);
+ workspace->ctxt = NULL;
+ if (workspace->doctree)
+ xmlFreeDoc(workspace->doctree);
+ workspace->doctree = NULL;
+}
+
static text *
pgxml_result_to_text(xmlXPathObjectPtr res,
xmlChar *toptag,
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
index 4c80732bb8..f8f7d7263f 100644
--- a/contrib/xml2/xslt_proc.c
+++ b/contrib/xml2/xslt_proc.c
@@ -1,5 +1,5 @@
/*
- * $PostgreSQL: pgsql/contrib/xml2/xslt_proc.c,v 1.21 2010/07/06 19:18:55 momjian Exp $
+ * contrib/xml2/xslt_proc.c
*
* XSLT processing functions (requiring libxslt)
*
@@ -41,9 +41,7 @@ Datum xslt_process(PG_FUNCTION_ARGS);
extern void pgxml_parser_init(void);
/* local defs */
-static void parse_params(const char **params, text *paramstr);
-
-#define MAXPARAMS 20 /* must be even, see parse_params() */
+static const char **parse_params(text *paramstr);
#endif /* USE_LIBXSLT */
@@ -57,7 +55,7 @@ xslt_process(PG_FUNCTION_ARGS)
text *doct = PG_GETARG_TEXT_P(0);
text *ssheet = PG_GETARG_TEXT_P(1);
text *paramstr;
- const char *params[MAXPARAMS + 1]; /* +1 for the terminator */
+ const char **params;
xsltStylesheetPtr stylesheet = NULL;
xmlDocPtr doctree;
xmlDocPtr restree;
@@ -69,11 +67,14 @@ xslt_process(PG_FUNCTION_ARGS)
if (fcinfo->nargs == 3)
{
paramstr = PG_GETARG_TEXT_P(2);
- parse_params(params, paramstr);
+ params = parse_params(paramstr);
}
else
+ {
/* No parameters */
+ params = (const char **) palloc(sizeof(char *));
params[0] = NULL;
+ }
/* Setup parser */
pgxml_parser_init();
@@ -139,22 +140,34 @@ xslt_process(PG_FUNCTION_ARGS)
#ifdef USE_LIBXSLT
-static void
-parse_params(const char **params, text *paramstr)
+static const char **
+parse_params(text *paramstr)
{
char *pos;
char *pstr;
- int i;
char *nvsep = "=";
char *itsep = ",";
+ const char **params;
+ int max_params;
+ int nparams;
pstr = text_to_cstring(paramstr);
+ max_params = 20; /* must be even! */
+ params = (const char **) palloc((max_params + 1) * sizeof(char *));
+ nparams = 0;
+
pos = pstr;
- for (i = 0; i < MAXPARAMS; i++)
+ while (*pos != '\0')
{
- params[i] = pos;
+ if (nparams >= max_params)
+ {
+ max_params *= 2;
+ params = (const char **) repalloc(params,
+ (max_params + 1) * sizeof(char *));
+ }
+ params[nparams++] = pos;
pos = strstr(pos, nvsep);
if (pos != NULL)
{
@@ -164,13 +177,12 @@ parse_params(const char **params, text *paramstr)
else
{
/* No equal sign, so ignore this "parameter" */
- /* We'll reset params[i] to NULL below the loop */
+ nparams--;
break;
}
- /* Value */
- i++;
- /* since MAXPARAMS is even, we still have i < MAXPARAMS */
- params[i] = pos;
+
+ /* since max_params is even, we still have nparams < max_params */
+ params[nparams++] = pos;
pos = strstr(pos, itsep);
if (pos != NULL)
{
@@ -178,13 +190,13 @@ parse_params(const char **params, text *paramstr)
pos++;
}
else
- {
- i++;
break;
- }
}
- params[i] = NULL;
+ /* Add the terminator marker; we left room for it in the palloc's */
+ params[nparams] = NULL;
+
+ return params;
}
#endif /* USE_LIBXSLT */