Project: YugabyteDB (App Definition and Development / Database)
File: pg-extensions.md

title: PostgreSQL extensions headerTitle: PostgreSQL extensions linkTitle: PostgreSQL extensions description: Summary of supported PostgreSQL extensions summary: Reference for YSQL extensions menu: v2.16: identifier: explore-ysql-postgresql-extensions parent: explore-ysql-language-features weight: 4400 type: docs PostgreSQL extensions provide a way to extend the functionality of a database by bundling SQL objects into a package and using them as a unit. This page describes the PostgreSQL extensions supported by YugabyteDB. Extensions are either pre-bundled with YugabyteDB, or require installation: Pre-bundled* extensions are included in the standard YugabyteDB distribution and can be enabled in YSQL by running the statement. Requires installation* - you must install these extensions manually before you can enable them using CREATE EXTENSION. Refer to . For information about using a specific extension in YugabyteDB, use the Example links in the following tables. YugabyteDB supports the following , all of which are pre-bundled. | Module | Status | Description | Examples | | :-- | :-- | :- | : | | | Pre-bundled | Provides a means for logging execution plans of slow statements automatically. | | | | Pre-bundled | Provides the foreign-data wrapper file_fdw, which can be used to access data files in the server's file system. | | | | Pre-bundled | Provides several functions to determine similarities and distance between strings. | | | | Pre-bundled | Implements the hstore data type for storing sets of key-value pairs in a single PostgreSQL value. | | | | Pre-bundled | Checks user passwords whenever they are set with CREATE ROLE or ALTER ROLE. If a password is considered too weak, it is rejected. | | | | Pre-bundled | Provides various cryptographic functions. | | | | Pre-bundled| Provides a means for tracking execution statistics of all SQL statements executed by a server. | | | | Pre-bundled | Provides functions and operators for determining the similarity of alphanumeric text based on trigram matching, as well as index operator classes that support fast searching for similar strings. | | | | Pre-bundled | Provides the foreign-data wrapper postgres_fdw, which can be used to access data stored in external PostgreSQL servers. | | | |Pre-bundled | Lets you use the Server Programming Interface (SPI) to create user-defined functions and stored procedures in C, and to run YSQL queries directly against YugabyteDB. | | | | Pre-bundled | Provides information about the SSL certificate that the current client provided when connecting to PostgreSQL. | | | | Pre-bundled | Provides several table functions. For example, `normalrand()` creates values, picked using a pseudorandom generator, from an ideal normal distribution. You specify how many values you want, and the mean and standard deviation of the ideal distribution. You use it in the same way that you use `generateseries()` | | | | Pre-bundled | Provides functions to generate universally unique identifiers (UUIDs), and functions to produce certain special UUID constants. | | | Extension | Status | Description | Examples | | :-- | :-- | :- | : | | | Pre-bundled | Tweak execution plans using "hints", which are descriptions in the form of SQL comments. | | | | Pre-bundled | The PostgreSQL Audit Extension (pgAudit) provides detailed session and/or object audit logging via the standard PostgreSQL logging facility. | | | | Pre-bundled | A PostgreSQL query performance monitoring tool, based on the PostgreSQL pgstatstatements module. | | | | Pre-bundled | Provides compatibility with Oracle functions and packages that are either missing or implemented differently in YugabyteDB and PostgreSQL. This compatibility layer can help you port your Oracle applications to

| | | | Requires installation | Introduces the data type `hll`, which is a HyperLogLog data structure. | | If an extension is not pre-bundled, you need to install it manually before you can enable it using the statement. You can install only extensions that are supported by YugabyteDB. Currently, in a multi-node setup, you need to install the extension on every node in the cluster. In a read replica setup, install extensions on the primary instance, not on the read replica. Once installed, the extension replicates to the read replica. You cannot install new extensions in YugabyteDB Managed. If you need a database extension that is not pre-bundled with YugabyteDB added to a YugabyteDB Managed cluster, contact {{% support-cloud %}} with the names of the cluster and extension, or . Typically, extensions need three types of files: Shared library files (`<name>.so`) SQL files (`<name>--<version>.sql`) Control files (`<name>.control`) To install an extension, you need to copy these files into the respective directories of your YugabyteDB installation. Shared library files go in the `pkglibdir` directory, while SQL and control files go in the `extension` subdirectory of the `libdir` directory. You can obtain the installation files for the target extension in two ways: Build the extension from scratch following the extension's build instructions. Copy the files from an existing PostgreSQL installation. After copying the files, restart the cluster (or the respective node in a multi-node install). To find the directories where you install the extension files on your local installation, use the YugabyteDB `pg_config` executable. First, alias it to `ybpgconfig` by replacing `<yugabyte-path>` with the path to your YugabyteDB installation as follows: ```sh alias ybpgconfig=/<yugabyte-path>/postgres/bin/pg_config ``` List existing shared libraries with: ```sh ls "$(ybpgconfig --pkglibdir)" ``` List SQL and control files for already-installed extensions with: ```sh ls "$(ybpgconfig --sharedir)"/extension/ ``` The easiest way to install an extension is to copy the files from an existing PostgreSQL installation. Ideally, use the same version of the PostgreSQL extension as that used by YugabyteDB. To see the version of PostgreSQL used in your YugabyteDB installation, enter the following `ysqlsh` command: ```sh ./bin/ysqlsh --version ``` ```output psql (PostgreSQL) 11.2-YB-2.11.2.0-b0 ``` If you already have PostgreSQL (use version `11.2` for best YSQL compatibility) with the extension installed, you can find the extension's files as follows: ```sh ls "$(pg_config --pkglibdir)" | grep <name> ``` ```sh ls "$(pg_config --sharedir)"/extension/ | grep <name> ``` If you have multiple PostgreSQL versions installed, make sure you're selecting the correct `pg_config`. On an Ubuntu 18.04 environment with multiple PostgreSQL versions installed: ```sh pg_config --version ``` ```output PostgreSQL 13.0 (Ubuntu 13.0-1.pgdg18.04+1) ``` ```sh /usr/lib/postgresql/11/bin/pg_config --version ``` ```output PostgreSQL 11.9 (Ubuntu 11.9-1.pgdg18.04+1) ``` In this case, you should be using `/usr/lib/postgresql/11/bin/pg_config`. On CentOS, the correct path is `/usr/pgsql-11/bin/pg_config`. The PostgreSQL module provides a means for logging execution plans of slow statements automatically, without having to run EXPLAIN by hand. This is especially helpful for tracking down un-optimized queries in large applications. To enable the autoexplain extension, add `autoexplain` to `sharedpreloadlibraries` in the PostgreSQL server configuration parameters using the YB-TServer flag: ```sh --ysqlpgconfcsv="sharedpreloadlibraries=autoexplain" ``` Note that modifying `sharedpreloadlibraries` requires restarting the YB-TServer. You can customize the following auto_explain parameters: | Parameter | Description | Default | | : | : | : | | `logminduration` | Minimum statement execution time, in milliseconds, that will cause the statement's plan to be logged. Setting this to zero logs all plans. Minus-one (the default) disables logging. For example, if you set it to 250ms then all statements that run 250ms or longer will be logged. Only superusers can change this

| -1 | | `loganalyze` | Print EXPLAIN ANALYZE output, rather than just EXPLAIN output when an execution plan is logged. When on, per-plan-node timing occurs for all statements executed, whether or not they run long enough to actually get logged. This can have an extremely negative impact on performance. Turning off `logtiming` ameliorates the performance cost, at the price of obtaining less information. Only superusers can change this setting. | false | | `logbuffers` | Print buffer usage statistics when an execution plan is logged; equivalent to the BUFFERS option of EXPLAIN. Has no effect unless `loganalyze` is enabled. Only superusers can change this setting. | false | | `logtiming` | Print per-node timing information when an execution plan is logged; equivalent to the TIMING option of EXPLAIN. The overhead of repeatedly reading the system clock can slow down queries significantly on some systems, so it may be beneficial to set this parameter to off when only actual row counts, and not exact times, are needed. Has no effect unless `loganalyze` is enabled. Only superusers can change this setting. | true | | `logtriggers` | Include trigger execution statistics when an execution plan is logged. Has no effect unless `loganalyze` is enabled. Only superusers can change this setting. | false | | `log_verbose` | Print verbose details when an execution plan is logged; equivalent to the VERBOSE option of EXPLAIN. Only superusers can change this setting. | false | | `log_format` | The format of the EXPLAIN output. Allowed values are `text`, `xml`, `json`, and `yaml`. Only superusers can change this setting. | text | | `lognestedstatements` | Consider nested statements (statements executed inside a function) for logging. When off, only top-level query plans are logged. Only superusers can change this setting. | false | | `sample_rate` | Explain only a set fraction of the statements in each session. The default 1 means explain all the queries. In case of nested statements, either all will be explained or none. Only superusers can change this setting. | 1 | Note that the default behavior is to do nothing, so you must set at least `autoexplain.logmin_duration` if you want any results. To change auto_explain parameters, use the SET statement. For example: ```sql SET autoexplain.logmin_duration = 0; SET autoexplain.loganalyze = true; SELECT count(*) FROM pgclass, pgindex WHERE oid = indrelid AND indisunique; ``` This produces log output similar to the following in the PostgreSQL log file in the `tserver/logs` directory: ```output LOG: duration: 316.556 ms plan: Query Text: SELECT count(*) FROM pgclass, pgindex WHERE oid = indrelid AND indisunique; Aggregate (cost=216.39..216.40 rows=1 width=8) (actual time=316.489..316.489 rows=1 loops=1) -> Nested Loop (cost=0.00..213.89 rows=1000 width=0) (actual time=10.828..316.200 rows=110 loops=1) -> Seq Scan on pg_index (cost=0.00..100.00 rows=1000 width=4) (actual time=7.465..8.068 rows=110 loops=1) Remote Filter: indisunique -> Index Scan using pgclassoidindex on pgclass (cost=0.00..0.11 rows=1 width=4) (actual time=2.673..2.673 rows=1 loops=110) Index Cond: (oid = pg_index.indrelid) ``` First, install the extension: ```sql CREATE EXTENSION file_fdw; ``` Create a foreign server: ```sql CREATE SERVER myserver FOREIGN DATA WRAPPER filefdw; ``` Now, you can create foreign tables that access data from files. For example: ```sql CREATE FOREIGN TABLE employees (id int, employeename varchar) SERVER myserver OPTIONS (filename 'employees.csv', format 'csv'); ``` You can execute `SELECT` statements on the foreign tables to access the data in the corresponding

```sql CREATE EXTENSION fuzzystrmatch; SELECT levenshtein('Yugabyte', 'yugabyte'), metaphone('yugabyte', 8); ``` ```output levenshtein | metaphone -+-- 2 | YKBT (1 row) ``` To enable the passwordcheck extension, add `passwordcheck` to `sharedpreloadlibraries` in the PostgreSQL server configuration parameters using the YB-TServer flag: ```sh --ysqlpgconfcsv="sharedpreload_libraries=passwordcheck" ``` You can customize the following passwordcheck parameters: | Parameter | Description | Default | | : | : | : | | minimum_length | Minimum password length. | 8 | | maximum_length | Maximum password length. | 15 | | restrict_lower | Passwords must include a lowercase character. | true | | restrict_upper | Passwords must include an uppercase character. | true | | restrict_numbers | Passwords must include a number. | true | | restrict_special | Passwords must include a special character. | true | | specialchars | The set of special characters. | <code>!@#$%^&*()+{}\|\<\>?=</code> | You can change passwordcheck parameters using a `SET` statement. For example, to increase the maximum length allowed and not require numbers, execute the following commands: ```sql SET passwordcheck.maximum_length TO 20; SET passwordcheck.restrict_numbers TO false; ``` When enabled, if a password is considered too weak, it's rejected with an error. For example: ```sql yugabyte=# create role test_role password 'tooshrt'; ``` ```output ERROR: password is too short ``` ```sql yugabyte=# create role test_role password 'nonumbers'; ``` ```output ERROR: password must contain both letters and nonletters ``` ```sql yugabyte=# create role testrole password '12testrole12'; ``` ```output ERROR: password must not contain user name ``` The passwordcheck extension only works for passwords that are provided in plain text. For more information, refer to the . ```sql CREATE EXTENSION pgcrypto; CREATE TABLE pgcryptoexample(id uuid PRIMARY KEY DEFAULT genrandom_uuid(), content text, digest text); INSERT INTO pgcrypto_example (content, digest) values ('abc', digest('abc', 'sha1')); SELECT * FROM pgcrypto_example; ``` ```output id | content | digest --++-- b8f2e2f7-0b8d-4d26-8902-fa4f5277869d | abc | \xa9993e364706816aba3e25717850c26c9cd0d89d (1 row) ``` ```sql CREATE EXTENSION pgstatstatements; SELECT query, calls, totaltime, mintime, maxtime, meantime, stddevtime, rows FROM pgstat_statements; ``` To get the output of `pgstatstatements` in JSON format, visit `https://<yb-tserver-ip>:13000/statements` in your web browser, where `<yb-tserver-ip>` is the IP address of any YB-TServer node in your cluster. For more information on using pgstatstatements in YugabyteDB, refer to . YugabyteDB supports the following four (of five &mdash; `timetravel` is not currently supported) extensions provided in the `spi` module: `autoinc` functions auto-increment fields. `insert_username` functions track who changed a table. `moddatetime` functions track last modification times. `refint` functions implement referential integrity. Set up a table with triggers for tracking modification time and user (role). Connect using `ysqlsh` and run the following commands: ```sql CREATE EXTENSION insert_username; CREATE EXTENSION moddatetime; CREATE TABLE spi_test ( id int primary key, content text, username text not null, moddate timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL ); CREATE TRIGGER insert_usernames BEFORE INSERT OR UPDATE ON spi_test FOR EACH ROW EXECUTE PROCEDURE insert_username (username); CREATE TRIGGER update_moddatetime BEFORE UPDATE ON spi_test FOR EACH ROW EXECUTE PROCEDURE moddatetime (moddate); ``` Insert some rows. Each insert should add the current role as `username` and the current timestamp as `moddate`. ```sql SET ROLE yugabyte; INSERT INTO spi_test VALUES(1, 'desc1'); SET ROLE postgres; INSERT INTO spi_test VALUES(2, 'desc2'); INSERT INTO spi_test VALUES(3, 'desc3'); SET ROLE yugabyte; INSERT INTO spi_test VALUES(4, 'desc4'); SELECT * FROM spi_test ORDER BY id; ``` ```output id | content | username | moddate -++-+- 1 | desc1 | yugabyte | 2019-09-13 16:55:53.969907 2 | desc2 | postgres | 2019-09-13 16:55:53.983306 3 | desc3 | postgres | 2019-09-13 16:55:53.98658 4 | desc4 | yugabyte | 2019-09-13 16:55:53.991315 (4 rows) ``` The `yugabyte` and (for compatibility) `postgres` YSQL users are created by default. Update some rows. This should update both `username` and `moddate` accordingly. ```sql UPDATE spitest SET content = 'desc1updated' WHERE id = 1; UPDATE spitest SET content = 'desc3updated' WHERE id = 3; SELECT * FROM spi_test ORDER BY id; ``` ```output id | content | username | moddate -++-+- 1 | desc1_updated | yugabyte | 2019-09-13

2 | desc2 | postgres | 2019-09-13 16:55:53.983306 3 | desc3_updated | yugabyte | 2019-09-13 16:56:27.634099 4 | desc4 | yugabyte | 2019-09-13 16:55:53.991315 (4 rows) ``` ```sql CREATE EXTENSION tablefunc; CREATE TABLE t(k int primary key, v double precision); PREPARE insertkv_pairs(int) AS INSERT INTO t(k, v) SELECT generate_series(1, $1), normal_rand($1, 1000.0, 10.0); ``` Test it as follows: ```sql DELETE FROM t; EXECUTE insertkv_pairs(10); SELECT k, to_char(v, '9999.99') AS v FROM t ORDER BY k; ``` You'll see results similar to the following: ```output k | v -+- 1 | 988.53 2 | 1005.18 3 | 1014.30 4 | 1000.92 5 | 999.51 6 | 1000.94 7 | 1007.45 8 | 991.22 9 | 987.95 10 | 996.57 (10 rows) ``` Every time you repeat the test, you'll see different generated values for `v`. For another example that uses `normal_rand()`, refer to . It populates a table with a large number (say 100,000) of rows and displays the outcome as a histogram that clearly shows the familiar bell-curve shape. `tablefunc` also provides the `connectby()`, `crosstab()`, and `crosstabN()` functions. The `connectby()` function displays a hierarchy of the kind that you see in an "employees" table with a reflexive foreign key constraint where "managerid" refers to "employeeid". Each next deeper level in the tree is indented from its parent following the well-known pattern. The `crosstab()`and `crosstabN()` functions produce "pivot" displays. The "N" in crosstabN() indicates the fact that a few, `crosstab1()`, `crosstab2()`, `crosstab3()`, are provided natively by the extension and that you can follow documented steps to create more. First, install the extension: ```sql CREATE EXTENSION postgres_fdw; ``` To connect to a remote YSQL or PostgreSQL database, create a foreign server object. Specify the connection information (except the username and password) using the `OPTIONS` clause: ```sql CREATE SERVER myserver FOREIGN DATA WRAPPER postgresfdw OPTIONS (host 'hostip', dbname 'externaldb', port 'port_number'); ``` Specify the username and password using `CREATE USER MAPPING`: ```sql CREATE USER MAPPING FOR mylocaluser SERVER myserver OPTIONS (user 'remoteuser', password 'password'); ``` You can now create foreign tables using `CREATE FOREIGN TABLE` and `IMPORT FOREIGN SCHEMA`: ```sql CREATE FOREIGN TABLE tablename (colname1 int, colname2 int) SERVER myserver OPTIONS (schemaname 'schema', tablename 'table'); IMPORT FOREIGN SCHEMA foreignschemaname FROM SERVER myserver INTO localschema_name; ``` You can execute `SELECT` statements on the foreign tables to access the data in the corresponding remote tables. First, install the extension: ```sql CREATE EXTENSION "uuid-ossp"; ``` Connect using `ysqlsh` and run the following: ```sql SELECT uuidgeneratev1(), uuidgeneratev4(), uuid_nil(); ``` ```output uuidgeneratev1 | uuidgeneratev4 | uuid_nil --+--+-- 69975ce4-d827-11e9-b860-bf2e5a7e1380 | 088a9b6c-46d8-4276-852b-64908b06a503 | 00000000-0000-0000-0000-000000000000 (1 row) ``` First, install `postgres-hll` locally in a PostgreSQL instance. Use the same PostgreSQL version as that incorporated into YugabyteDB. After you've installed the extension in PostgreSQL, copy the files to your YugabyteDB instance as follows: ```sh cp -v "$(pgconfig --pkglibdir)"/*hll*.so "$(ybpg_config --pkglibdir)" && cp -v "$(pgconfig --sharedir)"/extension/*hll*.sql "$(ybpg_config --sharedir)"/extension && cp -v "$(pgconfig --sharedir)"/extension/*hll*.control "$(ybpg_config --sharedir)"/extension && ./bin/ysqlsh -c "CREATE EXTENSION \"hll\";" ``` To run the example from the repository, connect using `ysqlsh` and run the following: ```sql yugabyte=# CREATE TABLE helloworld (id integer, set hll); CREATE TABLE Insert an empty HLL yugabyte=# INSERT INTO helloworld(id, set) VALUES (1, hll_empty()); INSERT 0 1 Add a hashed integer to the HLL yugabyte=# UPDATE helloworld SET set = hlladd(set, hllhash_integer(12345)) WHERE id = 1; UPDATE 1 Or add a hashed string to the HLL yugabyte=# UPDATE helloworld SET set = hlladd(set, hllhash_text('hello world')) WHERE id = 1; UPDATE 1 Get the cardinality of the HLL yugabyte=# SELECT hll_cardinality(set) FROM helloworld WHERE id = 1; ``` ```output hll_cardinality -- 2 (1 row) ```