PostgreSQL pgp_sym_encrypt() broken in version 9.1 - postgresql

The following works in PostgreSQL 8.4:
insert into credentials values('demo', pgp_sym_encrypt('password', 'longpassword'));
When I try it in version 9.1 I get this:
ERROR: function pgp_sym_encrypt(unknown, unknown) does not exist LINE
1: insert into credentials values('demo', pgp_sym_encrypt('pass...
^ HINT: No function matches the given name and argument types. You might need to add
explicit type casts.
*** Error ***
ERROR: function pgp_sym_encrypt(unknown, unknown) does not exist SQL
state: 42883 Hint: No function matches the given name and argument
types. You might need to add explicit type casts. Character: 40
If I try some explicit casts like this
insert into credentials values('demo', pgp_sym_encrypt(cast('password' as text), cast('longpassword' as text)))
I get a slightly different error message:
ERROR: function pgp_sym_encrypt(text, text) does not exist
I have pgcrypto installed. Does anyone have pgp_sym_encrypt() working in PostgreSQL 9.1?

On explanation could be that the module was installed into a schema that is not in your search path - or to the wrong database.
Diagnose your problem with this query and report back the output:
SELECT n.nspname, p.proname, pg_catalog.pg_get_function_arguments(p.oid) as params
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE p.proname ~~* '%pgp_sym_encrypt%'
AND pg_catalog.pg_function_is_visible(p.oid);
Finds functions in all schemas in your database. Similar to the psql meta-command
\df *pgp_sym_encrypt*

Make sure you install the extension on the desired schema.
sudo -i -u postgres
psql $database
CREATE EXTENSION pgcrypto;

OK, problem solved.
I was creating the pgcrypto extension as the first operation in the script. Then I dropped and added the VGDB database. That's why pgcrypto was there immediately after creating it, but didn't exist when running the sql later in the script or when I opened pgadmin.
This script is meant for setting up new databases and if I had tried it on a new database the create extension would have failed right away.
My bad. Thanks for the help, Erwin.

Just mention de schema where is installed pgcrypto like this:
#ColumnTransformer(forColumn = "TEST",
read = "public.pgp_sym_decrypt(TEST, 'password')",
write = "public.pgp_sym_encrypt(?, 'password')")
#Column(name = "TEST", columnDefinition = "bytea", nullable = false)
private String test;

I ran my (python) script again and the CREATE EXTENSION ran without error. The script also executes this command
psql -d VGDB -U postgres -c "select * from pg_available_extensions order by name"
which includes the following in the result set:
pgcrypto | 1.0 | 1.0 | cryptographic functions
So psql believes that it has installed pgcrypto.
Later in the same script when I execute
psql -d VGDB -U postgres -f sql/Create.Credentials.table.sql
where sql/Create.Credentials.table.sql includes this
insert into credentials values('demo', pgp_sym_encrypt('password', 'longpassword'));
I get this
psql:sql/Create.Credentials.table.sql:31: ERROR: function pgp_sym_encrypt(unknown, unknown) does not exist
LINE 1: insert into credentials values('demo', pgp_sym_encrypt('pass...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
When I open pgadmin it does not show pgcrypto in either the VGDB or postgres databases even though the query above called by psql shows that pgcrypto is installed.
Could there be an issue with needing to commit after using psql to execute the "create extension ..." command? None of my other DDL or SQL statements require a commit when they get executed with psql.
It's starting to look like psql is just flakey. Is there another way to call "create extension pgcrypto" - e.g. with Python's database support classes - or does that have to be run through psql?

Related

pg_dump / pg_restore error with extension cube

I've been running into an issue dumping and restoring one of my databases I think because of some extensions in the public schema. The extension that's throwing the error seems to be the Cube extension or the EarthDistance extension. This is the error I'm getting:
pg_restore: [archiver (db)] Error from TOC entry 2983;
pg_restore: [archiver (db)] could not execute query: ERROR: type "earth" does not exist
LINE 1: ...ians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth
QUERY: SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth
CONTEXT: SQL function "ll_to_earth" during inlining
Command was: REFRESH MATERIALIZED VIEW public.locationsearch
I was having a similarly different issue with some functions that I had written myself and the issue ended up being the search path, so explicitly setting the search path for those functions to public solved my issue. I tried the same with ll_to_earth but it seems the entire extension is the problem. I don't really want to try and install an extension to pg_catalog because that seems like poor practice.
This is my typical dump command:
pg_dump -U postgres -h ipAddress -p 5432 -w -F t database > database.tar
Followed by:
pg_restore -U postgres -h localhost -p 5432 -w -d postgres -C "database.tar"
The full dump with data is about 4gb, but I tried dumping just the schema with -s and -F p and interestingly this is the beginning:
--
-- PostgreSQL database dump
--
-- Dumped from database version 12.2
-- Dumped by pg_dump version 12.2
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: cube; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public;
--
-- Name: EXTENSION cube; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION cube IS 'data type for multidimensional cubes';
--
-- Name: earthdistance; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public;
--
-- Name: EXTENSION earthdistance; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION earthdistance IS 'calculate great-circle distances on the surface of the Earth';
I guess I'm confused by...logically, isn't this the same as it would be if I'd used the tar format? I know the issue is that when pg_restore gets to that materialized view and tries to use the function ll_to_earth(float8, float8) it fails because that function either isn't in its search path or hasn't been restored yet, but wouldn't this indicate that the extensions are the first thing to be restored? Can this be fixed?
This is part of a script I wrote that will dump the databases on my production environment and restore the databases on my test environment daily so that they match. It worked for months until I started using this extension, and I'm lost on how to rectify it.
For security reasons, pg_dump sets the search_path empty, so only objects in the system schema pg_catalog will be found if they are referenced without schema qualification.
Now your SQL functions uses the data type earth without the schema (probably public), so you get the error message.
You will have to change the function to use qualified names like public.earth for extension objects. Alternatively, and probably better, is to fix the search_path for the function:
ALTER FUNCTION myfun SET search_path = public;
This is a good idea anyway, because otherwise your function will cease to work if a user changes search_path. Depending on the way your function is defined or used, this can even constitute a security problem (which is why pg_dump does it this way).
I found a way around in this answer. I create extensions in pg_catalog scheme, which is as documentation states always effectively part of the search path.
CREATE EXTENSION IF NOT EXISTS cube SCHEMA pg_catalog;
CREATE EXTENSION IF NOT EXISTS earthdistance SCHEMA pg_catalog;
People consider this a bad practice, because it might pollute system catalog etc. But it serves me well in my use case - now I can pg_dump/pg_restore without worries.
Note: I found this thread containing a patch for earthdistance extension. Unfortunately it hasn't been merged yet.
Had the same problem, however solutions above didn't work. During data insertion I got the following error
ERROR: type "earth" does not exist
LINE 1: ...ians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth
QUERY: SELECT cube(cube(cube(earth()*cos(radians($1))*cos(radians($2))),earth()*cos(radians($1))*sin(radians($2))),earth()*sin(radians($1)))::earth
CONTEXT: SQL function "ll_to_earth" during inlining
In pgdump file I had to replace the following line (at the top of the file)
SELECT pg_catalog.set_config('search_path', '', false);
With
SELECT pg_catalog.set_config('search_path', 'public', false);

pg_restore fails when trying to create function referencing table that does not exist yet

I've used pg_dump --no-privileges --format custom --compress=0 some_database > my-dump.pgdump to dump a database, but I'm running into issues when I try to restore it.
Specifically, it appears to be loading function definitions before table definitions:
$ pg_restore ./my-dump.pgdump
…
create function my_function() returns …
language sql $$
select …
from some_table
where …
$$;
… later in the dump …
create table some_table ( … );
…
Which causes an error when I try to restore the dump:
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 4863; 0 16735 TABLE DATA some_table some_database
pg_restore: [archiver (db)] COPY failed for table "some_table": ERROR: relation "some_table" does not exist
LINE 3: from some_table
^
QUERY:
select …
from some_table
where …
CONTEXT: SQL function "my_function" during inlining
What's going on here? How can I trick pg_dump / pg_restore into doing things in the correct order?
Check your dump file for commands which mess with search_path, for example:
SELECT pg_catalog.set_config('search_path', '', false);
I encountered the same kind error as you (relation xxx does not exist ... during inlining) in a legacy project I inherited, even though it's running PostgreSQL 9.4.x.
I traced it to the above command.
The solution for me was to remove this command from the dump file.
After I did this I was able to restore the database without errors.
Note: the OP is using the custom format. There is no editing the binary file that is emitted.
In my experience, pg_dump using the custom format (-Fc) doesn't set check_function_bodies = false. But since it adds random functions at the top of the dump file (instead of putting all routines at the end), this causes pg_restore to barf.
I was able to workaround this issue by setting PGOPTIONS:
export PGOPTIONS="-c check_function_bodies=false"
pg_restore ...
That is strange. Ever since commit ef88199f611e625b496ff92aa17a447d254b9796 in 2003, pg_dump and pg_restore have emitted
SET check_function_bodies = false;
This setting makes sure that an error like you describe won't happen, because PostgreSQL won't check the validity of the function bodies.
Are you using an ancient PostgreSQL version or are you doing anything else that could mess with that?
If you run pg_restore on your dump (without specifying a destination database), does it emit the line?

AWS RDS PostgreSQL 9.5.4 Extension postgis_tiger_geocoder Missing Soundex?

I am attempting to install the AWS "Approved" PostgreSql Extension on our on large RDS instance but every time I at the point I attempt to 'create extension postgis_tiger_geocoder' I get this:
SQL Error [42883]: ERROR: function soundex(character varying) does not exist
I have spent a good bit of time reading the AWS / postgis / postgresql forums but unfortunately haven't found the writing on the wall.
Steps Taken
Installed the POSTGIS extension
create EXTENSION postgis;
Installed the FuzzyStrMatch Extension which contains the soundex function (verified)
create EXTENSION fuzzystrmatch;
Finally when I run this create extension I get the error above
create extension postgis_tiger_geocoder;
SQL Error [42883]: ERROR: function soundex(character varying) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 57558
org.postgresql.util.PSQLException: ERROR: function soundex(character varying) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 57558
Things I have tried:
set search_path = <schema_name>, public
Followed here:
Installing PostgreSQL Extension to all schemas
Dug deeply into postgis installation documentation
Read through RDS documentation on adding Extensions...
If anyone has had to deal with this frustration on AWS I will happily swap a few of the remaining hairs left on my head as I have not been able to work around this.
Results of \dx+
Objects in extension "fuzzystrmatch"
Object Description
--------------------------------------------------------------------------------
function <schema>.difference(...)
function <schema>.dmetaphone_alt(...)
function <schema>.dmetaphone(...)
function <schema>.levenshtein_less_equal(...)
function <schema>.levenshtein_less_equal(...)
function <schema>.levenshtein(...)
function <schema>.levenshtein(...)
function <schema>.metaphone(...)
function <schema>.soundex(...)
function <schema>.text_soundex(...)
(10 rows)
Results of \dfS+ soundex
List of functions
Schema | Name | Result data type | Argument data types | Type | Volatility | Owner | Security | Access privileges | Language | Source code | Description
--------+------+------------------+---------------------+------+------------+-------+----------+-------------------+----------+-------------+-------------
(0 rows)
Had the same problem, resolved it by altering search_path for database and reconnect before creating extension postgis_tiger_geocoder. Look for the FIX part :
-- Postgis Installation
------------------------------------------------------------------------------------------------------------------------------------------------
-- PostGIS AWS Configuration --
-- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.PostGIS --
------------------------------------------------------------------------------------------------------------------------------------------------
-- On postgis schema
SET SCHEMA '${POSTGIS_SCHEMA_NAME}';
-- Step 2: Load the PostGIS Extensions
create extension postgis;
create extension fuzzystrmatch;
-- FIX : To avoid "ERROR: function soundex(character varying) does not exist", change schema and reconnect
ALTER DATABASE ${DATABASE_NAME} SET search_path=${POSTGIS_SCHEMA_NAME};
\connect ${DATABASE_NAME};
-- End FIX
create extension postgis_tiger_geocoder;
create extension postgis_topology;
-- Step 3: Transfer Ownership of the Extensions to the rds_superuser Role
alter schema tiger owner to ${MASTER_USER};
alter schema tiger_data owner to ${MASTER_USER};
alter schema topology owner to ${MASTER_USER};
-- Step 4: Transfer Ownership of the Objects to the rds_superuser Role
CREATE FUNCTION exec(text) returns text language plpgsql volatile AS $f$ BEGIN EXECUTE $1; RETURN $1; END; $f$;
SELECT exec('ALTER TABLE ' || quote_ident(s.nspname) || '.' || quote_ident(s.relname) || ' OWNER TO ${MASTER_USER};')
FROM (
SELECT nspname, relname
FROM pg_class c JOIN pg_namespace n ON (c.relnamespace = n.oid)
WHERE nspname in ('tiger','topology') AND
relkind IN ('r','S','v') ORDER BY relkind = 'S')
s;
-- Adding postgis to default schema
ALTER DATABASE ${DATABASE_NAME} SET search_path=${SCHEMA_NAME},${POSTGIS_SCHEMA_NAME};
Had the same problem. Turns out that all the fuzzystrmatch's functions were created inside the wrong schema.
Connected with psql command line, I used the drop extension command to restart the process of creating the extensions:
drop extension postgis_topology;
drop extension postgis;
drop extension fuzzystrmatch;
Then, just to be sure, disconnected using \q.
Connected psql again.
Set the schema to public:
set schema 'public';
Then, follow the process described in AWS RDS Docs
create extension postgis;
create extension fuzzystrmatch;
create extension postgis_tiger_geocoder;
create extension postgis_topology;

Trouble installing additional module cube in PostgreSQL 8.4

I am trying to use PostgreSQL with the "Seven Databases in Seven Weeks" book. I am using PostgreSQL 8.4.1 on an Ubuntu 10.04 server.
The first task is to create a database named "book" and check if the contrib packages have been installed properly.
$ createdb book
$ psql book -c "SELECT '1'::cube;"
When I do that I get the following output:
ERROR: type "cube" does not exist
LINE 1: SELECT '1'::cube;
I already installed the cube package with the following command:
$ sudo -u postgres psql postgres < /usr/share/postgresql/8.4/contrib/cube.sql
I tried restarting PostgreSQL but the problem persists. When I tried running the package import a second time I got the following message, which explicitly states that type "cube" already exists:
SET
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
ERROR: type "cube" already exists
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
COMMENT
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
ERROR: operator < already exists
ERROR: operator > already exists
ERROR: operator <= already exists
ERROR: operator >= already exists
ERROR: operator && already exists
ERROR: operator = already exists
ERROR: operator <> already exists
ERROR: operator #> already exists
ERROR: operator <# already exists
ERROR: operator # already exists
ERROR: operator ~ already exists
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
ERROR: operator class "cube_ops" for access method "btree" already exists
ERROR: operator class "gist_cube_ops" for access method "gist" already exists
So, what am I doing wrong?
You only installed the extension to your postgres database (the default system database named "postgres") - which is probably not what you want. You need to install the extension to your database - once per database in which to use it.
Or you can install it to a template database (template1 by default, but any database can be used as template) so that every new database created starts out with the functionality pre-installed.
In PostgreSQL 8.4 or older, you need to run in the shell:
psql -d dbname -f SHAREDIR/contrib/cube.sql
Where dbname is the name of your actual target db. Or use the equivalent line that you have in your question.
More info for PostgreSQL 8.4 in the manual here.
Since PostgreSQL 9.1 this has been further simplified and you can just run in a database session:
CREATE extension cube
More in the manual here.
The full command for 9.1 is:
psql -d dbname
CREATE EXTENSION cube;
\q
Where dbname is the name of the database you want to add the extension to.
Note that the last command is a backlash q for quit. And don't forget the semicolon at the end of the second one.

How to generate uuid with PostgreSQL 8.4.4 on Ubuntu 10.04?

I am running PostgreSQL 8.4.4 with Ubuntu 10.04.
I am trying to generate uuid but can't find a way to do it.
I do have the uuid-ossp.sql in /usr/share/postgresql/8.4/contrib/uuid-ossp.sql
When I try this is what I get :
postgres=# SELECT uuid_generate_v1();
ERROR: function uuid_generate_v1() does not exist
LINE 1: SELECT uuid_generate_v1();
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Any idea ?
The stuff in contrib aren't run automatically. You have to run it yourself to install the functions. I don't know about the 8.4 version, but in the 8.3 version it appears to only install it per-database, so open up the database you're using in psql and issue the command \i /usr/share/postgresql/8.4/contrib/uuid-ossp.sql
I saw this in my PostgreSQL travels. It requires the pgcrypto contrib module.
CREATE OR REPLACE FUNCTION generate_uuid() RETURNS UUID AS
$$
SELECT ENCODE(GEN_RANDOM_BYTES(16), 'hex')::UUID
$$ LANGUAGE SQL IMMUTABLE;