Thực ra đây không phải là câu trả lời mà là một lời giải thích ngắn gọn về cách tìm ra nguồn gốc của lỗi.
Trước hết, hãy tìm pgcrypto
phần mở rộng:
select e.extname, n.nspname
from pg_catalog.pg_extension e left join pg_catalog.pg_namespace n on n.oid = e.extnamespace;
Nó sẽ trả về một cái gì đó như:
╔════════════════════╤════════════╗
║ extname │ nspname ║
╠════════════════════╪════════════╣
║ plpgsql │ pg_catalog ║
║ adminpack │ pg_catalog ║
║ plpythonu │ pg_catalog ║
║ pg_stat_statements │ public ║
║ plpython3u │ pg_catalog ║
║ hstore │ public ║
║ uuid-ossp │ public ║
║ pg_trgm │ public ║
║ ltree │ public ║
║ tablefunc │ public ║
║ unaccent │ public ║
║ pgcrypto │ nd ║
╚════════════════════╧════════════╝
Vì vậy, pgcrypto
được cài đặt trong lược đồ nd
trong cơ sở dữ liệu của tôi.
Tiếp theo, chúng ta hãy nhìn vào search_path
tham số cung cấp thông tin nơi tìm kiếm các đối tượng DB:
show search_path;
╔═════════════════╗
║ search_path ║
╠═════════════════╣
║ "$user", public ║
╚═════════════════╝
Nó có nghĩa là các đối tượng sẽ được tìm kiếm trong lược đồ với tên của người dùng hiện tại và nếu không tìm thấy gì, trong lược đồ public
.
Cuối cùng, hãy kiểm tra người dùng hiện tại:
select current_user;
╔══════════════╗
║ current_user ║
╠══════════════╣
║ postgres ║
╚══════════════╝
Vì vậy, như bạn có thể thấy tiện ích mở rộng được cài đặt trong lược đồ nd
không thể tìm thấy bằng search_path
thực ra là postgres, public
và chúng tôi gặp lỗi:
select gen_salt('md5');
ERROR: function gen_salt(unknown) does not exist
LINE 1: select gen_salt('md5');
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Có một số cách để khắc phục sự cố này tùy thuộc vào các giá trị thực tế cho DB của bạn được đề cập ở trên.
Bạn có thể di chuyển tiện ích mở rộng sang một lược đồ khác như:
alter extension pgcrypto set schema public;
Bạn có thể thay đổi search_path
tùy chọn như:
set search_path to '"$user", public'; -- for the active session only
alter database your_db_name set search_path to '"$user", public'; -- permanently for the database
Cuối cùng, bạn có thể chỉ định rõ ràng lược đồ trong câu lệnh SQL:
select schema_where_it_installed.gen_salt('md5');
-- For my example:
select nd.gen_salt('md5');