mirror of https://github.com/postgres/postgres
commit
9090f12201
@ -0,0 +1,3 @@ |
||||
[submodule "contrib/pg_tde/src/libkmip"] |
||||
path = contrib/pg_tde/src/libkmip |
||||
url = https://github.com/Percona-Lab/libkmip.git |
@ -0,0 +1,14 @@ |
||||
*.so |
||||
*.o |
||||
*.frontend |
||||
__pycache__ |
||||
|
||||
/config.cache |
||||
/config.log |
||||
/config.status |
||||
/autom4te.cache |
||||
/configure~ |
||||
t/results |
||||
|
||||
# tools files |
||||
typedefs-full.list |
@ -0,0 +1,124 @@ |
||||
# Contributing guide |
||||
|
||||
Welcome to `pg_tde` - the Transparent Database Encryption for PostgreSQL! |
||||
|
||||
We're glad that you would like to become a Percona community member and participate in keeping open source open. |
||||
|
||||
You can contribute in one of the following ways: |
||||
|
||||
1. Reach us on our [Forums](https://forums.percona.com/c/postgresql/pg-tde-transparent-data-encryption-tde/82). |
||||
2. [Submit a bug report or a feature request](#submit-a-bug-report-or-a-feature-request) |
||||
3. [Submit a pull request (PR) with the code patch](#submit-a-pull-request) |
||||
4. [Contribute to documentation](#contributing-to-documentation) |
||||
|
||||
By contributing, you agree to the [Percona Community code of conduct](https://github.com/percona/community/blob/main/content/contribute/coc.md). |
||||
|
||||
|
||||
## Submit a bug report or a feature request |
||||
|
||||
All bug reports, enhancements and feature requests are tracked in [Jira issue tracker](https://jira.percona.com/projects/PG). If you would like to suggest a new feature / an improvement or you found a bug in `pg_tde`, please submit the report to the [PG project](https://jira.percona.com/projects/PG/issues). |
||||
|
||||
Start by searching the open tickets for a similar report. If you find that someone else has already reported your issue, then you can upvote that report to increase its visibility. |
||||
|
||||
If there is no existing report, submit your report following these steps: |
||||
|
||||
1. Sign in to [Jira issue tracker](https://jira.percona.com/projects/PG/issues). You will need to create an account if you do not have one. |
||||
2. In the _Summary_, _Description_, _Steps To Reproduce_, _Affects Version_ fields describe the problem you have detected or an idea that you have for a new feature or improvement. |
||||
3. As a general rule of thumb, try to create bug reports that are: |
||||
|
||||
* Reproducible: describe the steps to reproduce the problem. |
||||
* Unique: check if there already exists a JIRA ticket to describe the problem. |
||||
* Scoped to a Single Bug: only report one bug in one JIRA ticket |
||||
|
||||
## Submit a pull request |
||||
|
||||
Though not mandatory, we encourage you to first check for a bug report among Jira issues and in the PR list: perhaps the bug has already been addressed. |
||||
|
||||
For feature requests and enhancements, we do ask you to create a Jira issue, describe your idea and discuss the design with us. This way we align your ideas with our vision for the product development. |
||||
|
||||
If the bug hasn’t been reported / addressed, or we’ve agreed on the enhancement implementation with you, do the following: |
||||
|
||||
1. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) this repository |
||||
2. Clone this repository on your machine. |
||||
3. Create a separate branch for your changes. If you work on a Jira issue, please include the issue number in the branch name so it reads as `<JIRAISSUE>-my_branch`. This makes it easier to track your contribution. |
||||
4. Make your changes. Please follow the guidelines outlined in the [PostgreSQL Coding Standard](https://www.postgresql.org/docs/current/source.html) to improve code readability. |
||||
<details> |
||||
<summary>.vimrc configuration example</summary> |
||||
|
||||
``` |
||||
set nocompatible " choose no compatibility with legacy vi |
||||
syntax enableset |
||||
tabstop=4set |
||||
background=lightset |
||||
textwidth=80set |
||||
colorcolumn=80 |
||||
let g:filestyle_ignore_patterns = ['^\t* \{1,3}\S'] |
||||
highlight Normal ctermbg=15 |
||||
highlight ColorColumn ctermbg=52 |
||||
``` |
||||
</details> |
||||
|
||||
5. Test your changes locally. See the [Running tests ](#running-tests) section for more information |
||||
6. Update the documentation describing your changes. See the [Contributing to documentation](#contributing-to-documentation) section for details |
||||
7. Commit the changes. Add the Jira issue number at the beginning of your message subject, so that is reads as `<JIRAISSUE> : My commit message`. Follow this pattern for your commits: |
||||
|
||||
``` |
||||
PG-1234: Main commit message. |
||||
<Blank line> |
||||
Details of fix. |
||||
``` |
||||
|
||||
The [commit message guidelines](https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53) will help you with writing great commit messages |
||||
|
||||
8. Open a pull request to Percona |
||||
9. Our team will review your code and if everything is correct, will merge it. Otherwise, we will contact you for additional information or with the request to make changes. |
||||
|
||||
### Building pg_tde |
||||
|
||||
To build `pg_tde` from source code, you require the following: |
||||
|
||||
* git |
||||
* make |
||||
* gcc |
||||
* pg_config |
||||
|
||||
Refer to the [Building from source code](https://github.com/percona/pg_tde?tab=readme-ov-file#building-from-sources-for-community-postgresql) section for guidelines. |
||||
|
||||
|
||||
### Running tests |
||||
|
||||
When you work, you should periodically run tests to check that your changes don’t break existing code. |
||||
|
||||
You can find the tests in the `sql` directory. |
||||
|
||||
#### Run manually |
||||
|
||||
1. Change directory to pg_tde |
||||
|
||||
**NOTE**: Make sure `postgres` user is the owner of the `pg_tde` directory |
||||
|
||||
2. Start the tests |
||||
1. If you built PostgreSQL from PGDG, use the following command: |
||||
|
||||
```sh |
||||
make installcheck |
||||
``` |
||||
|
||||
|
||||
2. If you installed PostgreSQL server from Percona Distribution for PostgreSQL, use the following command: |
||||
|
||||
```sh |
||||
sudo su postgres bash -c 'make installcheck USE_PGXS=1' |
||||
``` |
||||
#### Run automatically |
||||
|
||||
The tests are run automatically with GitHub actions once you commit and push your changes. Make sure all tests are successfully passed before you proceed. |
||||
|
||||
|
||||
## Contributing to documentation |
||||
|
||||
`pg_tde` documentation is maintained in the `documentation` directory. Please read the [Contributing guide](https://github.com/percona/pg_tde/blob/main/documentation/CONTRIBUTING.md) for guidelines how you can contribute to the docs. |
||||
|
||||
## After your pull request is merged |
||||
|
||||
Once your pull request is merged, you are an official Percona Community Contributor. Welcome to the community! |
@ -0,0 +1,21 @@ |
||||
MIT License |
||||
|
||||
Copyright (c) 2024 Percona LLC |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -0,0 +1,91 @@ |
||||
# contrib/pg_tde/Makefile
|
||||
|
||||
PGFILEDESC = "pg_tde access method"
|
||||
MODULE_big = pg_tde
|
||||
EXTENSION = pg_tde
|
||||
DATA = pg_tde--1.0-beta2.sql
|
||||
|
||||
REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_tde/pg_tde.conf
|
||||
REGRESS = toast_decrypt_basic \
|
||||
toast_extended_storage_basic \ |
||||
move_large_tuples_basic \ |
||||
non_sorted_off_compact_basic \ |
||||
update_compare_indexes_basic \ |
||||
pg_tde_is_encrypted_basic \ |
||||
test_issue_153_fix_basic \ |
||||
multi_insert_basic \ |
||||
update_basic \ |
||||
subtransaction_basic \ |
||||
trigger_on_view_basic \ |
||||
change_access_method_basic \ |
||||
insert_update_delete_basic \ |
||||
keyprovider_dependency_basic \ |
||||
vault_v2_test_basic \ |
||||
alter_index_basic \ |
||||
merge_join_basic \ |
||||
tablespace_basic |
||||
TAP_TESTS = 1
|
||||
|
||||
OBJS = src/encryption/enc_tde.o \
|
||||
src/encryption/enc_aes.o \ |
||||
src/access/pg_tde_slot.o \ |
||||
src/access/pg_tde_tdemap.o \ |
||||
src$(MAJORVERSION)/access/pg_tde_io.o \ |
||||
src$(MAJORVERSION)/access/pg_tdeam_visibility.o \ |
||||
src$(MAJORVERSION)/access/pg_tdeam.o \ |
||||
src$(MAJORVERSION)/access/pg_tdetoast.o \ |
||||
src$(MAJORVERSION)/access/pg_tde_prune.o \ |
||||
src$(MAJORVERSION)/access/pg_tde_vacuumlazy.o \ |
||||
src$(MAJORVERSION)/access/pg_tde_visibilitymap.o \ |
||||
src$(MAJORVERSION)/access/pg_tde_rewrite.o \ |
||||
src$(MAJORVERSION)/access/pg_tdeam_handler.o \ |
||||
src/access/pg_tde_ddl.o \ |
||||
src/access/pg_tde_xlog.o \ |
||||
src/access/pg_tde_xlog_encrypt.o \ |
||||
src/transam/pg_tde_xact_handler.o \ |
||||
src/keyring/keyring_curl.o \ |
||||
src/keyring/keyring_file.o \ |
||||
src/keyring/keyring_vault.o \ |
||||
src/keyring/keyring_kmip.o \ |
||||
src/keyring/keyring_kmip_ereport.o \ |
||||
src/keyring/keyring_api.o \ |
||||
src/catalog/tde_global_space.o \ |
||||
src/catalog/tde_keyring.o \ |
||||
src/catalog/tde_keyring_parse_opts.o \ |
||||
src/catalog/tde_principal_key.o \ |
||||
src/common/pg_tde_shmem.o \ |
||||
src/common/pg_tde_utils.o \ |
||||
src/smgr/pg_tde_smgr.o \ |
||||
src/pg_tde_defs.o \ |
||||
src/pg_tde_event_capture.o \ |
||||
src/pg_tde.o \ |
||||
src/libkmip/libkmip/src/kmip.o \ |
||||
src/libkmip/libkmip/src/kmip_bio.o \ |
||||
src/libkmip/libkmip/src/kmip_locate.o \ |
||||
src/libkmip/libkmip/src/kmip_memset.o |
||||
|
||||
ifdef USE_PGXS |
||||
PG_CONFIG = pg_config
|
||||
PGXS := $(shell $(PG_CONFIG) --pgxs)
|
||||
override PG_CPPFLAGS += -I$(CURDIR)/src/include -I$(CURDIR)/src/libkmip/libkmip/include -I$(CURDIR)/src$(MAJORVERSION)/include
|
||||
include $(PGXS) |
||||
else |
||||
subdir = contrib/pg_tde
|
||||
top_builddir = ../..
|
||||
override PG_CPPFLAGS += -I$(top_srcdir)/$(subdir)/src/include -I$(top_srcdir)/$(subdir)/src/libkmip/libkmip/include -I$(top_srcdir)/$(subdir)/src$(MAJORVERSION)/include
|
||||
include $(top_builddir)/src/Makefile.global |
||||
include $(top_srcdir)/contrib/contrib-global.mk |
||||
endif |
||||
|
||||
override SHLIB_LINK += -lcurl -lcrypto -lssl
|
||||
|
||||
# Fetches typedefs list for PostgreSQL core and merges it with typedefs defined in this project.
|
||||
# https://wiki.postgresql.org/wiki/Running_pgindent_on_non-core_code_or_development_code
|
||||
update-typedefs: |
||||
wget -q -O - "https://buildfarm.postgresql.org/cgi-bin/typedefs.pl?branch=REL_17_STABLE" | cat - typedefs.list | sort | uniq > typedefs-full.list
|
||||
|
||||
# Indents projects sources.
|
||||
indent: |
||||
pgindent --typedefs=typedefs-full.list --excludes=pgindent_excludes .
|
||||
|
||||
.PHONY: update-typedefs indent |
@ -0,0 +1,23 @@ |
||||
TDE_OBJS = \
|
||||
src/access/pg_tde_tdemap.frontend \
|
||||
src/access/pg_tde_xlog_encrypt.frontend \
|
||||
src/catalog/tde_global_space.frontend \
|
||||
src/catalog/tde_keyring.frontend \
|
||||
src/catalog/tde_keyring_parse_opts.frontend \
|
||||
src/catalog/tde_principal_key.frontend \
|
||||
src/common/pg_tde_utils.frontend \
|
||||
src/encryption/enc_aes.frontend \
|
||||
src/encryption/enc_tde.frontend \
|
||||
src/keyring/keyring_api.frontend \
|
||||
src/keyring/keyring_curl.frontend \
|
||||
src/keyring/keyring_file.frontend \
|
||||
src/keyring/keyring_vault.frontend \
|
||||
src/keyring/keyring_kmip.frontend \
|
||||
src/keyring/keyring_kmip_ereport.frontend \
|
||||
src/libkmip/libkmip/src/kmip.frontend \
|
||||
src/libkmip/libkmip/src/kmip_bio.frontend \
|
||||
src/libkmip/libkmip/src/kmip_locate.frontend \
|
||||
src/libkmip/libkmip/src/kmip_memset.frontend
|
||||
|
||||
%.frontend: %.c |
||||
$(CC) $(CPPFLAGS) -c $< -o $@
|
@ -0,0 +1,172 @@ |
||||
[](https://scorecard.dev/viewer/?uri=github.com/percona/pg_tde) |
||||
[](https://forums.percona.com/) |
||||
|
||||
# pg_tde: Transparent Database Encryption for PostgreSQL |
||||
|
||||
The PostgreSQL extension provides data at rest encryption. It is currently in an experimental phase and is under active development. [We need your feedback!](https://github.com/percona/pg_tde/discussions/151) |
||||
|
||||
## Table of contents |
||||
1. [Overview](#overview) |
||||
2. [Documentation](#documentation) |
||||
1. [Percona Server for PostgreSQL](#percona-server-for-postgresql) |
||||
3. [Build from sources](#building-from-sources-for-community-postgresql) |
||||
4. [Run in docker](#run-in-docker) |
||||
5. [Setting up](#setting-up) |
||||
6. [Helper functions](#helper-functions) |
||||
|
||||
## Overview |
||||
Transparent Data Encryption offers encryption at the file level and solves the problem of protecting data at rest. The encryption is transparent for users allowing them to access and manipulate the data and not to worry about the encryption process. As a key provider, the extension supports the keyringfile and [Hashicorp Vault](https://www.vaultproject.io/). |
||||
|
||||
### This extension provides two `access methods` with different options: |
||||
|
||||
#### `tde_heap_basic` access method |
||||
- Works with community PostgreSQL 16 and 17 or with [Percona Server for PosgreSQL 17](https://docs.percona.com/postgresql/17/postgresql-server.html) |
||||
- Encrypts tuples and WAL |
||||
- **Doesn't** encrypt indexes, temporary files, statistics |
||||
- CPU expensive as it decrypts pages each time they are read from bufferpool |
||||
|
||||
#### `tde_heap` access method |
||||
- Works only with [Percona Server for PostgreSQL 17](https://docs.percona.com/postgresql/17/postgresql-server.html) |
||||
- Uses extended Storage Manager and WAL APIs |
||||
- Encrypts tuples, WAL and indexes |
||||
- **Doesn't** encrypt temporary files and statistics **yet** |
||||
- Faster and cheaper than `tde_heap_basic` |
||||
|
||||
## Documentation |
||||
|
||||
Full and comprehensive documentation about `pg_tde` is available at https://percona.github.io/pg_tde/. |
||||
|
||||
## Percona Server for PostgreSQL |
||||
|
||||
Percona provides binary packages of `pg_tde` extension only for Percona Server for PostgreSQL. Learn how to install them or build `pg_tde` from sources for PSPG in the [documentation](https://percona.github.io/pg_tde/main/install.html). |
||||
|
||||
## Building from sources for community PostgreSQL |
||||
1. Install required dependencies (replace XX with 16 or 17) |
||||
- On Debian and Ubuntu: |
||||
```sh |
||||
sudo apt install make gcc autoconf git libcurl4-openssl-dev postgresql-server-dev-XX |
||||
``` |
||||
|
||||
- On RHEL 8 compatible OS: |
||||
```sh |
||||
sudo yum install epel-release |
||||
yum --enablerepo=powertools install git make gcc autoconf libcurl-devel perl-IPC-Run redhat-rpm-config openssl-devel postgresqlXX-devel |
||||
``` |
||||
|
||||
- On MacOS: |
||||
```sh |
||||
brew install make autoconf curl gettext postresql@XX |
||||
``` |
||||
|
||||
2. Install or build postgresql 16 or 17 |
||||
3. If postgres is installed in a non standard directory, set the `PG_CONFIG` environment variable to point to the `pg_config` executable |
||||
|
||||
4. Clone the repository, build and install it with the following commands: |
||||
|
||||
```sh |
||||
git clone https://github.com/percona/pg_tde |
||||
``` |
||||
|
||||
5. Compile and install the extension |
||||
|
||||
```sh |
||||
cd pg_tde |
||||
make USE_PGXS=1 |
||||
sudo make USE_PGXS=1 install |
||||
``` |
||||
|
||||
## Run in Docker |
||||
|
||||
There is a [docker image](https://hub.docker.com/r/perconalab/pg_tde) with `pg_tde` based community [PostgreSQL 16](https://hub.docker.com/_/postgres) |
||||
|
||||
``` |
||||
docker run --name pg-tde -e POSTGRES_PASSWORD=mysecretpassword -d perconalab/pg_tde |
||||
``` |
||||
Docker file is available [here](https://github.com/percona/pg_tde/blob/main/docker/Dockerfile) |
||||
|
||||
|
||||
_See [Make Builds for Developers](https://github.com/percona/pg_tde/wiki/Make-builds-for-developers) for more info on the build infrastructure._ |
||||
|
||||
## Setting up |
||||
|
||||
1. Add extension to the `shared_preload_libraries`: |
||||
1. Via configuration file `postgresql.conf ` |
||||
``` |
||||
shared_preload_libraries=pg_tde |
||||
``` |
||||
2. Via SQL using [ALTER SYSTEM](https://www.postgresql.org/docs/current/sql-altersystem.html) command |
||||
```sql |
||||
ALTER SYSTEM SET shared_preload_libraries = 'pg_tde'; |
||||
``` |
||||
2. Start or restart the `postgresql` instance to apply the changes. |
||||
* On Debian and Ubuntu: |
||||
|
||||
```sh |
||||
sudo systemctl restart postgresql.service |
||||
``` |
||||
|
||||
* On RHEL 8 compatible OS (replace XX with your version): |
||||
```sh |
||||
sudo systemctl restart postgresql-XX.service |
||||
``` |
||||
3. [CREATE EXTENSION](https://www.postgresql.org/docs/current/sql-createextension.html) with SQL (requires superuser or a database owner privileges): |
||||
|
||||
```sql |
||||
CREATE EXTENSION pg_tde; |
||||
``` |
||||
4. Create a key provider. Currently `pg_tde` supports `File` and `Vault-V2` key providers. You can add the required key provider using one of the functions. |
||||
|
||||
|
||||
```sql |
||||
-- For Vault-V2 key provider |
||||
-- pg_tde_add_key_provider_vault_v2(provider_name, vault_token, vault_url, vault_mount_path, vault_ca_path) |
||||
SELECT pg_tde_add_key_provider_vault_v2( |
||||
'vault-provider', |
||||
json_object( 'type' VALUE 'remote', 'url' VALUE 'http://localhost:8888/token' ), |
||||
json_object( 'type' VALUE 'remote', 'url' VALUE 'http://localhost:8888/url' ), |
||||
to_json('secret'::text), NULL); |
||||
|
||||
-- For File key provider |
||||
-- pg_tde_add_key_provider_file(provider_name, file_path); |
||||
SELECT pg_tde_add_key_provider_file('file','/tmp/pgkeyring'); |
||||
``` |
||||
|
||||
**Note: The `File` provided is intended for development and stores the keys unencrypted in the specified data file.** |
||||
|
||||
5. Set the principal key for the database using the `pg_tde_set_principal_key` function. |
||||
|
||||
```sql |
||||
-- pg_tde_set_principal_key(principal_key_name, provider_name); |
||||
SELECT pg_tde_set_principal_key('my-principal-key','file'); |
||||
``` |
||||
|
||||
6. Specify `tde_heap_basic` access method during table creation |
||||
```sql |
||||
CREATE TABLE albums ( |
||||
album_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, |
||||
artist_id INTEGER, |
||||
title TEXT NOT NULL, |
||||
released DATE NOT NULL |
||||
) USING tde_heap_basic; |
||||
``` |
||||
7. You can encrypt existing table. It requires rewriting the table, so for large tables, it might take a considerable amount of time. |
||||
```sql |
||||
ALTER TABLE table_name SET access method tde_heap_basic; |
||||
``` |
||||
|
||||
|
||||
## Latest test release |
||||
|
||||
To download the latest build of the main branch, use the `HEAD` release from [releases](https://github.com/percona/pg_tde/releases). |
||||
|
||||
Builds are available in a tar.gz format, containing only the required files, and as a deb package. |
||||
The deb package is built against the pgdg16 release, but this dependency is not yet enforced in the package. |
||||
|
||||
|
||||
## Helper functions |
||||
|
||||
The extension provides the following helper functions: |
||||
|
||||
### pg_tde_is_encrypted(tablename) |
||||
|
||||
Returns `t` if the table is encrypted (uses the tde_heap_basic access method), or `f` otherwise. |
@ -0,0 +1,24 @@ |
||||
# Security Policy |
||||
|
||||
## Supported Versions |
||||
|
||||
pg_tde project follows rolling release strategy. So all security updates go to new versions. |
||||
|
||||
## Reporting a Vulnerability |
||||
|
||||
Please report any vulnerabilities to our project in [Jira](https://perconadev.atlassian.net/jira/software/c/projects/PG/issues). |
||||
|
||||
If the vulnerability is accepted and confirmed by our experts, you should normally expect us to deliver |
||||
a version with a fix according to the timelines provided below: |
||||
|
||||
For Percona created software (our engineers wrote the code): |
||||
|
||||
- Low/Medium: 120 days |
||||
- High: 90 days |
||||
- Critical: ASAP but should not exceed 30 days |
||||
|
||||
For Non-Percona created software (upstream provided/packaged) from the time the vendor releases a patch: |
||||
|
||||
- Low/Medium: 2nd release from current version |
||||
- High: Next release |
||||
- Critical: Hotfix or no later than next release (our regular release cadence is once every month) |
@ -0,0 +1,5 @@ |
||||
# Percona Code of Conduct |
||||
|
||||
All Percona Products follow the [Percona Community Code of Conduct](https://github.com/percona/community/blob/main/content/contribute/coc.md). |
||||
|
||||
If you notice any unacceptable behavior, let us know as soon as possible by writing to <community-team@percona.com>. We will respond within 48 hours. |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,29 @@ |
||||
FROM postgres:16 |
||||
|
||||
RUN apt-get update; \ |
||||
apt-get install -y --no-install-recommends \ |
||||
curl \ |
||||
libssl-dev \ |
||||
gcc \ |
||||
postgresql-server-dev-16 \ |
||||
make \ |
||||
libcurl4-openssl-dev |
||||
|
||||
WORKDIR /opt/pg_tde |
||||
|
||||
COPY . . |
||||
|
||||
RUN make USE_PGXS=1 MAJORVERSION=16 && \ |
||||
make USE_PGXS=1 install |
||||
RUN cp /usr/share/postgresql/postgresql.conf.sample /etc/postgresql/postgresql.conf; \ |
||||
echo "shared_preload_libraries = 'pg_tde'" >> /etc/postgresql/postgresql.conf; \ |
||||
# echo "log_min_messages = debug3" >> /etc/postgresql/postgresql.conf; \ |
||||
# echo "log_min_error_statement = debug3" >> /etc/postgresql/postgresql.conf; \ |
||||
chown postgres /etc/postgresql/tde_conf.json; \ |
||||
mkdir -p /docker-entrypoint-initdb.d |
||||
COPY ./docker/pg-tde-create-ext.sh /docker-entrypoint-initdb.d/pg-tde-create-ext.sh |
||||
COPY ./docker/pg-tde-streaming-repl.sh /docker-entrypoint-initdb.d/pg-tde-streaming-repl.sh |
||||
|
||||
VOLUME /etc/postgresql/ |
||||
|
||||
CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"] |
@ -0,0 +1,26 @@ |
||||
# TODO: needs improvements as currentlly ` docker-compose up -d --build` has to be run twice |
||||
# as replication init on secodary doen't work 100% properly |
||||
version: "3.4" |
||||
services: |
||||
pg-primary: |
||||
build: |
||||
dockerfile: ./docker/Dockerfile |
||||
context: .. |
||||
environment: |
||||
- "POSTGRES_PASSWORD=testpass" |
||||
- "PG_PRIMARY=true" |
||||
- "POSTGRES_HOST_AUTH_METHOD=trust" |
||||
- "PG_REPLICATION=true" |
||||
ports: |
||||
- "5433:5432" |
||||
pg-secondary: |
||||
build: |
||||
dockerfile: ./docker/Dockerfile |
||||
context: .. |
||||
depends_on: |
||||
- pg-primary |
||||
environment: |
||||
- "POSTGRES_PASSWORD=testpass" |
||||
- "PG_REPLICATION=true" |
||||
ports: |
||||
- "5434:5432" |
@ -0,0 +1,8 @@ |
||||
#!/bin/bash |
||||
|
||||
set -e |
||||
|
||||
PG_USER=${POSTGRES_USER:-"postgres"} |
||||
|
||||
psql -U ${PG_USER} -c 'CREATE EXTENSION pg_tde;' |
||||
psql -U ${PG_USER} -d template1 -c 'CREATE EXTENSION pg_tde;' |
@ -0,0 +1,20 @@ |
||||
#!/bin/bash |
||||
|
||||
set -e |
||||
|
||||
PG_PRIMARY=${PG_PRIMARY:-"false"} |
||||
PG_REPLICATION=${PG_REPLICATION:-"false"} |
||||
REPL_PASS=${REPL_PASS:-"replpass"} |
||||
PG_USER=${POSTGRES_USER:-"postgres"} |
||||
|
||||
|
||||
if [ "$PG_REPLICATION" == "true" ] ; then |
||||
if [ "$PG_PRIMARY" == "true" ] ; then |
||||
psql -U ${PG_USER} -c "CREATE ROLE repl WITH REPLICATION PASSWORD '${REPL_PASS}' LOGIN;" |
||||
echo "host replication repl 0.0.0.0/0 trust" >> ${PGDATA}/pg_hba.conf |
||||
else |
||||
rm -rf ${PGDATA}/* |
||||
pg_basebackup -h pg-primary -p 5432 -U repl -D ${PGDATA} -Fp -Xs -R |
||||
fi |
||||
fi |
||||
|
@ -0,0 +1 @@ |
||||
site/ |
@ -0,0 +1,114 @@ |
||||
## Contribute to documentation |
||||
|
||||
`pg_tde` documentation is written in Markdown language, so you can [edit it online via GitHub](#edit-documentation-online-vi-github). If you wish to have more control over the doc process, jump to how to [edit documentation locally](#edit-documentation-locally). |
||||
|
||||
Before you start, learn what [git], [MkDocs] and [Docker] are and what [Markdown] is and how to write it. For your convenience, there's also a [cheat sheet](https://www.markdownguide.org/cheat-sheet/) to help you with the syntax. |
||||
|
||||
The doc files are in the `documentation` directory. |
||||
|
||||
### Edit documentation online via GitHub |
||||
|
||||
1. Click the **Edit this page** icon next to the page title. The source `.md` file of the page opens in GitHub editor in your browser. If you haven’t worked with the repository before, GitHub creates a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of it for you. |
||||
2. Edit the page. You can check your changes on the **Preview** tab. |
||||
3. Commit your changes. |
||||
* In the _Commit changes_ section, describe your changes. |
||||
* Select the **Create a new branch for this commit** and start a pull request option |
||||
* Click **Propose changes**. |
||||
4. GitHub creates a branch and a commit for your changes. It loads a new page on which you can open a pull request to Percona. The page shows the base branch - the one you offer your changes for, your commit message and a diff - a visual representation of your changes against the original page. This allows you to make a last-minute review. When you are ready, click the Create pull request button. |
||||
5. Someone from our team reviews the pull request and if everything is correct, merges it into the documentation. Then it gets published on the site. |
||||
|
||||
### Edit documentation locally |
||||
|
||||
This option is for users who prefer to work from their computer and / or have the full control over the documentation process. |
||||
|
||||
The steps are the following: |
||||
|
||||
1. Fork this repository |
||||
2. Clone the repository on your machine: |
||||
|
||||
```sh |
||||
git clone git@github.com:<your_name>/pg_tde.git |
||||
``` |
||||
|
||||
3. Change the directory to ``pg_tde`` and add the remote upstream repository: |
||||
|
||||
```sh |
||||
git remote add upstream git@github.com:percona/pg_tde.git |
||||
``` |
||||
|
||||
4. Pull the latest changes from upstream |
||||
|
||||
```sh |
||||
git fetch upstream |
||||
git merge upstream/main |
||||
``` |
||||
|
||||
5. Create a separate branch for your changes |
||||
|
||||
```sh |
||||
git checkout -b <my_branch> |
||||
``` |
||||
|
||||
6. Make changes |
||||
7. Commit your changes. The [commit message guidelines](https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53) will help you with writing great commit messages |
||||
|
||||
8. Open a pull request to Percona |
||||
|
||||
#### Building the documentation |
||||
|
||||
To verify how your changes look, generate the static site with the documentation. This process is called *building*. You can do it in these ways: |
||||
- [Use Docker](#use-docker) |
||||
- [Install MkDocs and build locally](#install-sphinx-and-build-locally) |
||||
|
||||
##### Use Docker |
||||
|
||||
1. [Get Docker](https://docs.docker.com/get-docker/) |
||||
2. We use [our Docker image](https://hub.docker.com/repository/docker/perconalab/pmm-doc-md) to build documentation. Run the following command: |
||||
|
||||
```sh |
||||
docker run --rm -v $(pwd):/documentation perconalab/pmm-doc-md mkdocs build |
||||
``` |
||||
If Docker can't find the image locally, it first downloads the image, and then runs it to build the documentation. |
||||
|
||||
3. Go to the ``site`` directory and open the ``index.html`` file to see the documentation. |
||||
|
||||
If you want to see the changes as you edit the docs, use this command instead: |
||||
|
||||
```sh |
||||
docker run --rm -v $(pwd):/documentation -p 8000:8000 perconalab/pmm-doc-md mkdocs serve --dev-addr=0.0.0.0:8000 |
||||
``` |
||||
|
||||
Wait until you see `INFO - Start detecting changes`, then enter `0.0.0.0:8000` in the browser's address bar. The documentation automatically reloads after you save the changes in source files. |
||||
|
||||
##### Install MkDocs and build locally |
||||
|
||||
1. Install [Python]. |
||||
|
||||
2. Install MkDocs and required extensions: |
||||
|
||||
```sh |
||||
pip install -r requirements.txt |
||||
``` |
||||
|
||||
3. Build the site: |
||||
|
||||
```sh |
||||
mkdocs build |
||||
``` |
||||
|
||||
4. Open `site/index.html` |
||||
|
||||
Or, to run the built-in web server: |
||||
|
||||
```sh |
||||
mkdocs serve |
||||
``` |
||||
|
||||
|
||||
View the site at <http://0.0.0.0:8000> |
||||
|
||||
[MkDocs]: https://www.mkdocs.org/ |
||||
[Markdown]: https://daringfireball.net/projects/markdown/ |
||||
[Git]: https://git-scm.com |
||||
[Python]: https://www.python.org/downloads/ |
||||
[Docker]: https://docs.docker.com/get-docker/ |
After Width: | Height: | Size: 619 B |
@ -0,0 +1,37 @@ |
||||
{#- |
||||
This file was automatically generated - do not edit |
||||
-#} |
||||
{% extends "base.html" %} |
||||
|
||||
{% block announce %} |
||||
This is a Beta version of Percona Transparent Encryption extension and it is |
||||
<strong>not recommended for production environments</strong> yet. We encourage you to test it and <a href= "https://forums.percona.com/c/postgresql/pg-tde-transparent-data-encryption-tde/82">give your feedback</a>. |
||||
This will help us improve the product and make it production-ready faster. |
||||
{% endblock %} |
||||
|
||||
{% block scripts %} |
||||
<script src="https://cmp.osano.com/Azqe5vTyLOSbN3OuT/49ad85b5-0418-4794-ab81-7599dddd534c/osano.js"></script> |
||||
{{ super() }} |
||||
{% endblock %} |
||||
|
||||
{% block extrahead %} |
||||
{{ super() }} |
||||
{% set title = config.site_name %} |
||||
{% if page and page.meta and page.meta.title %} |
||||
{% set title = title ~ " - " ~ page.meta.title %} |
||||
{% elif page and page.title and not page.is_homepage %} |
||||
{% set title = title ~ " - " ~ page.title %} |
||||
{% endif %} |
||||
<meta property="og:type" content="website" /> |
||||
<meta property="og:title" content="{{ title }}" /> |
||||
<meta property="og:image" content="https://percona-lab.github.io/pg_tde/main/documentation/_images/pg_tde.png"> |
||||
<meta property="og:url" content="https://percona-lab.github.io/pg_tde/main/"> |
||||
<script> |
||||
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]); |
||||
posthog.init('phc_7unoI9J6Fm0SMrfDp35xNOpCRTkOAibbffQwdGWbHnL',{api_host:'https://eu.posthog.com'}) |
||||
</script> |
||||
{% endblock %} |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,14 @@ |
||||
{#- |
||||
This file was automatically generated - do not edit |
||||
-#} |
||||
<div class="md-copyright"> |
||||
<div class="md-copyright__highlight"> |
||||
<a href='https://percona.com' target='_blank'>Percona LLC and/or its affiliates, </a> © {{ build_date_utc.strftime('%Y') }} — <a href="#" onclick="Osano.cm.showDrawer('osano-cm-dom-info-dialog-open')">Cookie Preferences</a> |
||||
</div> |
||||
{% if not config.extra.generator == false %} |
||||
Made with |
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"> |
||||
Material for MkDocs |
||||
</a> |
||||
{% endif %} |
||||
</div> |
@ -0,0 +1,135 @@ |
||||
<!-- |
||||
Copyright (c) 2016-2024 Martin Donath <martin.donath@squidfunk.com> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to |
||||
deal in the Software without restriction, including without limitation the |
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
sell copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in |
||||
all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
IN THE SOFTWARE. |
||||
--> |
||||
|
||||
<!-- Determine classes --> |
||||
{% set class = "md-header" %} |
||||
{% if "navigation.tabs.sticky" in features %} |
||||
{% set class = class ~ " md-header--shadow md-header--lifted" %} |
||||
{% elif "navigation.tabs" not in features %} |
||||
{% set class = class ~ " md-header--shadow" %} |
||||
{% endif %} |
||||
|
||||
<!-- Header --> |
||||
<header class="{{ class }}" data-md-component="header"> |
||||
|
||||
<!-- Super Nav --> |
||||
<div class="superNav"> |
||||
<div class="md-header__inner md-grid"> |
||||
<a href="https://docs.percona.com/percona-for-postgresql/" title="Percona Documentation home page"> |
||||
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> |
||||
<mask id="a" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24"> |
||||
<path d="M0 0h24v24H0z"/> |
||||
</mask> |
||||
<g mask="url(#a)"> |
||||
<path d="m7.825 13 5.6 5.6L12 20l-8-8 8-8 1.425 1.4-5.6 5.6H20v2H7.825Z"/> |
||||
</g> |
||||
</svg> |
||||
<span>Percona Software for PostgreSQL Documentation</span> |
||||
</a> |
||||
</div> |
||||
</div> |
||||
|
||||
<nav |
||||
class="md-header__inner md-grid" |
||||
aria-label="{{ lang.t('header') }}" |
||||
> |
||||
|
||||
<!-- Link to home --> |
||||
<a |
||||
href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" |
||||
title="{{ config.site_name | e }}" |
||||
class="md-header__button md-logo" |
||||
aria-label="{{ config.site_name }}" |
||||
data-md-component="logo" |
||||
> |
||||
{% include "partials/logo.html" %} |
||||
</a> |
||||
|
||||
<!-- Button to open drawer --> |
||||
<label class="md-header__button md-icon" for="__drawer"> |
||||
{% set icon = config.theme.icon.menu or "material/menu" %} |
||||
{% include ".icons/" ~ icon ~ ".svg" %} |
||||
</label> |
||||
|
||||
<!-- Header title --> |
||||
<div class="md-header__title"> |
||||
<div class="md-header__ellipsis"> |
||||
<a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" class="md-header__topic"> |
||||
<span class="md-ellipsis"> |
||||
{{ config.site_name }} |
||||
</span> |
||||
</a> |
||||
<div class="md-header__topic" data-md-component="header-topic"> |
||||
<span class="md-ellipsis"> |
||||
{% if page.meta and page.meta.title %} |
||||
{{ page.meta.title }} |
||||
{% else %} |
||||
{{ page.title }} |
||||
{% endif %} |
||||
</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<!-- Color palette toggle --> |
||||
{% if config.theme.palette %} |
||||
{% if not config.theme.palette is mapping %} |
||||
{% include "partials/palette.html" %} |
||||
{% endif %} |
||||
{% endif %} |
||||
|
||||
<!-- User preference: color palette --> |
||||
{% if not config.theme.palette is mapping %} |
||||
{% include "partials/javascripts/palette.html" %} |
||||
{% endif %} |
||||
|
||||
<!-- Site language selector --> |
||||
{% if config.extra.alternate %} |
||||
{% include "partials/alternate.html" %} |
||||
{% endif %} |
||||
|
||||
<!-- Button to open search modal --> |
||||
{% if "material/search" in config.plugins %} |
||||
<label class="md-header__button md-icon" for="__search"> |
||||
{% set icon = config.theme.icon.search or "material/magnify" %} |
||||
{% include ".icons/" ~ icon ~ ".svg" %} |
||||
</label> |
||||
|
||||
<!-- Search interface --> |
||||
{% include "partials/search.html" %} |
||||
{% endif %} |
||||
|
||||
<!-- Repository information --> |
||||
{% if config.repo_url %} |
||||
<div class="md-header__source"> |
||||
{% include "partials/source.html" %} |
||||
</div> |
||||
{% endif %} |
||||
</nav> |
||||
|
||||
<!-- Navigation tabs (sticky) --> |
||||
{% if "navigation.tabs.sticky" in features %} |
||||
{% if "navigation.tabs" in features %} |
||||
{% include "partials/tabs.html" %} |
||||
{% endif %} |
||||
{% endif %} |
||||
</header> |
@ -0,0 +1,118 @@ |
||||
/* Style for PDF created by MkDocs with mkdocs-with-pdf plugin (https://pypi.org/project/mkdocs-with-pdf/) */ |
||||
@media print { |
||||
html { |
||||
font-size: 100%; |
||||
font-family: "Poppins", sans-serif; |
||||
} |
||||
|
||||
body { |
||||
font-family: "Poppins", sans-serif; |
||||
color: #00162b; |
||||
} |
||||
|
||||
article { |
||||
font-family: "Poppins", sans-serif; |
||||
text-align: justify; |
||||
} |
||||
|
||||
pre, |
||||
code, |
||||
var, |
||||
samp, |
||||
kbd, |
||||
tt { |
||||
font-family: monospace; |
||||
font-size: 110%; |
||||
} |
||||
|
||||
pre code, |
||||
pre var, |
||||
pre samp, |
||||
pre kbd, |
||||
pre tt { |
||||
font-size: 110%; |
||||
} |
||||
} |
||||
|
||||
@page { |
||||
size: a4 portrait; |
||||
margin: 25mm 20mm 25mm 20mm; |
||||
counter-increment: page; |
||||
white-space: pre; |
||||
color: #00162b; |
||||
|
||||
@top-right { |
||||
content: string(chapter); |
||||
} |
||||
|
||||
@bottom-left { |
||||
content: string(subtitle); |
||||
} |
||||
|
||||
@bottom-center { |
||||
content: counter(page)' of 'counter(pages); |
||||
} |
||||
|
||||
@bottom-right { |
||||
} |
||||
} |
||||
|
||||
@page :first { |
||||
@top-right { |
||||
content: ''; |
||||
} |
||||
|
||||
@bottom-right { |
||||
content: ''; |
||||
} |
||||
|
||||
@bottom-left { |
||||
content: ''; |
||||
} |
||||
} |
||||
|
||||
article { |
||||
page-break-before: always; |
||||
min-height: 100%; |
||||
} |
||||
|
||||
article { |
||||
|
||||
h1, |
||||
h2, |
||||
h3 { |
||||
border-bottom: 0px solid #fff; |
||||
} |
||||
|
||||
h1>.pdf-order, |
||||
h2>.pdf-order, |
||||
h3>.pdf-order { |
||||
padding-left: 6px; |
||||
padding-right: 0.8rem; |
||||
} |
||||
} |
||||
|
||||
article h1, |
||||
h2, |
||||
h3 { |
||||
border-bottom: 0px solid #fff; |
||||
color: #3e4875; |
||||
} |
||||
|
||||
.admonition { |
||||
font-size: 100%; |
||||
} |
||||
|
||||
article div.tabbed-content--wrap { |
||||
page-break-inside: auto !important; |
||||
} |
||||
article div.tabbed-content--wrap * { |
||||
page-break-before: auto !important; |
||||
page-break-inside: auto !important; |
||||
} |
||||
|
||||
.md-typeset .admonition.note, |
||||
.md-typeset details.note { |
||||
color: #00162b; |
||||
border-color: #fff; |
||||
} |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 299 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 30 KiB |
@ -0,0 +1,82 @@ |
||||
# Install `pg_tde` on Debian or Ubuntu |
||||
|
||||
The packages for the tech preview `pg_tde` are available in the experimental repository for Percona Distribution for PostgreSQL 17. |
||||
|
||||
Check the [list of supported platforms](install.md#__tabbed_1_2). |
||||
|
||||
This tutorial shows how to install `pg_tde` with [Percona Distribution for PostgreSQL](https://docs.percona.com/postgresql/latest/index.html). |
||||
|
||||
## Preconditions |
||||
|
||||
1. Debian and other systems that use the `apt` package manager include the upstream PostgreSQL server package (`postgresql-{{pgversion17}}`) by default. You need to uninstall this package before you install Percona Server for PostgreSQL and `pg_tde` to avoid conflicts. |
||||
2. You need the `percona-release` repository management tool that enables the desired Percona repository for you. |
||||
|
||||
|
||||
### Install `percona-release` |
||||
|
||||
1. You need the following dependencies to install `percona-release`: |
||||
|
||||
- `wget` |
||||
- `gnupg2` |
||||
- `curl` |
||||
- `lsb-release` |
||||
|
||||
Install them with the following command: |
||||
|
||||
```bash |
||||
sudo apt-get install -y wget gnupg2 curl lsb-release |
||||
``` |
||||
|
||||
2. Fetch the `percona-release` package |
||||
|
||||
```bash |
||||
sudo wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb |
||||
``` |
||||
|
||||
3. Install `percona-release` |
||||
|
||||
```bash |
||||
sudo dpkg -i percona-release_latest.generic_all.deb |
||||
``` |
||||
|
||||
4. Enable the Percona Distribution for PostgreSQL repository |
||||
|
||||
Percona provides [two repositories](repo-overview.md) for Percona Distribution for PostgreSQL. We recommend enabling the Major release repository to timely receive the latest updates. |
||||
|
||||
```{.bash data-prompt="$"} |
||||
$ sudo percona-release enable ppg-{{pgversion17}} |
||||
``` |
||||
|
||||
6. Update the local cache |
||||
|
||||
```bash |
||||
sudo apt-get update |
||||
``` |
||||
|
||||
## Install `pg_tde` |
||||
|
||||
!!! important |
||||
|
||||
The `pg_tde` {{release}} extension is a part of the `percona-postgresql-17` package. If you installed a previous version of `pg_tde` from the `percona-postgresql-17-pg-tde` package, do the following: |
||||
|
||||
* Drop the extension using the `DROP EXTENSION` with `CASCADE` command. |
||||
|
||||
<i warning>:material-alert: Warning:</i> The use of the `CASCADE` parameter deletes all tables that were created in the database with `pg_tde` enabled and also all dependencies upon the encrypted table (e.g. foreign keys in a non-encrypted table used in the encrypted one). |
||||
|
||||
```sql |
||||
DROP EXTENSION pg_tde CASCADE |
||||
``` |
||||
|
||||
* Uninstall the `percona-postgresql-17-pg-tde` package. |
||||
|
||||
After all [preconditions](#preconditions) are met, run the following command to install `pg_tde`: |
||||
|
||||
|
||||
```bash |
||||
sudo apt-get install -y percona-postgresql-17 |
||||
``` |
||||
|
||||
|
||||
## Next step |
||||
|
||||
[Setup](setup.md){.md-button} |
@ -0,0 +1,197 @@ |
||||
# Contributing guide |
||||
|
||||
Welcome to `pg_tde` - the Transparent Data Encryption extension for PostgreSQL! |
||||
|
||||
We're glad that you would like to become a community member and contribute to this project. |
||||
|
||||
You can contribute in one of the following ways: |
||||
|
||||
1. Reach us on our [Forums](https://forums.percona.com/c/postgresql/25). |
||||
2. Submit a bug report or a feature request |
||||
3. Submit a pull request (PR) with the code patch |
||||
4. Contribute to documentation |
||||
|
||||
## Prerequisites |
||||
|
||||
Before submitting code contributions, we ask you to complete the following prerequisites. |
||||
|
||||
### 1. Sign the CLA |
||||
|
||||
Before you can contribute, we kindly ask you to sign our [Contributor License Agreement](https://cla-assistant.percona.com/<linktoCLA>) (CLA). You can do this in on click using your GitHub account. |
||||
|
||||
**Note**: You can sign it later, when submitting your first pull request. The CLA assistant validates the PR and asks you to sign the CLA to proceed. |
||||
|
||||
### 2. Code of Conduct |
||||
|
||||
Please make sure to read and agree to our [Code of Conduct](https://github.com/percona/community/blob/main/content/contribute/coc.md). |
||||
|
||||
## Submitting a pull request |
||||
|
||||
All bug reports, enhancements and feature requests are tracked in [GitHub issues](https://github.com/percona/pg_tde/issues). Though not mandatory, we encourage you to first check for a bug report among the issues and in the PR list: perhaps the bug has already been addressed. |
||||
|
||||
For feature requests and enhancements, we do ask you to create a GitHub issue, describe your idea and discuss the design with us. This way we align your ideas with our vision for the product development. |
||||
|
||||
If the bug hasn’t been reported / addressed, or we’ve agreed on the enhancement implementation with you, do the following: |
||||
|
||||
1. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) this repository |
||||
2. Clone this repository on your machine. |
||||
3. Create a separate branch for your changes. If you work on a GitHub issue, please [create a branch from it](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#manually-linking-a-pull-request-or-branch-to-an-issue-using-the-issue-sidebar). This makes it easier to track your contribution. |
||||
4. Make your changes. Please follow the following guidelines to improve code readability: |
||||
|
||||
- [PostgreSQL coding conventions](https://www.postgresql.org/docs/current/source.html) |
||||
- [C style and Coding rules](https://github.com/MaJerle/c-code-style) |
||||
|
||||
5. [Build `pg_tde`](https://github.com/percona/pg_tde/wiki/Make-builds-for-developers) and [test your changes locally](#run-local-tests). |
||||
6. Commit the changes. The [commit message guidelines](https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53) will help you with writing great commit messages |
||||
7. Open a pull request to Percona. |
||||
8. Our team will review your code and if everything is correct, will merge it. |
||||
Otherwise, we will contact you for additional information or with the request to make changes. |
||||
|
||||
### Run local tests |
||||
|
||||
When you work, you should periodically run tests to check that your changes don’t break existing code. |
||||
|
||||
To run the tests, use the following command: |
||||
|
||||
``` |
||||
cd pg_tde |
||||
make USE_PGXS=1 installcheck |
||||
``` |
||||
|
||||
You can run tests on your local machine with whatever operating system you have. After you submit the pull request, we will check your patch on multiple operating systems. |
||||
|
||||
## Contribute to documentation |
||||
|
||||
`pg_tde` documentation is written in Markdown language, so you can |
||||
[edit it online via GitHub](#edit-documentation-online-vi-github). If you wish to have more control over the doc process, jump to how to [edit documentation locally](#edit-documentation-locally). |
||||
|
||||
Before you start, learn what [git], [MkDocs] and [Docker] are and what [Markdown] is and how to write it. For your convenience, there's also a cheat sheet to help you with the syntax. |
||||
|
||||
The doc files are in the `docs` directory. |
||||
|
||||
### Edit documentation online via GitHub |
||||
|
||||
1. Click the **Edit this page** icon next to the page title. The source `.md` file of the page opens in GitHub editor in your browser. If you haven’t worked with the repository before, GitHub creates a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of it for you. |
||||
2. Edit the page. You can check your changes on the **Preview** tab. |
||||
3. Commit your changes. |
||||
* In the _Commit changes_ section, describe your changes. |
||||
* Select the **Create a new branch for this commit** and start a pull request option |
||||
* Click **Propose changes**. |
||||
4. GitHub creates a branch and a commit for your changes. It loads a new page on which you can open a pull request to Percona. The page shows the base branch - the one you offer your changes for, your commit message and a diff - a visual representation of your changes against the original page. This allows you to make a last-minute review. When you are ready, click the Create pull request button. |
||||
5. Someone from our team reviews the pull request and if everything is correct, merges it into the documentation. Then it gets published on the site. |
||||
|
||||
### Edit documentation locally |
||||
|
||||
This option is for users who prefer to work from their computer and / or have the full control over the documentation process. |
||||
|
||||
The steps are the following: |
||||
|
||||
1. Fork this repository |
||||
2. Clone the repository on your machine: |
||||
|
||||
```sh |
||||
git clone git@github.com:<your-name>/pg_tde.git |
||||
|
||||
3. Change the directory to ``pg_tde`` and add the remote upstream repository: |
||||
|
||||
```sh |
||||
git remote add upstream git@github.com:percona/pg_tde.git |
||||
``` |
||||
|
||||
4. Pull the latest changes from upstream |
||||
|
||||
```sh |
||||
git fetch upstream |
||||
git merge upstream/main |
||||
``` |
||||
|
||||
5. Create a separate branch for your changes |
||||
|
||||
```sh |
||||
git checkout -b <my_branch> |
||||
``` |
||||
|
||||
6. Make changes |
||||
7. Commit your changes. The [commit message guidelines](https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53) will help you with writing great commit messages |
||||
|
||||
8. Open a pull request to Percona |
||||
|
||||
#### Building the documentation |
||||
|
||||
To verify how your changes look, generate the static site with the documentation. This process is called *building*. You can do it in these ways: |
||||
- [Use Docker](#use-docker) |
||||
- [Install MkDocs and build locally](#install-mkdocs-and-build-locally) |
||||
|
||||
##### Use Docker |
||||
|
||||
1. [Get Docker](https://docs.docker.com/get-docker/) |
||||
2. We use [our Docker image](https://hub.docker.com/repository/docker/perconalab/pmm-doc-md) to build documentation. Run the following command: |
||||
|
||||
```sh |
||||
cd documentation |
||||
docker run --rm -v $(pwd):/docs perconalab/pmm-doc-md mkdocs build |
||||
``` |
||||
If Docker can't find the image locally, it first downloads the image, and then runs it to build the documentation. |
||||
|
||||
3. Go to the ``site`` directory and open the ``index.html`` file to see the documentation. |
||||
|
||||
If you want to see the changes as you edit the docs, use this command instead: |
||||
|
||||
```sh |
||||
cd documentation |
||||
docker run --rm -v $(pwd):/docs -p 8000:8000 perconalab/pmm-doc-md mkdocs serve --dev-addr=0.0.0.0:8000 |
||||
``` |
||||
|
||||
Wait until you see `INFO - Start detecting changes`, then enter `0.0.0.0:8000` in the browser's address bar. The documentation automatically reloads after you save the changes in source files. |
||||
|
||||
##### Install MkDocs and build locally |
||||
|
||||
1. Install [Python]. |
||||
|
||||
2. Install MkDocs and required extensions: |
||||
|
||||
```sh |
||||
pip install -r requirements.txt |
||||
``` |
||||
|
||||
3. Build the site: |
||||
|
||||
```sh |
||||
cd documentation |
||||
mkdocs build |
||||
``` |
||||
|
||||
4. Open `site/index.html` |
||||
|
||||
Or, to run the built-in web server: |
||||
|
||||
```sh |
||||
cd documentation |
||||
mkdocs serve |
||||
``` |
||||
|
||||
View the site at <http://0.0.0.0:8000> |
||||
|
||||
#### Build PDF file |
||||
|
||||
To build a PDF version of the documentation, do the following: |
||||
|
||||
1. Disable displaying the last modification of the page: |
||||
|
||||
```sh |
||||
export ENABLED_GIT_REVISION_DATE=false |
||||
``` |
||||
|
||||
2. Build the PDF file: |
||||
|
||||
```sh |
||||
ENABLE_PDF_EXPORT=1 mkdocs build -f mkdocs-pdf.yml |
||||
``` |
||||
|
||||
The PDF document is in the ``site/pdf`` folder. |
||||
|
||||
[MkDocs]: https://www.mkdocs.org/ |
||||
[Markdown]: https://daringfireball.net/projects/markdown/ |
||||
[Git]: https://git-scm.com |
||||
[Python]: https://www.python.org/downloads/ |
||||
[Docker]: https://docs.docker.com/get-docker/ |
@ -0,0 +1,670 @@ |
||||
/* |
||||
* Prefixed by https://autoprefixer.github.io |
||||
* PostCSS: v8.4.14, |
||||
* Autoprefixer: v10.4.7 |
||||
* Browsers: last 4 version |
||||
*/ |
||||
|
||||
/* Custom fonts */ |
||||
|
||||
@font-face { |
||||
font-family: "Poppins"; |
||||
src: url("../fonts/Poppins-Regular.ttf"); |
||||
font-weight: normal; |
||||
font-style: normal; |
||||
} |
||||
@font-face { |
||||
font-family: "Poppins"; |
||||
src: url("../fonts/Poppins-Italic.ttf"); |
||||
font-weight: normal; |
||||
font-style: italic; |
||||
} |
||||
@font-face { |
||||
font-family: "Poppins"; |
||||
src: url("../fonts/Poppins-SemiBold.ttf"); |
||||
font-weight: bold; |
||||
font-style: normal; |
||||
} |
||||
@font-face { |
||||
font-family: "Poppins"; |
||||
src: url("../fonts/Poppins-SemiBoldItalic.ttf"); |
||||
font-weight: bold; |
||||
font-style: italic; |
||||
} |
||||
|
||||
/* Variables */ |
||||
|
||||
:root { |
||||
|
||||
/* Typography */ |
||||
--fHeading: "Poppins", "Roboto", Arial, Helvetica, sans-serif; |
||||
|
||||
/* Colors */ |
||||
--white: #fff; |
||||
|
||||
/* Percona Night */ |
||||
--night500: #0E1A53; |
||||
--night400: #3E4875; |
||||
--night300: #5E668C; |
||||
|
||||
/* Percona Aqua */ |
||||
--aqua900: #14584B; |
||||
--aqua800: #1A7362; |
||||
--aqua700: #22947E; |
||||
--aqua600: #2CBEA2; |
||||
|
||||
/* Percona Sky */ |
||||
--sky900: #08386B; |
||||
--sky800: #0B4A8C; |
||||
--sky700: #0E5FB5; |
||||
--sky600: #127AE8; |
||||
--sky500: #1486FF; |
||||
--sky400: #439EFF; |
||||
--sky300: #62AEFF; |
||||
--sky200: #93C7FF; |
||||
|
||||
/* Percona Stone */ |
||||
--stone900: #2C323E; |
||||
--stone800: #3A4151; |
||||
--stone700: #4B5468; |
||||
--stone100: #D1D5DE; |
||||
--stone50: #F0F1F4; |
||||
|
||||
/* mkdocs root override */ |
||||
--md-primary-fg-color--dark: var(--night400); |
||||
} |
||||
:root, |
||||
[data-md-color-scheme="percona-light"] { |
||||
|
||||
/* Primitives */ |
||||
--md-primary-fg-color: var(--sky700); |
||||
|
||||
/* Type */ |
||||
--md-typeset-color: var(--stone900); |
||||
--md-typeset-a-color: var(--sky700); |
||||
|
||||
/* Defaults */ |
||||
--md-default-bg-color: var(--white); |
||||
--md-default-fg-color--light: rgba(44,50,62,0.72); |
||||
--md-default-fg-color--lighter: rgba(44,50,62,0.40); |
||||
--md-default-fg-color--lightest: rgba(44,50,62,0.25); |
||||
|
||||
/* Accent */ |
||||
--md-accent-fg-color: var(--sky500); |
||||
|
||||
/* Footer */ |
||||
--md-footer-fg-color: var(--stone900); |
||||
--md-footer-fg-color--light: rgba(44,50,62,0.72); |
||||
--md-footer-fg-color--lighter: rgba(44,50,62,0.40); |
||||
--md-footer-bg-color: var(--stone50); |
||||
--md-footer-bg-color--dark: var(--stone50); |
||||
|
||||
/* Code */ |
||||
--md-code-bg-color: var(--stone800); |
||||
--md-code-bg-color: var(--stone50); |
||||
} |
||||
[data-md-color-scheme="percona-dark"] { |
||||
|
||||
/* Primitives */ |
||||
--md-hue: 230; |
||||
--md-primary-fg-color: var(--sky200); |
||||
|
||||
/* Type */ |
||||
--md-typeset-color: #FBFBFB; |
||||
--md-typeset-a-color: var(--sky200); |
||||
|
||||
/* Defaults */ |
||||
--md-default-bg-color: var(--stone900); |
||||
--md-default-fg-color--light: rgba(251,251,251,0.72); |
||||
--md-default-fg-color--lighter: rgba(251,251,251,0.4); |
||||
--md-default-fg-color--lightest: rgba(209,213,222,0.25); |
||||
|
||||
/* Accent */ |
||||
--md-accent-fg-color: var(--sky400); |
||||
--md-accent-bg-color: var(--stone900); |
||||
|
||||
/* Footer */ |
||||
--md-footer-fg-color: #FBFBFB; |
||||
--md-footer-fg-color--light: rgba(251,251,251,0.72); |
||||
--md-footer-fg-color--lighter: rgba(251,251,251,0.4); |
||||
--md-footer-bg-color: var(--stone800); |
||||
--md-footer-bg-color--dark: var(--stone800); |
||||
|
||||
/* Code */ |
||||
--md-code-bg-color: var(--stone50); |
||||
--md-code-bg-color: var(--stone800); |
||||
} |
||||
|
||||
/* Typography */ |
||||
|
||||
.md-typeset { |
||||
font-size: 0.75rem; |
||||
} |
||||
.md-typeset h1, |
||||
.md-typeset h2, |
||||
.md-typeset h3, |
||||
.md-typeset h4, |
||||
.md-typeset h5, |
||||
.md-typeset h6 { |
||||
font-family: var(--fHeading); |
||||
font-weight: bold; |
||||
} |
||||
.md-typeset h1 { |
||||
color: inherit; |
||||
} |
||||
.md-typeset h1 { |
||||
margin: 0 0 0.75em; |
||||
} |
||||
.md-header { |
||||
font-family: var(--fHeading); |
||||
font-weight: bold; |
||||
} |
||||
.md-header__button.md-logo { |
||||
margin: 0.2rem 0.1rem 0.2rem 0.4rem; |
||||
padding: 0.2rem; |
||||
} |
||||
.md-header__button.md-logo img, |
||||
.md-header__button.md-logo svg { |
||||
height: 1.6rem; |
||||
} |
||||
.md-nav__link--active { |
||||
font-weight: bold; |
||||
} |
||||
.md-typeset small { |
||||
opacity: 0.5; |
||||
} |
||||
.md-content a:not(.md-button) { |
||||
text-decoration: underline; |
||||
} |
||||
.md-content .tabbed-labels a { |
||||
text-decoration: none; |
||||
} |
||||
|
||||
/* Header nav */ |
||||
|
||||
.md-header, |
||||
.md-tabs { |
||||
background-color: var(--night400); |
||||
} |
||||
[dir=ltr] .md-header__title { |
||||
margin-left: 0; |
||||
} |
||||
[dir=rtl] .md-header__title { |
||||
margin-right: 0; |
||||
} |
||||
.md-tabs .md-tabs__link { |
||||
font-family: var(--fHeading); |
||||
font-weight: bold; |
||||
} |
||||
.md-nav__source { |
||||
margin-top: -0.25rem; |
||||
} |
||||
.md-header__inner > :last-child { |
||||
padding-right: 0.6rem; |
||||
} |
||||
.md-tabs__item { |
||||
height: 2rem; |
||||
} |
||||
.md-tabs__link { |
||||
margin-top: 0.55rem; |
||||
} |
||||
.md-header__topic { |
||||
transition: opacity .25s; |
||||
} |
||||
.md-header__topic:hover { |
||||
opacity: 0.7; |
||||
} |
||||
|
||||
/* Footer */ |
||||
|
||||
.md-footer a { |
||||
text-decoration: underline; |
||||
} |
||||
.md-copyright, |
||||
.md-copyright__highlight { |
||||
color: var(--md-footer-fg-color--light); |
||||
} |
||||
|
||||
/* Base components */ |
||||
|
||||
.md-typeset .md-button { |
||||
font-family: var(--fHeading); |
||||
font-size: 0.6818rem; |
||||
font-weight: bold; |
||||
padding: 0.4167em 1.6em; |
||||
border-radius: 10rem; |
||||
transition: all 0.2s ease-out; |
||||
} |
||||
.md-typeset .md-button--primary { |
||||
color: var(--md-accent-bg-color); |
||||
box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.12), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.20); |
||||
} |
||||
.md-typeset .md-button--primary:focus, |
||||
.md-typeset .md-button--primary:hover { |
||||
box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.12), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 2px 4px -1px rgba(0, 0, 0, 0.20); |
||||
} |
||||
.md-typeset .md-button:not(.md-button--primary):focus, |
||||
.md-typeset .md-button:not(.md-button--primary):hover { |
||||
background: none; |
||||
color: var(--md-accent-fg-color); |
||||
} |
||||
.md-typeset code { |
||||
font-size: 0.9091em; |
||||
color: var(--md-typeset-color); |
||||
vertical-align: baseline; |
||||
padding: 0 0.2em 0.1em; |
||||
border-radius: 0.15em; |
||||
} |
||||
.md-button code, |
||||
[data-md-color-scheme="percona-dark"] .md-button:not(.md-button--primary) code { |
||||
background-color: rgba(255, 255, 255, 0.1); |
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1) inset; |
||||
} |
||||
.md-button:not(.md-button--primary) code { |
||||
background-color: rgba(0, 0, 0, 0.05); |
||||
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.05) inset; |
||||
} |
||||
.md-content .md-button { |
||||
margin: 0 0.25em 0.5em 0; |
||||
} |
||||
.md-typeset .tabbed-labels--linked > label > a { |
||||
font-size: 0.75rem; |
||||
padding: 0.75em 1em; |
||||
} |
||||
.js .md-typeset .tabbed-labels:before { |
||||
height: 4px; |
||||
background-color: var(--md-typeset-a-color); |
||||
} |
||||
.md-typeset [class*="moji"] { |
||||
vertical-align: -0.25em; |
||||
} |
||||
.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child, .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10), .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11), .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12), .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13), .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14), .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15), .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16), .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17), .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18), .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19), .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2), .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20), .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3), .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4), .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5), .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6), .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7), .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8), .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9) { |
||||
color: var(--md-typeset-a-color); |
||||
} |
||||
.md-typeset .md-button [class*="moji"], |
||||
.md-typeset .tabbed-set [class*="moji"] { |
||||
height: 1.3333em; |
||||
vertical-align: -0.3333em; |
||||
} |
||||
.md-typeset .md-button [class*="moji"] svg, |
||||
.md-typeset .tabbed-set [class*="moji"] svg { |
||||
width: 1.3333em; |
||||
} |
||||
.md-typeset a [class*="moji"] { |
||||
vertical-align: -0.2222em; |
||||
} |
||||
.md-clipboard { |
||||
color: var(--md-default-fg-color--lighter); |
||||
} |
||||
.md-typeset hr { |
||||
margin: 2em 0; |
||||
border-color: var(--md-default-fg-color--lightest) |
||||
} |
||||
.md-typeset .tabbed-labels { |
||||
box-shadow: 0 -0.05rem var(--md-default-fg-color--lightest) inset; |
||||
} |
||||
.md-typeset .tabbed-labels > label:hover { |
||||
color: var(--md-accent-fg-color); |
||||
} |
||||
.md-typeset .tabbed-button { |
||||
width: 1.25rem; |
||||
height: 1.25rem; |
||||
margin-top: 0.0625rem; |
||||
} |
||||
.md-typeset .tabbed-control { |
||||
width: 2.25rem; |
||||
height: 2.25rem; |
||||
} |
||||
.tabbed-block > *:last-child { |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
/* Content re-styling */ |
||||
|
||||
.md-main__inner { |
||||
margin-top: 0.75rem; |
||||
margin-bottom: 0.75rem; |
||||
} |
||||
.md-typeset [type=checkbox]:checked + .task-list-indicator:before { |
||||
background-color: var(--aqua600); |
||||
} |
||||
.md-feedback { |
||||
margin: 2em 0 !important; |
||||
} |
||||
:not([data-banner]):not(.splash) + .md-feedback { |
||||
padding-top: 2em; |
||||
border-top: 0.05rem solid var(--md-default-fg-color--lightest); |
||||
} |
||||
.md-typeset .admonition, |
||||
.md-typeset details { |
||||
--md-admonition-bg-color: var(--md-default-bg-color); |
||||
--md-admonition-fg-color: var(--md-typeset-color); |
||||
border-width: 0.1125rem; |
||||
box-shadow: none; |
||||
} |
||||
.md-tabs__link { |
||||
font-size: 0.67rem; |
||||
} |
||||
.md-tabs__item--active .md-tabs__link, |
||||
.md-tabs__item--active .md-tabs__link a { |
||||
font-weight: bold; |
||||
border-bottom: 0.15em solid currentColor; |
||||
} |
||||
.md-sidebar__scrollwrap { |
||||
scrollbar-gutter: unset; |
||||
} |
||||
|
||||
/* Custom Banner */ |
||||
|
||||
[data-banner] { |
||||
padding: 1.5em; |
||||
margin: 1.5em 0; |
||||
border: 0.05rem solid var(--md-default-fg-color--lightest); |
||||
border-radius: 0.2rem; |
||||
/* box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.12), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.20); */ |
||||
transition: all 0.2s ease-out; |
||||
} |
||||
[data-banner]:hover { |
||||
box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.12), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 2px 4px -1px rgba(0, 0, 0, 0.20); |
||||
} |
||||
[data-banner] .title { |
||||
font-weight: bold; |
||||
margin: 0; |
||||
} |
||||
[data-banner] .title + * { |
||||
margin-top: 0.25em; |
||||
} |
||||
[data-banner] > :last-child { |
||||
margin-bottom: 0; |
||||
} |
||||
[data-banner] a:link { |
||||
font-family: var(--fHeading); |
||||
font-size: 0.6818rem; |
||||
font-weight: bold; |
||||
text-decoration: none; |
||||
} |
||||
[data-banner] .actions > p { |
||||
margin: 0; |
||||
} |
||||
[data-banner] .actions a { |
||||
display: inline-block; |
||||
margin: 0 1em 0 0; |
||||
} |
||||
[data-banner] > :only-child, |
||||
[data-banner] .actions a:first-of-type { |
||||
margin-top: 0; |
||||
} |
||||
[data-banner] a [class*="moji"] { |
||||
height: 1.3333em; |
||||
vertical-align: -0.3333em; |
||||
} |
||||
[data-banner] a [class*="moji"] svg { |
||||
width: 1.3333em; |
||||
} |
||||
[data-banner="logo"] > p:first-child { |
||||
margin-top: 0; |
||||
} |
||||
[data-banner="logo"] > p:first-child [class*="moji"] { |
||||
font-size: 4em; |
||||
} |
||||
[data-grid] { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
margin-right: -1rem; |
||||
} |
||||
[data-grid] [data-banner] { |
||||
flex: 1 1 320px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
margin: 0 1rem 1rem 0; |
||||
} |
||||
[data-grid] .title { |
||||
font-size: 0.8rem; |
||||
font-weight: bold; |
||||
} |
||||
[data-grid] [data-banner] > p:last-child { |
||||
margin-top: 0; |
||||
} |
||||
[data-grid] [data-banner] > p:nth-last-child(2) { |
||||
flex-grow: 2; |
||||
} |
||||
[data-grid] + [data-banner] { |
||||
margin-top: 0; |
||||
} |
||||
[data-grid] .md-button { |
||||
margin: 0.5em 0.25em 0 0; |
||||
} |
||||
|
||||
/* Custom lists */ |
||||
|
||||
[dir] .power-bullet + ul, |
||||
[dir] .power-bullet + ul ul, |
||||
[dir] .power-bullet + ul ol, |
||||
[dir] .power-number + ol, |
||||
[dir] .power-number + ol ol, |
||||
[dir] .power-number + ol ul { |
||||
list-style: none; |
||||
--power-list-indent: 2em; |
||||
--power-list-gap: 0.5em; |
||||
--power-list-counter-size: calc(var(--power-list-indent) - var(--power-list-gap)); |
||||
margin: 1.25em 0 2em; |
||||
} |
||||
[dir] .power-bullet + ul ul:last-child, |
||||
[dir] .power-bullet + ul ol:last-child, |
||||
[dir] .power-number + ol ol:last-child, |
||||
[dir] .power-number + ol ul:last-child { |
||||
margin-bottom: 0; |
||||
} |
||||
.power-bullet + ul > li:not(:last-child), |
||||
.power-bullet + ul ul > li:not(:last-child), |
||||
.power-bullet + ul ol > li:not(:last-child), |
||||
.power-number + ol > li:not(:last-child), |
||||
.power-number + ol ol > li:not(:last-child), |
||||
.power-number + ol ul > li:not(:last-child) { |
||||
margin-bottom: 1.25em; |
||||
} |
||||
[dir=ltr] .power-bullet + ul > li, |
||||
[dir=ltr] .power-bullet + ul ul > li, |
||||
[dir=ltr] .power-bullet + ul ol > li, |
||||
[dir=ltr] .power-number + ol > li, |
||||
[dir=ltr] .power-number + ol ol > li, |
||||
[dir=ltr] .power-number + ol ul > li { |
||||
margin-left: var(--power-list-indent); |
||||
} |
||||
[dir=rtl] .power-bullet + ul > li, |
||||
[dir=rtl] .power-bullet + ul ul > li, |
||||
[dir=rtl] .power-bullet + ul ol > li, |
||||
[dir=rtl] .power-number + ol > li, |
||||
[dir=rtl] .power-number + ol ol > li, |
||||
[dir=rtl] .power-number + ol ul > li { |
||||
margin-right: var(--power-list-indent); |
||||
} |
||||
.power-bullet + ul > li::before, |
||||
.power-bullet + ul ul > li::before, |
||||
.power-number + ol ul > li::before { |
||||
content: "→"; |
||||
} |
||||
.power-number + ol, |
||||
.power-number + ol ol, |
||||
.power-bullet + ul ol { |
||||
counter-reset: power-list; |
||||
} |
||||
.power-number + ol > li, |
||||
.power-number + ol ol > li, |
||||
.power-bullet + ul ol > li { |
||||
counter-increment: power-list; |
||||
position: relative; |
||||
} |
||||
.power-number + ol > li::before, |
||||
.power-number + ol ol > li::before, |
||||
.power-bullet + ul ol > li::before { |
||||
content: counter(power-list); |
||||
font-family: var(--fHeading); |
||||
} |
||||
.power-bullet + ul > li::before, |
||||
.power-bullet + ul ul > li::before, |
||||
.power-bullet + ul ol > li::before, |
||||
.power-number + ol > li::before, |
||||
.power-number + ol ol > li::before, |
||||
.power-number + ol ul > li::before { |
||||
display: inline-block; |
||||
position: absolute; |
||||
font-weight: bold; |
||||
text-align: center; |
||||
line-height: var(--power-list-counter-size); |
||||
width: var(--power-list-counter-size); |
||||
height: var(--power-list-counter-size); |
||||
margin-right: var(--power-list-gap); |
||||
border-radius: 50%; |
||||
color: var(--md-default-bg-color); |
||||
background-color: var(--md-typeset-color); |
||||
} |
||||
[dir=ltr] .power-bullet + ul > li::before, |
||||
[dir=ltr] .power-bullet + ul ul > li::before, |
||||
[dir=ltr] .power-bullet + ul ol > li::before, |
||||
[dir=ltr] .power-number + ol > li::before, |
||||
[dir=ltr] .power-number + ol ol > li::before, |
||||
[dir=ltr] .power-number + ol ul > li::before { |
||||
margin-left: calc(var(--power-list-indent) - (var(--power-list-indent) * 2)); |
||||
} |
||||
[dir=rtl] .power-bullet + ul > li::before, |
||||
[dir=rtl] .power-bullet + ul ul > li::before, |
||||
[dir=rtl] .power-bullet + ul ol > li::before, |
||||
[dir=rtl] .power-number + ol > li::before, |
||||
[dir=rtl] .power-number + ol ol > li::before, |
||||
[dir=rtl] .power-number + ol ul > li::before { |
||||
margin-right: calc(var(--power-list-indent) - (var(--power-list-indent) * 2)); |
||||
} |
||||
.power-bullet + ul ul > li::before, |
||||
.power-bullet + ul ol > li::before, |
||||
.power-number + ol ul > li::before, |
||||
.power-number + ol ol > li::before { |
||||
opacity: 0.3; |
||||
} |
||||
|
||||
/* Custom highlights */ |
||||
|
||||
i[info], |
||||
i[warning] { |
||||
font-style: normal; |
||||
font-weight: bold; |
||||
display: inline-block; |
||||
padding: 0 0.25em; |
||||
border-radius: 0.2em; |
||||
} |
||||
i[info] { |
||||
background-color: #00b8d41a; |
||||
border-width: 0.05rem; |
||||
border-style: solid; |
||||
border-color: #00b8d41a; |
||||
} |
||||
i[info] [class*="moji"] { |
||||
color: #00b8d4; |
||||
} |
||||
i[warning] { |
||||
background-color: #ff91001a; |
||||
border-width: 0.05rem; |
||||
border-style: solid; |
||||
border-color: #ff91001a; |
||||
} |
||||
i[warning] [class*="moji"] { |
||||
color: #ff9100; |
||||
} |
||||
|
||||
/* Modals */ |
||||
|
||||
.md-consent__overlay { |
||||
-webkit-backdrop-filter: blur(.2rem); |
||||
backdrop-filter: blur(.2rem); |
||||
background-color: rgba(44,50,62,0.72); |
||||
} |
||||
.md-consent__inner { |
||||
background-color: var(--md-footer-bg-color--dark); |
||||
} |
||||
|
||||
/* Code injections */ |
||||
|
||||
.injections { |
||||
position: absolute; |
||||
width: 0; |
||||
height: 0; |
||||
padding: 0; |
||||
margin: 0; |
||||
visibility: hidden; |
||||
pointer-events: none; |
||||
} |
||||
|
||||
/* Super Nav */ |
||||
|
||||
.superNav { |
||||
font-family: var(--fHeading); |
||||
font-size: 0.5625rem; |
||||
line-height: 1; |
||||
font-weight: bold; |
||||
text-transform: uppercase; |
||||
letter-spacing: 0.0625em; |
||||
color: var(--white); |
||||
background-color: var(--stone800); |
||||
} |
||||
.superNav a { |
||||
display: inline-block; |
||||
padding: 0.25rem 0.625rem !important; |
||||
transition: all 0.2s ease-out; |
||||
} |
||||
.superNav a:hover { |
||||
opacity: 0.7; |
||||
} |
||||
.superNav svg { |
||||
width: 1.375em; |
||||
height: 1.375em; |
||||
margin-right: 0.125em; |
||||
fill: currentColor; |
||||
vertical-align: -0.3125em; |
||||
} |
||||
|
||||
/* Version Select */ |
||||
|
||||
.version-select::after { |
||||
content: "\25BE"; |
||||
display: inline-block; |
||||
margin-left: -1em; |
||||
transform: translate(-0.625em, -0.0625em); |
||||
pointer-events: none; |
||||
} |
||||
#versionSelect { |
||||
-webkit-appearance: none; |
||||
-moz-appearance: none; |
||||
appearance: none; |
||||
align-self: center; |
||||
font-size: 0.9rem; |
||||
line-height: 1; |
||||
font-weight: 700; |
||||
padding: 0.5em 1.375em 0.5em 0.5em; |
||||
margin: 0 0.25em; |
||||
background-color: rgba(0,0,0,0.2); |
||||
color: inherit; |
||||
border: none; |
||||
border-radius: 0.1rem; |
||||
} |
||||
#versionSelect::-ms-expand { |
||||
display: none; |
||||
} |
||||
|
||||
/* Media queries */ |
||||
|
||||
@media screen and (max-width: 76.1875em) { |
||||
.md-nav--primary .md-nav__title[for=__drawer], |
||||
.md-nav--primary .md-nav__title { |
||||
line-height: 1.5; |
||||
height: unset; |
||||
padding: 3.5rem .8rem 0.5rem; |
||||
color: var(--md-primary-bg-color); |
||||
background-color: var(--md-primary-fg-color--dark); |
||||
} |
||||
} |
||||
@media screen and (max-width: 60em) { |
||||
[data-banner] { |
||||
padding: 1em; |
||||
} |
||||
} |
||||
/**/ |
@ -0,0 +1,7 @@ |
||||
@media print { |
||||
/* Adjusts positioning of admonition icon */ |
||||
.md-typeset :is(.admonition-title,summary):before { |
||||
top: 0.6rem; |
||||
left: 0.6rem; |
||||
} |
||||
} |
@ -0,0 +1,301 @@ |
||||
|
||||
/* Type */ |
||||
|
||||
.landing h1, |
||||
.landing h2 { |
||||
font-size: calc(1.5em + 1vw); |
||||
line-height: 1.125; |
||||
text-transform: uppercase; |
||||
letter-spacing: 0; |
||||
margin: 0.5em 0; |
||||
} |
||||
|
||||
/* Layout adjustments */ |
||||
|
||||
.md-header, .md-tabs { |
||||
background-color: var(--stone800); |
||||
} |
||||
.landing > :not(:last-child) { |
||||
margin-bottom: 2em; |
||||
} |
||||
/* .md-content__inner { |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
.md-content__inner > :not(.landing) { |
||||
width: 100%; |
||||
max-width: calc(34.3rem); |
||||
max-width: calc(34.3rem + 1.2rem + 12.1rem); |
||||
align-self: center; |
||||
} */ |
||||
[data-grid] [data-banner] { |
||||
flex: 0 1 calc(50% - 1rem); |
||||
} |
||||
|
||||
/* Splash Box */ |
||||
|
||||
.splash { |
||||
display: flex; |
||||
position: relative; |
||||
justify-content: space-between; |
||||
line-height: 1.25; |
||||
padding: calc(0.5em + 3%); |
||||
border: 1px solid var(--md-default-fg-color--lightest); |
||||
border-radius: calc(0.5rem + 0.75vw); |
||||
background: linear-gradient(110deg, var(--md-default-bg-color) 33%, var(--md-footer-bg-color--dark) 95%); |
||||
overflow: hidden; |
||||
background-repeat: no-repeat; |
||||
} |
||||
.splash.dark { |
||||
color: var(--white); |
||||
--md-primary-fg-color: var(--stone50); |
||||
--md-accent-fg-color: var(--white); |
||||
} |
||||
.splash.highlight { |
||||
background: |
||||
linear-gradient( |
||||
110deg, |
||||
rgba(44,50,62,0.9) 10%, |
||||
rgba(44,50,62,0.1) 90% |
||||
), |
||||
url(../assets/highlight.jpg) center / cover var(--stone800); |
||||
border: none; |
||||
background-repeat: no-repeat; |
||||
} |
||||
.splash.mysql { |
||||
background: |
||||
linear-gradient( |
||||
110deg, |
||||
rgba(0,0,0,0.2) 33%, |
||||
rgba(0,0,0,0.1) 95% |
||||
), |
||||
linear-gradient( |
||||
110deg, |
||||
rgb(14,95,181) 33%, |
||||
rgb(48,209,178) 95% |
||||
); |
||||
} |
||||
.splash.postgresql { |
||||
background: |
||||
linear-gradient( |
||||
110deg, |
||||
rgba(0,0,0,0.4) 33%, |
||||
rgba(0,0,0,0.1) 95% |
||||
), |
||||
linear-gradient( |
||||
110deg, |
||||
rgb(78,91,150) 33%, |
||||
rgb(67,158,255) 95% |
||||
); |
||||
} |
||||
.splash.mongodb { |
||||
background: |
||||
linear-gradient( |
||||
110deg, |
||||
rgba(0,0,0,0.4) 33%, |
||||
rgba(0,0,0,0.1) 95% |
||||
), |
||||
linear-gradient( |
||||
110deg, |
||||
rgb(24,109,73) 33%, |
||||
rgb(48,209,190) 95% |
||||
); |
||||
} |
||||
.splash.operators { |
||||
background: |
||||
linear-gradient( |
||||
110deg, |
||||
transparent 33%, |
||||
rgba(0,0,0,0.1) 95% |
||||
), |
||||
linear-gradient( |
||||
110deg, |
||||
rgb(11,39,140) 33%, |
||||
rgb(20,142,255) 95% |
||||
); |
||||
} |
||||
.splash.header { |
||||
flex-direction: column; |
||||
align-items: flex-start; |
||||
border: none; |
||||
background-repeat: no-repeat; |
||||
} |
||||
|
||||
/* Splash Contents */ |
||||
|
||||
.splash > * { |
||||
flex: 0 1 45%; |
||||
} |
||||
.splash h1, |
||||
.splash h2 { |
||||
margin-top: 0; |
||||
margin-bottom: -0.125em; |
||||
} |
||||
.splash > :last-child { |
||||
margin-bottom: 0; |
||||
} |
||||
.splash-intro { |
||||
margin: 0.5rem 0.75rem; |
||||
} |
||||
.splash-links > :not(:last-child) { |
||||
margin-bottom: 1em; |
||||
} |
||||
.splash.dark .md-button { |
||||
border-color: rgba(255, 255, 255, 0.4) |
||||
} |
||||
.splash.dark .md-button:hover { |
||||
border-color: var(--white) |
||||
} |
||||
.splash.dark .md-button--primary, |
||||
.splash.dark .md-button--primary:hover { |
||||
color: var(--stone700); |
||||
} |
||||
.splash.dark .md-button--primary:hover { |
||||
color: var(--stone900); |
||||
} |
||||
.splash.header > * { |
||||
max-width: 30rem; |
||||
z-index: 1; |
||||
} |
||||
.splash.header > :first-child { |
||||
margin: 0; |
||||
} |
||||
.splash.header img { |
||||
display: block; |
||||
position: absolute; |
||||
top: 50%; |
||||
right: 1rem; |
||||
width: 12rem; |
||||
height: 12rem; |
||||
margin: 0; |
||||
transform: translateY(-50%); |
||||
z-index: 0; |
||||
} |
||||
|
||||
/* Splash Card */ |
||||
|
||||
a.splash-card { |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
min-height: 6.75em; |
||||
padding: 0.75rem 0.375rem 0.5rem 4.75rem; |
||||
border: 1px solid var(--md-default-fg-color--lightest); |
||||
border-radius: calc(0.25rem + 0.375vw); |
||||
cursor: pointer; |
||||
text-decoration: none !important; |
||||
color: var(--md-typeset-color); |
||||
position: relative; |
||||
background-color: var(--md-default-bg-color); |
||||
transition: all 0.2s ease-out; |
||||
} |
||||
.splash.highlight a.splash-card { |
||||
color: var(--white); |
||||
background-color: rgba(255, 255, 255, 0.2); |
||||
backdrop-filter: blur(0.75rem); |
||||
border-color: rgba(255,255,255,0.1); |
||||
} |
||||
a.splash-card:hover { |
||||
box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.12), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 2px 4px -1px rgba(0, 0, 0, 0.20); |
||||
color: var(--md-typeset-color); |
||||
} |
||||
.splash.highlight a.splash-card:hover { |
||||
background-color: rgba(255, 255, 255, 0.4); |
||||
border-color: rgba(255,255,255,0.2); |
||||
backdrop-filter: blur(1.5rem); |
||||
} |
||||
a.splash-card img { |
||||
display: block; |
||||
position: absolute; |
||||
top: 0.75rem; |
||||
left: 0.75rem; |
||||
width: 3.5rem; |
||||
height: 3.5rem; |
||||
border-radius: 0.25rem; |
||||
float: left; |
||||
} |
||||
.splash-card > * { |
||||
margin: 0 0.25rem 0.25rem 0 !important; |
||||
} |
||||
.splash-card > h3 { |
||||
font-size: 0.875rem; |
||||
margin-bottom: 0.0625rem !important; |
||||
} |
||||
|
||||
/* News elements */ |
||||
|
||||
[data-news] { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
margin-right: -1rem; |
||||
} |
||||
[data-news] [data-article] { |
||||
flex: 0 1 calc(50% - 1rem); |
||||
display: flex; |
||||
flex-direction: column; |
||||
margin: 0 1rem 1rem 0; |
||||
padding: 0 1rem 1rem 0; |
||||
border-bottom: 1px solid var(--md-default-fg-color--lightest); |
||||
} |
||||
[data-article] > * { |
||||
margin: 0.25rem 0; |
||||
} |
||||
[data-article] > :first-child { |
||||
font-family: var(--fHeading); |
||||
font-size: 0.8rem; |
||||
/* flex-grow: 1; */ |
||||
} |
||||
[data-article] > :nth-child(2):not(:last-child) { |
||||
font-size: 0.875em; |
||||
line-height: 1.4; |
||||
display: -webkit-box; |
||||
-webkit-line-clamp: 3; |
||||
-webkit-box-orient: vertical; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
max-height: 2.8em; |
||||
position: relative; |
||||
} |
||||
[data-article] > :nth-child(2):not(:last-child)::after { |
||||
content: ""; |
||||
position: absolute; |
||||
display: block; |
||||
right: 0; |
||||
bottom: 0; |
||||
width: 4rem; |
||||
height: 1.4em; |
||||
background: linear-gradient(to right, transparent 0%, var(--md-default-bg-color) 50%); |
||||
} |
||||
[data-article] > :last-child > * { |
||||
margin-right: 1em; |
||||
} |
||||
[data-article] a:link { |
||||
font-family: var(--fHeading); |
||||
font-size: 0.6818rem; |
||||
font-weight: bold; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
/* Conditionals */ |
||||
|
||||
@media screen and (max-width: 76.1875em) { |
||||
.md-nav--primary .md-nav__title[for=__drawer], |
||||
.md-nav--primary .md-nav__title { |
||||
background-color: var(--stone800); |
||||
} |
||||
} |
||||
@media screen and (max-width: 55em) { |
||||
.splash.header img { |
||||
right: -2rem; |
||||
opacity: 0.2; |
||||
} |
||||
} |
||||
@media screen and (max-width: 45em) { |
||||
.splash { |
||||
flex-direction: column; |
||||
} |
||||
[data-grid] [data-banner], |
||||
[data-news] [data-article] { |
||||
flex: 1 1 100%; |
||||
} |
||||
} |
@ -0,0 +1,206 @@ |
||||
/* General styling */ |
||||
|
||||
.osano-cm-window { |
||||
font-family: "Roboto", Arial, Helvetica, sans-serif; |
||||
font-size: 20px; |
||||
} |
||||
.osano-cm-dialog--type_bar { |
||||
justify-content: center; |
||||
color: #000; |
||||
background: #fff; |
||||
box-shadow: 0 0 0 100vmax rgba(0,0,0,0.66) |
||||
} |
||||
|
||||
.osano-cm-dialog { |
||||
font-size: 0.75em; |
||||
padding: 2em 1em; |
||||
color: var(--md-typeset-color); |
||||
background: var(--md-footer-bg-color--dark); |
||||
} |
||||
.osano-cm-header, |
||||
.osano-cm-info-dialog-header { |
||||
background: var(--md-default-bg-color); |
||||
} |
||||
.osano-cm-link, |
||||
.osano-cm-disclosure__toggle, |
||||
.osano-cm-expansion-panel__toggle { |
||||
color: var(--md-typeset-a-color); |
||||
} |
||||
.osano-cm-link:hover, |
||||
.osano-cm-link:active, |
||||
.osano-cm-disclosure__toggle:hover, |
||||
.osano-cm-disclosure__toggle:active, |
||||
.osano-cm-disclosure__toggle:focus, |
||||
.osano-cm-expansion-panel__toggle:hover, |
||||
.osano-cm-expansion-panel__toggle:active, |
||||
.osano-cm-expansion-panel__toggle:focus { |
||||
color: var(--md-accent-fg-color); |
||||
} |
||||
.osano-cm-drawer-links { |
||||
display: inline-block; |
||||
} |
||||
.osano-cm-link.osano-cm-storage-policy { |
||||
margin-right: 0.5em; |
||||
} |
||||
.osano-cm-description { |
||||
font-weight: 400; |
||||
} |
||||
.osano-cm-info { |
||||
color: var(--md-typeset-color); |
||||
background: var(--md-default-bg-color); |
||||
box-shadow: unset; |
||||
} |
||||
.osano-cm-dialog--hidden, |
||||
.osano-cm-info-dialog--hidden { |
||||
transition-delay: 0ms, 0ms; |
||||
} |
||||
.osano-cm-disclosure { |
||||
padding-top: 0; |
||||
} |
||||
.osano-cm-disclosure--collapse { |
||||
border-color: var(--md-default-fg-color--lightest); |
||||
} |
||||
|
||||
/* Closing button */ |
||||
|
||||
.osano-cm-dialog__close, |
||||
.osano-cm-dialog__close:hover, |
||||
.osano-cm-dialog__close:focus, |
||||
.osano-cm-dialog__close:focus:hover { |
||||
color: var(--md-typeset-color); |
||||
stroke: var(--md-typeset-color); |
||||
border-color: transparent; |
||||
outline: initial; |
||||
} |
||||
.osano-cm-dialog__close:focus { |
||||
background-color: var(--md-default-fg-color--lightest); |
||||
} |
||||
.osano-cm-close { |
||||
padding: 0.25em; |
||||
margin: 0.5em; |
||||
stroke-width: 2px; |
||||
border-width: 2px; |
||||
opacity: 0.4; |
||||
} |
||||
.osano-cm-close:focus, |
||||
.osano-cm-close:hover { |
||||
stroke-width: 2px; |
||||
opacity: 1; |
||||
} |
||||
.osano-cm-info-dialog-header__close:focus { |
||||
background-color: var(--md-typeset-color); |
||||
} |
||||
|
||||
/* Switch buttons */ |
||||
|
||||
.osano-cm-toggle__switch { |
||||
background-color: var(--md-default-fg-color--lightest); |
||||
transition: all 0.1s ease-out; |
||||
} |
||||
.osano-cm-toggle__input:hover + .osano-cm-toggle__switch { |
||||
background-color: var(--md-default-fg-color--light); |
||||
border-color: transparent; |
||||
} |
||||
.osano-cm-toggle__input:focus + .osano-cm-toggle__switch { |
||||
background-color: var(--md-default-fg-color--lightest); |
||||
border-color: transparent; |
||||
} |
||||
.osano-cm-toggle__input:focus + .osano-cm-toggle__switch::before { |
||||
border-color: var(--md-accent-fg-color); |
||||
} |
||||
.osano-cm-toggle__input:focus:hover + .osano-cm-toggle__switch { |
||||
background-color: var(--md-default-fg-color--light); |
||||
border-color: transparent; |
||||
} |
||||
.osano-cm-toggle__input:checked + .osano-cm-toggle__switch, |
||||
.osano-cm-toggle__input:disabled:checked + .osano-cm-toggle__switch { |
||||
background-color: var(--md-primary-fg-color); |
||||
border-color: var(--md-primary-fg-color); |
||||
} |
||||
.osano-cm-toggle__input:checked:hover + .osano-cm-toggle__switch, |
||||
.osano-cm-toggle__input:disabled:checked:hover + .osano-cm-toggle__switch { |
||||
background-color: var(--md-accent-fg-color); |
||||
border-color: var(--md-accent-fg-color); |
||||
} |
||||
.osano-cm-toggle__input:checked:focus + .osano-cm-toggle__switch, |
||||
.osano-cm-toggle__input:disabled:checked:focus + .osano-cm-toggle__switch { |
||||
background-color: var(--md-primary-fg-color); |
||||
border-color: var(--md-primary-fg-color); |
||||
} |
||||
.osano-cm-toggle__input:checked:focus + .osano-cm-toggle__switch::before { |
||||
border-color: var(--md-accent-fg-color); |
||||
} |
||||
.osano-cm-toggle__input:checked:focus:hover + .osano-cm-toggle__switch { |
||||
background-color: var(--md-accent-fg-color); |
||||
border-color: var(--md-accent-fg-color); |
||||
} |
||||
.osano-cm-toggle__input:disabled:checked + .osano-cm-toggle__switch, |
||||
.osano-cm-toggle__input:disabled:checked:focus + .osano-cm-toggle__switch, |
||||
.osano-cm-toggle__input:disabled:checked:hover + .osano-cm-toggle__switch { |
||||
opacity: 0.3; |
||||
cursor: not-allowed; |
||||
} |
||||
.osano-cm-toggle__input + .osano-cm-toggle__switch::after { |
||||
background-color: var(--md-default-bg-color) !important; |
||||
} |
||||
.osano-cm-toggle__input:checked + .osano-cm-toggle__switch::before { |
||||
border-color: transparent; |
||||
} |
||||
.osano-cm-list { |
||||
gap: 0.75em; |
||||
} |
||||
|
||||
/* CTA Buttons */ |
||||
|
||||
.osano-cm-dialog__buttons { |
||||
display: flex; |
||||
justify-content: flex-start; |
||||
flex-wrap: wrap; |
||||
gap: 0.5em 0.75em; |
||||
} |
||||
.osano-cm-button { |
||||
font-family: var(--fHeading); |
||||
flex: 1 1 20em; |
||||
color: var(--md-primary-fg-color); |
||||
background-color: transparent; |
||||
border-width: 2px; |
||||
border-color: var(--md-primary-fg-color); |
||||
border-radius: 20em; |
||||
} |
||||
.osano-cm-button:hover { |
||||
color: var(--md-accent-fg-color); |
||||
background-color: transparent; |
||||
border-color: var(--md-accent-fg-color); |
||||
} |
||||
|
||||
/* Widget */ |
||||
|
||||
.osano-cm-widget { |
||||
display: none; |
||||
opacity: 0.5; |
||||
border-radius: 10em; |
||||
bottom: 3em; |
||||
} |
||||
.osano-cm-widget:focus { |
||||
outline-offset: 0.125em; |
||||
outline-color: var(--md-default-fg-color--lighter); |
||||
outline-width: 0.1875em; |
||||
} |
||||
.osano-cm-widget__outline { |
||||
fill: transparent; |
||||
stroke: var(--md-typeset-color); |
||||
} |
||||
.osano-cm-widget__dot { |
||||
fill: var(--md-typeset-color); |
||||
} |
||||
|
||||
/* Media conditions */ |
||||
|
||||
@media screen and (min-width: 768px) { |
||||
.osano-cm-dialog--type_bar .osano-cm-dialog__content { |
||||
max-width: 50em; |
||||
} |
||||
.osano-cm-dialog--type_bar .osano-cm-dialog__buttons { |
||||
max-width: 20em; |
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
/* Overrides */ |
||||
|
||||
:root { |
||||
--md-primary-fg-color--dark: var(--night400); |
||||
} |
||||
.md-header, |
||||
.md-tabs { |
||||
background: |
||||
-o-linear-gradient( |
||||
340deg, |
||||
rgba(0,0,0,0.3) 33%, |
||||
rgba(0,0,0,0.2) 95% |
||||
), |
||||
-o-linear-gradient( |
||||
340deg, |
||||
rgb(78,91,150) 33%, |
||||
rgb(67,158,255) 95% |
||||
); |
||||
background: |
||||
linear-gradient( |
||||
110deg, |
||||
rgba(0,0,0,0.3) 33%, |
||||
rgba(0,0,0,0.2) 95% |
||||
), |
||||
linear-gradient( |
||||
110deg, |
||||
rgb(78,91,150) 33%, |
||||
rgb(67,158,255) 95% |
||||
); |
||||
} |
||||
@media screen and (max-width: 76.1875em) { |
||||
.md-nav--primary .md-nav__title[for="__drawer"], |
||||
.md-nav--primary .md-nav__title { |
||||
background: |
||||
-o-linear-gradient( |
||||
340deg, |
||||
rgba(0,0,0,0.3) 33%, |
||||
rgba(0,0,0,0.2) 95% |
||||
), |
||||
-o-linear-gradient( |
||||
340deg, |
||||
rgb(78,91,150) 33%, |
||||
rgb(67,158,255) 95% |
||||
); |
||||
background: |
||||
linear-gradient( |
||||
110deg, |
||||
rgba(0,0,0,0.3) 33%, |
||||
rgba(0,0,0,0.2) 95% |
||||
), |
||||
linear-gradient( |
||||
110deg, |
||||
rgb(78,91,150) 33%, |
||||
rgb(67,158,255) 95% |
||||
); |
||||
} |
||||
} |
||||
.superNav, |
||||
.md-nav__source { |
||||
background-color: var(--night500); |
||||
} |
@ -0,0 +1,44 @@ |
||||
# Decrypt an encrypted table |
||||
|
||||
## Method 1. Change the access method |
||||
|
||||
If you encrypted a table with the `tde_heap` or `tde_heap_basic` access method and need to decrypt it, run the following command against the desired table (`mytable` in the example below): |
||||
|
||||
``` |
||||
ALTER TABLE mytable SET access method heap; |
||||
``` |
||||
|
||||
Check that the table is not encrypted: |
||||
|
||||
``` |
||||
SELECT pg_tde_is_encrypted('mytable'); |
||||
``` |
||||
|
||||
The output returns `f` meaning that the table is no longer encrypted. |
||||
|
||||
!!! note "" |
||||
|
||||
In the same way you can re-encrypt the data with the `tde_heap_basic` access method. |
||||
|
||||
``` |
||||
ALTER TABLE mytable SET access method tde_heap_basic; |
||||
``` |
||||
|
||||
Note that the indexes and WAL files will no longer be encrypted. |
||||
|
||||
## Method 2. Create a new unencrypted table on the base of the encrypted one |
||||
|
||||
Alternatively, you can create a new unencrypted table with the same structure and data as the initial table. For example, the original encrypted table is `EncryptedCustomers`. Use the following command to create a new table `Customers`: |
||||
|
||||
``` |
||||
CREATE TABLE Customers AS |
||||
SELECT * FROM EncryptedCustomers; |
||||
``` |
||||
|
||||
The new table `Customers` inherits the structure and the data from `EncryptedCustomers`. |
||||
|
||||
(Optional) If you no longer need the `EncryptedCustomers` table, you can delete it. |
||||
|
||||
``` |
||||
DROP TABLE EncryptedCustomers; |
||||
``` |
@ -0,0 +1,34 @@ |
||||
# Use external reference to parameters |
||||
|
||||
To allow storing secrets or any other parameters in a more secure, external location, `pg_tde` |
||||
allows users to specify an external reference instead of hardcoded parameters. |
||||
|
||||
In Alpha1 version, `pg_tde` supports the following external storage methods: |
||||
|
||||
* `file`, which just stores the data in a simple file specified by a `path`. The file should be |
||||
readable to the postgres process. |
||||
* `remote`, which uses a HTTP request to retrieve the parameter from the specified `url`. |
||||
|
||||
## Examples |
||||
|
||||
To use the file provider with a file location specified by the `remote` method, |
||||
use the following command: |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_file( |
||||
'file-provider', |
||||
json_object( 'type' VALUE 'remote', 'url' VALUE 'http://localhost:8888/hello' ) |
||||
);" |
||||
``` |
||||
|
||||
Or to use the `file` method, use the following command: |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_file( |
||||
'file-provider', |
||||
json_object( 'type' VALUE 'remote', 'path' VALUE '/tmp/datafile-location' ) |
||||
);" |
||||
``` |
||||
|
||||
Any parameter specified to the `add_key_provider` function can be a `json_object` instead of the string, |
||||
similar to the above examples. |
@ -0,0 +1,30 @@ |
||||
# FAQ |
||||
|
||||
## Why do I need TDE? |
||||
|
||||
- Compliance to security and legal regulations like GDPR, PCI DSS and others |
||||
- Encryption of backups |
||||
- Granular encryption of specific data sets and reducing the performance overhead that encryption brings |
||||
- Additional layer of security to existing security measures |
||||
|
||||
## I use disk-level encryption. Why should I care about TDE? |
||||
|
||||
Encrypting a hard drive encrypts all data including system and application files that are there. However, disk encryption doesn’t protect your data after the boot-up of your system. During runtime, the files are decrypted with disk-encryption. |
||||
|
||||
TDE focuses specifically on data files and offers a more granular control over encrypted data. It also ensures that files are encrypted on disk during runtime and when moved to another system or storage. |
||||
|
||||
Consider using TDE and storage-level encryption together to add another layer of data security |
||||
|
||||
## Is TDE enough to ensure data security? |
||||
|
||||
No. TDE is an additional layer to ensure data security. It protects data at rest. Consider introducing also these measures: |
||||
|
||||
* Access control and authentication |
||||
* Strong network security like TLS |
||||
* Disk encryption |
||||
* Regular monitoring and auditing |
||||
* Additional data protection for sensitive fields (e.g., application-layer encryption) |
||||
|
||||
## What happens to my data if I lose a principal key? |
||||
|
||||
If you lose encryption keys, especially, the principal key, the data is lost. That's why it's critical to back up your encryption keys securely. |
@ -0,0 +1,18 @@ |
||||
# Features |
||||
|
||||
We provide `pg_tde` in two versions for both PostgreSQL Community and [Percona Server for PostgreSQL](https://docs.percona.com/postgresql/17/). The difference between the versions is in the set of included features which in its turn depends on the Storage Manager API. While PostgreSQL Community uses the default Storage Manager API, Percona Server for PostgreSQL extends the Storage Manager API enabling to integrate custom storage managers. |
||||
|
||||
The following table provides features available for each version: |
||||
|
||||
| PostgreSQL Community version | Percona Server for PostgreSQL version <br> | |
||||
|----------------------|-------------------------------| |
||||
| Table encryption: <br> - data tables, <br> - TOAST tables <br> - temporary tables created during the database operation.<br><br> Metadata of those tables is not encrypted. | Table encryption: <br> - data tables, <br> - **Index data for encrypted tables**, <br> - TOAST tables, <br> - temporary tables created during the database operation.<br><br> Metadata of those tables is not encrypted. | |
||||
| Write-Ahead Log (WAL) encryption of data in encrypted tables | **Global** Write-Ahead Log (WAL) encryption: for data in encrypted and non-encrypted tables | |
||||
| Multi-tenancy support| Multi-tenancy support | |
||||
| Table-level granularity |Table-level granularity | |
||||
| Key management via: <br> - HashiCorp Vault; <br> - Local keyfile | Key management via: <br> - HashiCorp Vault; <br> - KMIP server; <br> - Local keyfile| |
||||
| | Logical replication of encrypted tables | |
||||
|
||||
|
||||
|
||||
[Get started](install.md){.md-button} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,108 @@ |
||||
# Functions |
||||
|
||||
The `pg_tde` extension provides the following functions: |
||||
|
||||
## pg_tde_add_key_provider_file |
||||
|
||||
Creates a new key provider for the database using a local file. |
||||
|
||||
This function is intended for development, and stores the keys unencrypted in the specified data file. |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_file('provider-name','/path/to/the/keyring/data.file'); |
||||
``` |
||||
|
||||
All parameters can be either strings, or JSON objects [referencing remote parameters](external-parameters.md). |
||||
|
||||
## pg_tde_add_key_provider_vault_v2 |
||||
|
||||
Creates a new key provider for the database using a remote HashiCorp Vault server. |
||||
|
||||
The specified access parameters require permission to read and write keys at the location. |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_vault_v2('provider-name','secret_token','url','mount','ca_path'); |
||||
``` |
||||
|
||||
where: |
||||
|
||||
* `url` is the URL of the Vault server |
||||
* `mount` is the mount point where the keyring should store the keys |
||||
* `secret_token` is an access token with read and write access to the above mount point |
||||
* [optional] `ca_path` is the path of the CA file used for SSL verification |
||||
|
||||
All parameters can be either strings, or JSON objects [referencing remote parameters](external-parameters.md). |
||||
|
||||
## pg_tde_add_key_provider_kmip |
||||
|
||||
Creates a new key provider for the database using a remote KMIP server. |
||||
|
||||
The specified access parameters require permission to read and write keys at the server. |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_kmip('provider-name','kmip-IP', 5696, '/path_to/server_certificate.pem', '/path_to/client_key.pem'); |
||||
``` |
||||
|
||||
where: |
||||
|
||||
* `provider-name` is the name of the provider. You can specify any name, it's for you to identify the provider. |
||||
* `kmip-IP` is the IP address of a domain name of the KMIP server |
||||
* The port to communicate with the KMIP server. The default port is `5696`. |
||||
* `server-certificate` is the path to the certificate file for the KMIP server. |
||||
* `client key` is the path to the client key. |
||||
|
||||
## pg_tde_set_principal_key |
||||
|
||||
Sets the principal key for the database using the specified key provider. |
||||
|
||||
The principal key name is also used for constructing the name in the provider, for example on the remote Vault server. |
||||
|
||||
You can use this function only to a principal key. For changes in the principal key, use the [`pg_tde_rotate_principal_key`](#pg_tde_rotate_principal_key) function. |
||||
|
||||
``` |
||||
SELECT pg_tde_set_principal_key('name-of-the-principal-key', 'provider-name'); |
||||
``` |
||||
|
||||
## pg_tde_rotate_principal_key |
||||
|
||||
Creates a new version of the specified principal key and updates the database so that it uses the new principal key version. |
||||
|
||||
When used without any parameters, the function will just create a new version of the current database |
||||
principal key, using the same provider: |
||||
|
||||
``` |
||||
SELECT pg_tde_rotate_principal_key(); |
||||
``` |
||||
|
||||
Alternatively, you can pass two parameters to the function, specifying both a new key name and a new provider name: |
||||
|
||||
``` |
||||
SELECT pg_tde_rotate_principal_key('name-of-the-new-principal-key', 'name-of-the-new-provider'); |
||||
``` |
||||
|
||||
Both parameters support the `NULL` value, which means that the parameter won't be changed: |
||||
|
||||
``` |
||||
-- creates new principal key on the same provider as before |
||||
SELECT pg_tde_rotate_principal_key('name-of-the-new-principal-key', NULL); |
||||
|
||||
-- copies the current principal key to a new provider |
||||
SELECT pg_tde_rotate_principal_key(NULL, 'name-of-the-new-provider'); |
||||
``` |
||||
|
||||
|
||||
## pg_tde_is_encrypted |
||||
|
||||
Tells if a table is encrypted using the `tde_heap` access method or not. |
||||
|
||||
To verify a table encryption, run the following statement: |
||||
|
||||
``` |
||||
SELECT pg_tde_is_encrypted('table_name'); |
||||
``` |
||||
|
||||
You can also verify if the table in a custom schema is encrypted. Pass teh schema name for the function as follows: |
||||
|
||||
``` |
||||
SELECT pg_tde_is_encrypted('schema.table_name'); |
||||
``` |
@ -0,0 +1,58 @@ |
||||
# `pg_tde` documentation |
||||
|
||||
`pg_tde` is the open source PostgreSQL extension that provides Transparent Data Encryption (TDE) to protect data at rest. This ensures that the data stored on disk is encrypted, and no one can read it without the proper encryption keys, even if they gain access to the physical storage media. |
||||
|
||||
You can configure encryption differently for each database, encrypting specific tables in some databases with different encryption keys while keeping others unencrypted. |
||||
|
||||
Lear more [what is Transparent Data Encryption](tde.md#how-does-it-work) and [why you need it](tde.md#why-do-you-need-tde). |
||||
|
||||
!!! important |
||||
|
||||
This is the {{release}} version of the extension and it is not meant for production use yet. We encourage you to use it in testing environments and [provide your feedback](https://forums.percona.com/c/postgresql/pg-tde-transparent-data-encryption-tde/82). |
||||
|
||||
[Get started](install.md){.md-button} |
||||
[What's new in pg_tde {{release}}](release-notes/release-notes.md){.md-button} |
||||
|
||||
## What's encrypted: |
||||
|
||||
* User data in tables, including TOAST tables, that are created using the extension. Metadata of those tables is not encrypted. |
||||
* Temporary tables created during the database operation for data tables created using the extension |
||||
* Write-Ahead Log (WAL) data for the entire database cluster. This includes WAL data in encrypted and non-encrypted tables |
||||
* Indexes on encrypted tables |
||||
* Logical replication on encrypted tables |
||||
|
||||
[Check the full feature list](features.md){.md-button} |
||||
|
||||
## Known limitations |
||||
|
||||
* Keys in the local keyfile are stored unencrypted. For better security we recommend using the Key management storage. |
||||
* System tables are currently not encrypted. |
||||
* Currently you cannot update the configuration of an existing Key Management Store (KMS). If its configuration changes (e.g. your Vault server has a new URL), you must set up a new key provider in `pg_tde` and create new keys there. Both the KMS and PostgreSQL servers must be up and running during these changes. [Reach out to our experts](https://www.percona.com/about/contact) for assistance and to outline the best update path for you. |
||||
|
||||
We plan to introduce the way to update the configuration of an existing KMS in future releases. |
||||
|
||||
* `pg_rewind` doesn't work with encrypted WAL for now. We plan to fix it in future releases. |
||||
|
||||
|
||||
<i warning>:material-alert: Warning:</i> Note that introducing encryption/decryption affects performance. Our benchmark tests show less than 10% performance overhead for most situations. However, in some specific applications such as those using JSONB operations, performance degradation might be higher. |
||||
|
||||
## Versions and supported PostgreSQL deployments |
||||
|
||||
The `pg_tde` extension comes in two distinct versions with specific access methods to encrypt the data. These versions are database-specific and differ in terms of what they encrypt and with what access method. Each version is characterized by the database it supports, the access method it provides, and the scope of encryption it offers. |
||||
|
||||
* **Version for Percona Server for PostgreSQL** |
||||
|
||||
This `pg_tde` version is based on and supported for [Percona Server for PostgreSQL 17.x :octicons-link-external-16:](https://docs.percona.com/postgresql/17/postgresql-server.html) - an open source binary drop-in replacement for PostgreSQL Community. It provides the `tde_heap` access method and offers [full encryption capabilities](features.md). |
||||
|
||||
* **Community version** |
||||
|
||||
This version is supported for PostgreSQL Community 16 and 17, and Percona Distribution for PostgreSQL 16. It provides the `tde_heap_basic` access method, offering limited encryption features. The limitations are in encrypting WAL data only for tables created using the extension and no support of index encryption nor logical replication. |
||||
|
||||
### Which version to chose? |
||||
|
||||
The answer is pretty straightforward: for data sets where indexing is not mandatory or index encryption is not required, use the community version and the `tde_heap_basic` access method. Check the [upstream documentation :octicons-link-external-16:](https://github.com/percona/pg_tde/blob/main/README.md) how to get started. |
||||
|
||||
Otherwise, enjoy full encryption with the Percona Server for PostgreSQL version and the `tde_heap` access method. |
||||
|
||||
Still not sure? [Contact our experts](https://www.percona.com/about/contact) to find the best solution for you. |
||||
|
@ -0,0 +1,93 @@ |
||||
# Installation |
||||
|
||||
## Considerations |
||||
|
||||
You can use the following options to manage encryption keys: |
||||
|
||||
* Use the HashiCorp Vault server. This is the recommended approach. The Vault server configuration is out of scope of this document. We assume that you have the Vault server up and running. For the `pg_tde` configuration, you need the following information: |
||||
|
||||
* The secret access token to the Vault server |
||||
* The URL to access the Vault server |
||||
* (Optional) The CA file used for SSL verification |
||||
|
||||
* Use the local keyfile. This approach is rather used for development and testing purposes since the keys are stored unencrypted in the specified keyfile. |
||||
|
||||
## Procedure |
||||
|
||||
Install `pg_tde` using one of available installation methods: |
||||
|
||||
|
||||
=== "Package manager" |
||||
|
||||
The packages are available for the following operating systems: |
||||
|
||||
- Red Hat Enterprise Linux 8 and compatible derivatives |
||||
- Red Hat Enterprise Linux 9 and compatible derivatives |
||||
- Ubuntu 20.04 (Focal Fossa) |
||||
- Ubuntu 22.04 (Jammy Jellyfish) |
||||
- Ubuntu 24.04 (Noble Numbat) |
||||
- Debian 11 (Bullseye) |
||||
- Debian 12 (Bookworm) |
||||
|
||||
[Install on Debian or Ubuntu](apt.md){.md-button} |
||||
[Install on RHEL or derivatives](yum.md){.md-button} |
||||
|
||||
=== "Build from source" |
||||
|
||||
To build `pg_tde` from source code, do the following |
||||
|
||||
1. On Ubuntu/Debian: Install the following dependencies required for the build: |
||||
|
||||
```sh |
||||
sudo apt install make gcc postgresql-server-dev-17 libcurl4-openssl-dev |
||||
``` |
||||
|
||||
2. [Install Percona Distribution for PostgreSQL 17 :octicons-link-external-16:](https://docs.percona.com/postgresql/17/installing.html) or [upstream PostgreSQL 17 :octicons-link-external-16:](https://www.postgresql.org/download/) |
||||
|
||||
3. If PostgreSQL is installed in a non standard directory, set the `PG_CONFIG` environment variable to point to the `pg_config` executable. |
||||
|
||||
4. Clone the repository: |
||||
|
||||
``` |
||||
git clone git://github.com/percona/pg_tde |
||||
``` |
||||
|
||||
5. Compile and install the extension |
||||
|
||||
``` |
||||
cd pg_tde |
||||
make USE_PGXS=1 |
||||
sudo make USE_PGXS=1 install |
||||
``` |
||||
|
||||
=== "Run in Docker" |
||||
|
||||
!!! note |
||||
|
||||
The steps below are for the `pg_tde` community version. |
||||
|
||||
To run `pg_tde` version for Percona Server for PostgreSQL, [use the Percona Distribution for PostgreSQL Docker image :octicons-link-external-16:](https://docs.percona.com/postgresql/17/docker.html). |
||||
|
||||
You can find Docker images built from the current main branch on [Docker Hub](https://hub.docker.com/r/perconalab/pg_tde). Images are built on top of [postgres:16](https://hub.docker.com/_/postgres) official image. |
||||
|
||||
To run `pg_tde` in Docker, use the following command: |
||||
|
||||
``` |
||||
docker run --name pg-tde -e POSTGRES_PASSWORD=mysecretpassword -d perconalab/pg_tde |
||||
``` |
||||
|
||||
It builds and adds `pg_tde` extension to PostgreSQL 16. The `postgresql.conf` contains the required modifications. The `pg_tde` extension is added to `template1` so that all new databases automatically have the `pg_tde` extension loaded. |
||||
|
||||
Keys are not created automatically. You must configure a key provider and a principal key for each database where you wish to use encrypted tables. See the instructions in the [Setup](setup.md) section, starting with the 4th point, as the first 3 steps are already completed in the Docker image. |
||||
|
||||
See [Docker Docs](https://hub.docker.com/_/postgres) on usage. |
||||
|
||||
You can also build a Docker image manually with: |
||||
|
||||
``` |
||||
docker build . -f ./docker/Dockerfile -t your-image-name |
||||
``` |
||||
|
||||
## Next steps |
||||
|
||||
[Setup](setup.md){.md-button} |
@ -0,0 +1,6 @@ |
||||
var consent = __md_get("__consent") |
||||
if (consent && consent.custom) { |
||||
/* The user accepted the cookie */ |
||||
} else { |
||||
/* The user rejected the cookie */ |
||||
} |
@ -0,0 +1,44 @@ |
||||
document.addEventListener("DOMContentLoaded", function(){ |
||||
// get collection of code blocks:
|
||||
const collection = document.getElementsByClassName("highlight"); |
||||
for (let i = 0; i < collection.length; i++) { |
||||
const commandElement=collection.item(i); |
||||
let commandButtonElement = commandElement.getElementsByTagName("button"); |
||||
// read the prompt string from an attribute of the code block:
|
||||
let promptString = commandElement.getAttribute("data-prompt"); |
||||
if (!promptString) continue; |
||||
let commandCodeElement = commandElement.getElementsByTagName("code"); |
||||
let commandCodeElementString = commandCodeElement.item(0).textContent; |
||||
let trueCommand = commandCodeElementString; |
||||
if (commandCodeElementString.startsWith(promptString)) { |
||||
// remove the first occurrence of the prompt:
|
||||
trueCommand = commandCodeElementString.substring(promptString.length, commandCodeElementString.length).trim(); |
||||
} |
||||
// remove other occurrencies in case of a multi-line string:
|
||||
trueCommand = trueCommand.replaceAll("\n"+promptString, "\n").replace(/^[^\S\r\n]+/gm, ""); |
||||
|
||||
// CHECK IF THERE IS A SECOND PROMPT:
|
||||
promptString = commandElement.getAttribute("data-prompt-second"); |
||||
if (promptString) { |
||||
if (trueCommand.startsWith(promptString)) { |
||||
trueCommand = trueCommand.substring(promptString.length, trueCommand.length).trim(); |
||||
} |
||||
trueCommand = trueCommand.replaceAll("\n"+promptString, "\n").replace(/^[^\S\r\n]+/gm, ""); |
||||
} |
||||
|
||||
// CHECK IF THERE IS A THIRD PROMPT:
|
||||
promptString = commandElement.getAttribute("data-prompt-third"); |
||||
if (promptString) { |
||||
if (trueCommand.startsWith(promptString)) { |
||||
trueCommand = trueCommand.substring(promptString.length, trueCommand.length).trim(); |
||||
} |
||||
trueCommand = trueCommand.replaceAll("\n"+promptString, "\n").replace(/^[^\S\r\n]+/gm, ""); |
||||
} |
||||
// attach the updated command as an attribute to the button where clipboard.js will find it:
|
||||
commandButtonElement.item(0).setAttribute("data-clipboard-text", trueCommand); |
||||
} |
||||
}); |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,100 @@ |
||||
# pg_tde release notes |
||||
|
||||
`pg_tde` extension brings in [Transparent Data Encryption (TDE)](tde.md) to PostgreSQL and enables you to keep sensitive data safe and secure. |
||||
|
||||
[Get started](../install.md){.md-button} |
||||
|
||||
## Beta 2 (2024-12-16) |
||||
|
||||
With this release, `pg_tde` extension offers two database specific versions: |
||||
|
||||
* PostgreSQL Community version provides only the `tde_heap_basic` access method using which you can introduce table encryption and WAL encryption for data in the encrypted tables. Index data remains unencrypted. |
||||
* Version for Percona Server for PostgreSQL provides the `tde_heap`access method. using this method you can encrypt index data in encrypted tables thus increasing the safety of your sensitive data. For backward compatibility, the `tde_heap_basic` method is available in this version too. |
||||
|
||||
The Beta 2 version introduces the following features and improvements: |
||||
|
||||
### New Features |
||||
|
||||
* Added the `tde_heap` access method with which you can now enable index encryption for encrypted tables and global WAL data encryption. To use this access method, you must install Percona Server for PostgreSQL. Check the [installation guide](../install.md) |
||||
* Added event triggers to identify index creation operations on encrypted tables and store those in a custom storage. |
||||
* Added support for secure transfer of keys using the [OASIS Key Management Interoperability Protocol (KMIP)](https://docs.oasis-open.org/kmip/kmip-spec/v2.0/os/kmip-spec-v2.0-os.html). The KMIP implementation was tested with the PyKMIP server and the HashiCorp Vault Enterprise KMIP Secrets Engine. |
||||
|
||||
|
||||
### Improvements |
||||
|
||||
* WAL encryption improvements: |
||||
|
||||
* Added a global key to encrypt WAL data in global space |
||||
* Added WAL key management |
||||
|
||||
* Keyring improvements: |
||||
|
||||
* Renamed functions to point their usage for principal key management |
||||
* Improved keyring provider management across databases and the global space. |
||||
* Keyring configuration now uses common JSON API. This simplifies code handling and enables frontend tools like `pg_waldump` to read the code thus improving debugging. |
||||
|
||||
* The `pg_tde_is_encrypted` function now supports custom schemas in the format of `pg_tde_is_encrypted('schema.table');` |
||||
* Changed the location of internal TDE files: instead of the database directory, now all files are stored in ` $PGDATA/pg_tde` |
||||
* Improved error reporting when `pg_tde` is not added to the `shared_preload_libraries` |
||||
* Improved memory usage of `tde_heap_basic `during sequential reads |
||||
* Improved `tde_heap_basic` for select statements |
||||
* Added encryption support for (some) command line utilities |
||||
|
||||
### Bugs fixed |
||||
|
||||
* Fixed multiple bugs with `tde_heap_basic` and TOAST records |
||||
* Fixed various memory leaks |
||||
|
||||
## Beta (2024-06-30) |
||||
|
||||
With this version, the access method for `pg_tde` extension is renamed `tde_heap_basic`. Use this access method name to create tables. Find guidelines in [Test TDE](../test.md) tutorial. |
||||
|
||||
The Beta version introduces the following bug fixes and improvements: |
||||
|
||||
* Fixed the issue with `pg_tde` running out of memory used for decrypted tuples. The fix introduces the new component `TDEBufferHeapTupleTableSlot` that keeps track of the allocated memory for decrypted tuples and frees this memory when the tuple slot is no longer needed. |
||||
|
||||
* Fixed the issue with adjusting a current position in a file by using raw file descriptor for the `lseek` function. (Thanks to user _rainhard_ for providing the fix) |
||||
|
||||
* Enhanced the init script to consider a custom superuser for the POSTGRES_USER parameter when `pg_tde` is running via Docker (Thanks to _Alejandro Paredero_ for reporting the issue) |
||||
|
||||
|
||||
|
||||
## Alpha 1 (2024-03-28) |
||||
|
||||
### Release Highlights |
||||
|
||||
The Alpha1 version of the extension introduces the following key features: |
||||
|
||||
* You can now rotate principal keys used for data encryption. This reduces the risk of long-term exposure to potential attacks and helps you comply with security standards such as GDPR, HIPAA, and PCI DSS. |
||||
|
||||
* You can now configure encryption differently for each database. For example, encrypt specific tables in some databases with different encryption keys while keeping others non-encrypted. |
||||
|
||||
* Keyring configuration has undergone several improvements, namely: |
||||
|
||||
* You can define separate keyring configuration for each database |
||||
* You can change keyring configuration dynamically, without having to restart the server |
||||
* The keyring configuration is now stored in a catalog separately for each database, instead of a configuration file |
||||
* Avoid storing secrets in the unencrypted catalog by configuring keyring parameters to be read from external sources (file, http(s) request) |
||||
|
||||
### Improvements |
||||
|
||||
* Renamed the repository and Docker image from `postgres-tde-ext` to `pg_tde`. The extension name remains unchanged |
||||
* Changed the Initialization Vector (IV) calculation of both the data and internal keys |
||||
|
||||
### Bugs fixed |
||||
|
||||
* Fixed toast related crashes |
||||
* Fixed a crash with the DELETE statement |
||||
* Fixed performance-related issues |
||||
* Fixed a bug where `pg_tde` sent many 404 requests to the Vault server |
||||
* Fixed сompatibility issues with old OpenSSL versions |
||||
* Fixed сompatibility with old Curl versions |
||||
|
||||
## MVP (2023-12-12) |
||||
|
||||
The Minimum Viable Product (MVP) version introduces the following functionality: |
||||
|
||||
* Encryption of heap tables, including TOAST |
||||
* Encryption keys are stored either in Hashicorp Vault server or in local keyring file (for development) |
||||
* The key storage is configurable via separate JSON configuration files |
||||
* Replication support |
@ -0,0 +1,192 @@ |
||||
# Set up `pg_tde` |
||||
|
||||
## Enable extension |
||||
|
||||
Load the `pg_tde` at the start time. The extension requires additional shared memory; therefore, add the `pg_tde` value for the `shared_preload_libraries` parameter and restart the `postgresql` instance. |
||||
|
||||
1. Use the [ALTER SYSTEM](https://www.postgresql.org/docs/current/sql-altersystem.html) command from `psql` terminal to modify the `shared_preload_libraries` parameter. This requires superuser privileges. |
||||
|
||||
``` |
||||
ALTER SYSTEM SET shared_preload_libraries = 'pg_tde'; |
||||
``` |
||||
|
||||
2. Start or restart the `postgresql` instance to apply the changes. |
||||
|
||||
* On Debian and Ubuntu: |
||||
|
||||
```sh |
||||
sudo systemctl restart postgresql.service |
||||
``` |
||||
|
||||
* On RHEL and derivatives |
||||
|
||||
```sh |
||||
sudo systemctl restart postgresql-17 |
||||
``` |
||||
|
||||
3. Create the extension using the [CREATE EXTENSION](https://www.postgresql.org/docs/current/sql-createextension.html) command. You must have the privileges of a superuser or a database owner to use this command. Connect to `psql` as a superuser for a database and run the following command: |
||||
|
||||
``` |
||||
CREATE EXTENSION pg_tde; |
||||
``` |
||||
|
||||
By default, the `pg_tde` extension is created for the currently used database. To enable data encryption in other databases, you must explicitly run the `CREATE EXTENSION` command against them. |
||||
|
||||
!!! tip |
||||
|
||||
You can have the `pg_tde` extension automatically enabled for every newly created database. Modify the template `template1` database as follows: |
||||
|
||||
```sh |
||||
psql -d template1 -c 'CREATE EXTENSION pg_tde;' |
||||
``` |
||||
|
||||
## Key provider configuration |
||||
|
||||
1. Set up a key provider for the database where you have enabled the extension. |
||||
|
||||
=== "With KMIP server" |
||||
|
||||
Make sure you have obtained the root certificate for the KMIP server and the keypair for the client. The client key needs permissions to create / read keys on the server. Find the [configuration guidelines for the HashiCorp Vault Enterprise KMIP Secrets Engine](https://developer.hashicorp.com/vault/tutorials/enterprise/kmip-engine). |
||||
|
||||
For testing purposes, you can use the PyKMIP server which enables you to set up required certificates. To use a real KMIP server, make sure to obtain the valid certificates issued by the key management appliance. |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_kmip('provider-name','kmip-IP', 5696, '/path_to/server_certificate.pem', '/path_to/client_key.pem'); |
||||
``` |
||||
|
||||
where: |
||||
|
||||
* `provider-name` is the name of the provider. You can specify any name, it's for you to identify the provider. |
||||
* `kmip-IP` is the IP address of a domain name of the KMIP server |
||||
* `port` is the port to communicate with the KMIP server. Typically used port is 5696. |
||||
* `server-certificate` is the path to the certificate file for the KMIP server. |
||||
* `client key` is the path to the client key. |
||||
|
||||
<i warning>:material-information: Warning:</i> This example is for testing purposes only: |
||||
|
||||
The Vault server setup is out of scope of this document. |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_kmip('kmip','127.0.0.1', 5696, '/tmp/server_certificate.pem', '/tmp/client_key_jane_doe.pem'); |
||||
``` |
||||
|
||||
=== "With HashiCorp Vault" |
||||
|
||||
The Vault server setup is out of scope of this document. |
||||
|
||||
```sql |
||||
SELECT pg_tde_add_key_provider_vault_v2('provider-name','root_token','url','mount','ca_path'); |
||||
``` |
||||
|
||||
where: |
||||
|
||||
* `url` is the URL of the Vault server |
||||
* `mount` is the mount point where the keyring should store the keys |
||||
* `root_token` is an access token with read and write access to the above mount point |
||||
* [optional] `ca_path` is the path of the CA file used for SSL verification |
||||
|
||||
<i warning>:material-information: Warning:</i> This example is for testing purposes only: |
||||
|
||||
``` |
||||
SELECT pg_tde_add_key_provider_file_vault_v2('my-vault','https://vault.example.com','secret/data','hvs.zPuyktykA...example...ewUEnIRVaKoBzs2', NULL); |
||||
``` |
||||
|
||||
=== "With a keyring file" |
||||
|
||||
This setup is intended for development and stores the keys unencrypted in the specified data file. |
||||
|
||||
```sql |
||||
SELECT pg_tde_add_key_provider_file('provider-name','/path/to/the/keyring/data.file'); |
||||
``` |
||||
|
||||
<i warning>:material-information: Warning:</i> This example is for testing purposes only: |
||||
|
||||
```sql |
||||
SELECT pg_tde_add_key_provider_file('file-keyring','/tmp/pg_tde_test_local_keyring.per'); |
||||
``` |
||||
|
||||
|
||||
2. Add a principal key |
||||
|
||||
```sql |
||||
SELECT pg_tde_set_principal_key('name-of-the-principal-key', 'provider-name'); |
||||
``` |
||||
|
||||
<i warning>:material-information: Warning:</i> This example is for testing purposes only: |
||||
|
||||
```sql |
||||
SELECT pg_tde_set_principal_key('test-db-master-key','file-vault'); |
||||
``` |
||||
|
||||
The key is auto-generated. |
||||
|
||||
|
||||
<i info>:material-information: Info:</i> The key provider configuration is stored in the database catalog in an unencrypted table. See [how to use external reference to parameters](external-parameters.md) to add an extra security layer to your setup. |
||||
|
||||
|
||||
## WAL encryption configuration |
||||
|
||||
After you [enabled `pg_tde`](#enable-extension) and started the Percona Server for PostgreSQL, a principal key and a keyring for WAL are created. Now you need to instruct `pg_tde ` to encrypt WAL files by configuring WAL encryption. |
||||
|
||||
Here's how to do it: |
||||
|
||||
1. Enable WAL level encryption using the `ALTER SYSTEM SET` command. You need the privileges of the superuser to run this command: |
||||
|
||||
```sql |
||||
ALTER SYSTEM set pg_tde.wal_encrypt = on; |
||||
``` |
||||
|
||||
2. Restart the server to apply the changes. |
||||
|
||||
* On Debian and Ubuntu: |
||||
|
||||
```sh |
||||
sudo systemctl restart postgresql.service |
||||
``` |
||||
|
||||
* On RHEL and derivatives |
||||
|
||||
```sh |
||||
sudo systemctl restart postgresql-17 |
||||
``` |
||||
|
||||
3. We highly recommend you to create your own keyring and rotate the principal key. This is because the default principal key is created from the local keyfile and is stored unencrypted. |
||||
|
||||
Set up the key provider for WAL encryption |
||||
|
||||
=== "With HashiCorp Vault" |
||||
|
||||
```sql |
||||
SELECT pg_tde_add_key_provider_vault_v2('PG_TDE_GLOBAL','provider-name',:'secret_token','url','mount','ca_path'); |
||||
``` |
||||
|
||||
where: |
||||
|
||||
* `PG_TDE_GLOBAL` is the constant that defines the WAL encryption key |
||||
* `provider-name` is the name you define for the key provider |
||||
* `url` is the URL of the Vault server |
||||
* `mount` is the mount point where the keyring should store the keys |
||||
* `secret_token` is an access token with read and write access to the above mount point |
||||
* [optional] `ca_path` is the path of the CA file used for SSL verification |
||||
|
||||
|
||||
=== "With keyring file" |
||||
|
||||
This setup is intended for development and stores the keys unencrypted in the specified data file. |
||||
|
||||
```sql |
||||
SELECT pg_tde_add_key_provider_file('provider-name','/path/to/the/keyring/data.file'); |
||||
``` |
||||
|
||||
4. Rotate the principal key. Don't forget to specify the `PG_TDE_GLOBAL` constant to rotate only the principal key for WAL. |
||||
|
||||
```sql |
||||
SELECT pg_tde_rotate_principal_key('PG_TDE_GLOBAL', 'new-principal-key', 'provider-name'); |
||||
``` |
||||
|
||||
Now all WAL files are encrypted for both encrypted and unencrypted tables. |
||||
|
||||
## Next steps |
||||
|
||||
[Test TDE](test.md){.md-button} |
||||
|
@ -0,0 +1,5 @@ |
||||
# Switch from Percona Server for PostgreSQL to PostgreSQL Community |
||||
|
||||
Percona Server for PostgreSQL and PostgreSQL Community are binary compatible and enable you to switch from one to another. Here's how: |
||||
|
||||
1. If you used the `tde_heap` (tech preview feature) access method for encryption, either re-encrypt the data using the `tde_heap_basic` access method, or [decrypt](decrypt.md) it completely |
@ -0,0 +1,96 @@ |
||||
# Table access method |
||||
|
||||
A table access method is the way how PostgreSQL stores the data in a table. The default table access method is `heap`. PostgreSQL organizes data in a heap structure, meaning there is no particular order to the rows in the table. Each row is stored independently and identified by its unique row identifier (TID). |
||||
|
||||
## How the `heap` access method works |
||||
|
||||
**Insertion**: When a new row is inserted, PostgreSQL finds a free space in the tablespace and stores the row there. |
||||
|
||||
**Deletion**: When a row is deleted, PostgreSQL marks the space occupied by the row as free, but the data remains until it is overwritten by a new insertion. |
||||
|
||||
**Updates**: PostgreSQL handles updates by deleting the old row and inserting a new row with the updated values. |
||||
|
||||
## Custom access method |
||||
|
||||
Custom access methods allow you to implement and define your own way of organizing data in PostgreSQL. This is useful if the default table access method doesn't meet your needs. |
||||
|
||||
Custom access methods are typically available with PostgreSQL extensions. When you install an extension and enable it in PostgreSQL, a custom access method is created. |
||||
|
||||
An example of such an approach is the `tde_heap` access method. It is automatically created **only** for the databases where you [enabled the `pg_tde` extension](setup.md) and configured the key provider, enabling you to encrypt the data. |
||||
|
||||
To use a custom access method, specify the `USING` clause for the `CREATE TABLE` command: |
||||
|
||||
```sql |
||||
CREATE TABLE table_name ( |
||||
column1 data_type, |
||||
column2 data_type, |
||||
... |
||||
) USING tde_heap; |
||||
``` |
||||
|
||||
### How `tde_heap` works |
||||
|
||||
The `tde_heap` access method works on top of the default `heap` access method and is a marker to point which tables require encryption. It uses the custom storage manager TDE SMGR, which becomes active only after you installed the `pg_tde` extension. |
||||
|
||||
Every data modification operation is first sent to the Buffer Manager, which updates the buffer cache. Then, it is passed to the storage manager, which then writes it to disk. When a table requires encryption, the data is sent to the TDE storage manager, where it is encrypted before written to disk. |
||||
|
||||
Similarly, when a client queries the database, the PostgreSQL core sends the request to the Buffer Manager which checks if the requested data is already in the buffer cache. If it’s not there, the Buffer Manager requests the data from the storage manager. The TDE storage manager reads the encrypted data from disk, decrypts it and loads it to the buffer cache. The Buffer Manager sends the requested data to the PostgreSQL core and then to the client. |
||||
|
||||
|
||||
Thus, the encryption is done at the storage manager level. |
||||
|
||||
## Changing the default table access method |
||||
|
||||
You can change the default table access method so that every table in the entire database cluster is created using the custom access method. For example, you can enable data encryption by default by defining the `tde_heap` as the default table access method. |
||||
|
||||
However, consider the following before making this change: |
||||
|
||||
* This is a global setting and applies across the entire database cluster and not just a single database. |
||||
We recommend setting it with caution because all tables and materialized views created without an explicit access method in their `CREATE` statement will default to the specified table access method. |
||||
* You must create the `pg_tde` extension and configure the key provider for all databases before you modify the configuration. Otherwise PostgreSQL won't find the specified access method and will throw an error. |
||||
|
||||
Here's how you can set the new default table access method: |
||||
|
||||
1. Add the access method to the `default_table_access_method` parameter. |
||||
|
||||
=== "via the SQL statement" |
||||
|
||||
Use the `ALTER SYSTEM SET` command. This requires superuser or ALTER SYSTEM privileges. |
||||
|
||||
This example shows how to set the `tde_heap` access method. Replace it with the `tde_heap_basic` if needed. |
||||
|
||||
|
||||
```sql |
||||
ALTER SYSTEM SET default_table_access_method=tde_heap; |
||||
``` |
||||
|
||||
=== "via the configuration file" |
||||
|
||||
Edit the `postgresql.conf` configuration file and add the value for the `default_table_access_method` parameter. |
||||
|
||||
This example shows how to set the `tde_heap` access method. Replace it with the `tde_heap_basic` if needed. |
||||
|
||||
```ini |
||||
default_table_access_method = 'tde_heap' |
||||
``` |
||||
|
||||
=== "via the SET command" |
||||
|
||||
You can use the SET command to change the default table access method temporarily, for the current session. |
||||
|
||||
Unlike modifying the `postgresql.conf` file or using the ALTER SYSTEM SET command, the changes you make via the SET command don't persist after the session ends. |
||||
|
||||
You also don't need to have the superuser privileges to run the SET command. |
||||
|
||||
You can run the SET command anytime during the session. This example shows how to set the `tde_heap` access method. Replace it with the `tde_heap_basic` if needed. |
||||
|
||||
```sql |
||||
SET default_table_access_method = tde_heap; |
||||
``` |
||||
|
||||
2. Reload the configuration to apply the changes: |
||||
|
||||
```sql |
||||
SELECT pg_reload_conf(); |
||||
``` |
||||
|
@ -0,0 +1,43 @@ |
||||
# What is Transparent Data Encryption (TDE) |
||||
|
||||
Transparent Data Encryption is a technology to protect data at rest. The encryption process happens transparently in the background, without affecting database operations. Data is automatically encrypted as it's written to the disk and decrypted as it's read, all in real-time. Users and applications interact with the data as usual without noticing any difference. |
||||
|
||||
## How does it work? |
||||
|
||||
To encrypt the data, two types of keys are used: |
||||
|
||||
* Internal encryption keys to encrypt user data. They are stored internally, near the data that they encrypt. |
||||
* The principal key to encrypt database keys. It is kept separately from the database keys and is managed externally in the key management store. |
||||
|
||||
You have the following options to store and manage principal keys externally: |
||||
|
||||
* Use the HashiCorp Vault server. Only the back end KV Secrets Engine - Version 2 (API) is supported. |
||||
* Use the KMIP-compatible server. `pg_tde` has been tested with the [PyKMIP](https://pykmip.readthedocs.io/en/latest/server.html) server and [the HashiCorp Vault Enterprise KMIP Secrets Engine](https://www.vaultproject.io/docs/secrets/kmip). |
||||
|
||||
The encryption process is the following: |
||||
|
||||
 |
||||
|
||||
When a user creates an encrypted table using `pg_tde`, a new random key is generated for that table using the AES128 (AES-ECB) cipher algorithm. This key is used to encrypt all data the user inserts in that table. Eventually the encrypted data gets stored in the underlying storage. |
||||
|
||||
The table itself is encrypted using the principal key. The principal key is stored externally in the key management store. |
||||
|
||||
Similarly when the user queries the encrypted table, the principal key is retrieved from the key store to decrypt the table. Then the same unique internal key for that table is used to decrypt the data, and unencrypted data gets returned to the user. So, effectively, every TDE table has a unique key, and each table key is encrypted using the principal key. |
||||
|
||||
## Why do you need TDE? |
||||
|
||||
Using TDE has the following benefits: |
||||
|
||||
* For organizations: |
||||
|
||||
- Ensure data safety when it is stored on disk and in backups |
||||
- Comply with security and legal standards like HIPAA, PCI DSS, SOC 2, ISO 27001 |
||||
|
||||
* For DBAs: |
||||
|
||||
- Granular encryption of specific tables and reducing the performance overhead that encryption brings |
||||
- Additional layer of security to existing security measures like storage-level encryption, data encryption in transit using TLS, access control and more. |
||||
|
||||
!!! admonition "See also" |
||||
|
||||
Percona Blog: [Transparent Data Encryption (TDE)](https://www.percona.com/blog/transparent-data-encryption-tde/) |
@ -0,0 +1,52 @@ |
||||
# Test Transparent Data Encryption |
||||
|
||||
Enabling `pg_tde` extension for a database creates the table access method `tde_heap` . This access method enables you to encrypt the data. |
||||
|
||||
Here's how to do it: |
||||
|
||||
1. Create a table in the database for which you have [enabled `pg_tde`](setup.md) using the `tde_heap` access method as follows: |
||||
|
||||
``` |
||||
CREATE TABLE <table_name> (<field> <datatype>) USING tde_heap; |
||||
``` |
||||
|
||||
<i warning>:material-information: Warning:</i> Example for testing purposes only: |
||||
|
||||
``` |
||||
CREATE TABLE albums ( |
||||
album_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, |
||||
artist_id INTEGER, |
||||
title TEXT NOT NULL, |
||||
released DATE NOT NULL |
||||
) USING tde_heap; |
||||
``` |
||||
|
||||
Learn more about table access methods and how you can enable data encryption by default in the [Table access methods](table-access-method.md) section. |
||||
|
||||
2. To check if the data is encrypted, run the following function: |
||||
|
||||
``` |
||||
SELECT pg_tde_is_encrypted('table_name'); |
||||
``` |
||||
|
||||
The function returns `t` if the table is encrypted and `f` - if not. |
||||
|
||||
3. Rotate the principal key when needed: |
||||
|
||||
``` |
||||
SELECT pg_tde_rotate_principal_key(); -- uses automatic key versionin |
||||
-- or |
||||
SELECT pg_tde_rotate_principal_key('new-principal-key', NULL); -- specify new key name |
||||
-- or |
||||
SELECT pg_tde_rotate_principal_key('new-principal-key', 'new-provider'); -- changeprovider |
||||
``` |
||||
|
||||
4. You can encrypt an existing table. It requires rewriting the table, so for large tables, it might take a considerable amount of time. |
||||
|
||||
``` |
||||
ALTER TABLE table_name SET access method tde_heap; |
||||
``` |
||||
|
||||
!!! hint |
||||
|
||||
If you no longer wish to use `pg_tde` or wish to switch to using the `tde_heap_basic` access method, see how you can [decrypt your data](decrypt.md). |
@ -0,0 +1,31 @@ |
||||
# Uninstall `pg_tde` |
||||
|
||||
If you no longer wish to use TDE in your deployment, you can remove the `pg_tde` extension. To do that, your user must have the privileges of the superuser or a database owner. |
||||
|
||||
Here's how to do it: |
||||
|
||||
1. Drop the extension using the `DROP EXTENSION` with `CASCADE` command. |
||||
|
||||
<i warning>:material-alert: Warning:</i> The use of the CASCADE parameter deletes all tables that were created in the database with `pg_tde` enabled and also all dependencies upon the encrypted table (e.g. foreign keys in a non-encrypted table used in the encrypted one). |
||||
|
||||
``` |
||||
DROP EXTENSION pg_tde CASCADE |
||||
``` |
||||
|
||||
2. Run the `DROP EXTENSION` command against every database where you have enabled the `pg_tde` extension |
||||
|
||||
3. Modify the `shared_preload_libraries` and remove the 'pg_tde' from it. Use the `ALTER SYSTEM SET` command for this purpose |
||||
|
||||
4. Start or restart the `postgre` instance to apply the changes. |
||||
|
||||
* On Debian and Ubuntu: |
||||
|
||||
```sh |
||||
sudo systemctl restart postgre.service |
||||
``` |
||||
|
||||
* On RHEL and derivatives |
||||
|
||||
```sh |
||||
sudo systemctl restart postgre-17 |
||||
``` |
@ -0,0 +1,52 @@ |
||||
# Install `pg_tde` on Red Hat Enterprise Linux and derivatives |
||||
|
||||
The packages for the tech preview `pg_tde` are available in the experimental repository for Percona Distribution for PostgreSQL 17. |
||||
|
||||
Check the [list of supported platforms](install.md#__tabbed_1_2). |
||||
|
||||
This tutorial shows how to install `pg_tde` with [Percona Distribution for PostgreSQL](https://docs.percona.com/postgresql/latest/index.html). |
||||
|
||||
## Preconditions |
||||
|
||||
### Install `percona-release` |
||||
|
||||
You need the `percona-release` repository management tool that enables the desired Percona repository for you. |
||||
|
||||
1. Install `percona-release`: |
||||
|
||||
```bash |
||||
sudo yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm |
||||
``` |
||||
|
||||
2. Enable the repository. |
||||
|
||||
Percona provides [two repositories](repo-overview.md) for Percona Distribution for PostgreSQL. We recommend enabling the Major release repository to timely receive the latest updates. |
||||
|
||||
```bash |
||||
sudo percona-release enable-only ppg-{{pgversion17}} |
||||
``` |
||||
|
||||
## Install `pg_tde` |
||||
|
||||
!!! important |
||||
|
||||
The `pg_tde` {{release}} extension is a part of the `percona-postgresql17` package. If you installed a previous version of `pg_tde` from the `percona-pg_tde_17` package, do the following: |
||||
|
||||
* Drop the extension using the `DROP EXTENSION` with `CASCADE` command. |
||||
|
||||
<i warning>:material-alert: Warning:</i> The use of the `CASCADE` parameter deletes all tables that were created in the database with `pg_tde` enabled and also all dependencies upon the encrypted table (e.g. foreign keys in a non-encrypted table used in the encrypted one). |
||||
|
||||
```sql |
||||
DROP EXTENSION pg_tde CASCADE |
||||
``` |
||||
|
||||
* Uninstall the `percona-pg_tde_17` package. |
||||
|
||||
|
||||
```bash |
||||
sudo yum -y install percona-postgresql17 |
||||
``` |
||||
|
||||
## Next steps |
||||
|
||||
[Setup](setup.md){.md-button} |
@ -0,0 +1,16 @@ |
||||
# MkDocs configuration for PDF builds |
||||
# Usage: ENABLE_PDF_EXPORT=1 mkdocs build -f mkdocs-pdf.yml |
||||
|
||||
INHERIT: mkdocs.yml |
||||
|
||||
copyright: Percona LLC, © 2024 |
||||
|
||||
extra_css: |
||||
- https://unicons.iconscout.com/release/v3.0.3/css/line.css |
||||
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css |
||||
- css/extra.css |
||||
|
||||
markdown_extensions: |
||||
pymdownx.tabbed: {} |
||||
admonition: {} |
||||
|
@ -0,0 +1,179 @@ |
||||
# MkDocs general configuration |
||||
|
||||
site_name: pg_tde documentation |
||||
site_description: Documentation |
||||
site_author: Percona LLC |
||||
copyright: > |
||||
<a href="https://www.percona.com/about">Percona LLC</a> and/or its affiliates © 2023 — <a href="#__consent">Cookie Consent</a> |
||||
|
||||
|
||||
repo_name: percona/pg_tde |
||||
repo_url: https://github.com/percona/pg_tde |
||||
edit_uri: edit/main/documentation/docs/ |
||||
|
||||
use_directory_urls: false |
||||
|
||||
# Theme settings |
||||
theme: |
||||
name: material |
||||
logo: _images/postgresql-mark.svg |
||||
favicon: _images/postgresql-fav.svg |
||||
custom_dir: _resource/overrides |
||||
font: |
||||
text: Roboto |
||||
palette: |
||||
- media: "(prefers-color-scheme)" |
||||
toggle: |
||||
icon: material/brightness-auto |
||||
name: Color theme set to Automatic. Click to change |
||||
- media: "(prefers-color-scheme: light)" |
||||
scheme: percona-light |
||||
primary: custom |
||||
accent: custom |
||||
toggle: |
||||
icon: material/brightness-7 |
||||
name: Color theme set to Light Mode. Click to change |
||||
- media: "(prefers-color-scheme: dark)" |
||||
scheme: percona-dark |
||||
primary: custom |
||||
accent: custom |
||||
toggle: |
||||
icon: material/brightness-4 |
||||
name: Color theme set to Dark Mode. Click to change |
||||
|
||||
# Theme features |
||||
|
||||
features: |
||||
- search.share |
||||
- search.highlight |
||||
- content.code.copy |
||||
- content.action.view |
||||
- content.action.edit |
||||
- content.tabs.link |
||||
- navigation.top |
||||
- navigation.tracking |
||||
|
||||
|
||||
|
||||
extra_css: |
||||
- https://unicons.iconscout.com/release/v3.0.3/css/line.css |
||||
- https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css |
||||
- css/percona.css |
||||
- css/design.css |
||||
- css/osano.css |
||||
- css/postgresql.css |
||||
- css/landing.css |
||||
|
||||
extra_javascript: |
||||
- js/version-select.js |
||||
- js/promptremover.js |
||||
- js/consent.js |
||||
|
||||
markdown_extensions: |
||||
- attr_list |
||||
- toc: |
||||
permalink: True |
||||
- admonition |
||||
- md_in_html |
||||
- footnotes |
||||
- def_list # https://michelf.ca/projects/php-markdown/extra/#def-list |
||||
- meta |
||||
- smarty: |
||||
smart_angled_quotes: true |
||||
- pymdownx.mark |
||||
- pymdownx.smartsymbols |
||||
- pymdownx.tilde |
||||
- pymdownx.superfences |
||||
- pymdownx.tabbed: |
||||
alternate_style: true |
||||
- pymdownx.tilde |
||||
- pymdownx.details |
||||
- pymdownx.highlight: |
||||
linenums: false |
||||
- pymdownx.snippets: |
||||
base_path: ["snippets"] |
||||
auto_append: |
||||
- services-banner.md |
||||
- pymdownx.emoji: |
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji |
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg |
||||
options: |
||||
custom_icons: |
||||
- _resource/.icons |
||||
|
||||
|
||||
plugins: |
||||
- search: |
||||
separator: '[\s\-,:!=\[\]()"/]+|(?!\b)(?=[A-Z][a-z])|\.(?!\d)|&[lg]t;' |
||||
- open-in-new-tab: |
||||
- git-revision-date-localized: |
||||
enable_creation_date: true |
||||
enabled: !ENV [ENABLED_GIT_REVISION_DATE, True] |
||||
- meta-descriptions: |
||||
export_csv: false |
||||
quiet: false |
||||
enable_checks: false |
||||
min_length: 50 |
||||
max_length: 160 |
||||
- section-index # Adds links to nodes - comment out when creating PDF |
||||
# - htmlproofer # Uncomment to check links - but extends build time significantly |
||||
- glightbox |
||||
- macros: |
||||
include_yaml: |
||||
- 'variables.yml' # Use in markdown as '{{ VAR }}' |
||||
- with-pdf: # https://github.com/orzih/mkdocs-with-pdf |
||||
output_path: '_pdf/PerconaTDE.pdf' |
||||
cover_title: 'Percona Transparent Data Encryption' |
||||
cover_subtitle: Alpha 1 (2024-03-28) |
||||
author: 'Percona Technical Documentation Team' |
||||
cover_logo: docs/_images/Percona_Logo_Color.png |
||||
debug_html: false |
||||
# two_columns_level: 3 |
||||
custom_template_path: _resource/templates |
||||
enabled_if_env: ENABLE_PDF_EXPORT |
||||
|
||||
extra: |
||||
version: |
||||
provider: mike |
||||
analytics: |
||||
provider: google |
||||
property: G-J4J70BNH0G |
||||
feedback: |
||||
title: Was this page helpful? |
||||
ratings: |
||||
- icon: material/emoticon-happy-outline |
||||
name: This page was helpful |
||||
data: 1 |
||||
note: >- |
||||
Thanks for your feedback! |
||||
- icon: material/emoticon-sad-outline |
||||
name: This page could be improved |
||||
data: 0 |
||||
note: >- |
||||
Thank you for your feedback! Help us improve by using our |
||||
<a href="https://docs.google.com/forms/d/1bkWACehjqlwA0AKf-qTJcXvYbOSYgze8iTPXjntqmNo/edit" target="_blank" rel="noopener"> |
||||
feedback form</a>. |
||||
|
||||
nav: |
||||
- Home: index.md |
||||
- features.md |
||||
- Get started: |
||||
- "Install": "install.md" |
||||
- "Via apt": apt.md |
||||
- "Via yum": yum.md |
||||
- "Set up": "setup.md" |
||||
- "Test TDE": "test.md" |
||||
- functions.md |
||||
- Concepts: |
||||
- "What is TDE": tde.md |
||||
- table-access-method.md |
||||
- How to: |
||||
- Use reference to external parameters: external-parameters.md |
||||
- Decrypt an encrypted table: decrypt.md |
||||
- faq.md |
||||
- Release notes: |
||||
- "pg_tde release notes": release-notes/release-notes.md |
||||
- uninstall.md |
||||
- contribute.md |
||||
|
||||
|
@ -0,0 +1,19 @@ |
||||
|
||||
Markdown |
||||
mkdocs |
||||
mkdocs-versioning |
||||
mkdocs-macros-plugin |
||||
mkdocs-exclude |
||||
markdown-include |
||||
mkdocs-material |
||||
mkdocs-with-pdf |
||||
mkdocs-git-revision-date-localized-plugin |
||||
mkdocs-material-extensions |
||||
mkdocs-bootstrap-tables-plugin |
||||
mkdocs-section-index |
||||
mkdocs-htmlproofer-plugin |
||||
mkdocs-meta-descriptions-plugin |
||||
mike |
||||
mkdocs-glightbox |
||||
Pillow > 10.1.0 |
||||
mkdocs-open-in-new-tab |
@ -0,0 +1,13 @@ |
||||
<div data-banner markdown><svg style="display:block;margin:-1em 0 0.75em" width="78" height="69" viewBox="0 0 78 69" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M56.7281 30.7666C62.6528 26.8938 64.5914 18.9942 61.0059 12.7854C59.2094 9.67113 56.3053 7.44082 52.8311 6.50951C49.6122 5.64535 46.2502 5.99872 43.2912 7.49366L39.251 0.5L30.8648 15.0245L11.4811 48.5937H67.021L56.7281 30.7666ZM51.881 10.0674C54.4064 10.7401 56.5079 12.3616 57.8168 14.6194C60.3895 19.0701 59.053 24.7153 54.8808 27.5665L45.1362 10.6905C47.2355 9.68104 49.6034 9.46087 51.881 10.0674ZM39.251 7.87125L60.6339 44.907H48.1228L32.9927 18.7102L39.2499 7.87235L39.251 7.87125ZM17.8682 44.907L30.8637 22.4035L43.8592 44.907H17.8682Z" fill="url(#paint0_linear_2899_1968)"/><path style="fill:var(--md-typeset-color)" d="M4.981 64.943H3.157V68.207H.756V57.323H5.217C7.822 57.323 9.397 58.861 9.397 61.086V61.116C9.397 63.635 7.433 64.94 4.984 64.94L4.981 64.943V64.943ZM6.961 61.134C6.961 60.061 6.213 59.485 5.011 59.485H3.154V62.812H5.056C6.258 62.812 6.958 62.096 6.958 61.163V61.134H6.961ZM10.738 68.208V57.323H18.973V59.455H13.124V61.664H18.27V63.796H13.124V66.082H19.051V68.214H10.738V68.208 68.208ZM27.557 68.208 25.218 64.726H23.332V68.208H20.931V57.323H25.921C28.496 57.323 30.039 58.677 30.039 60.915V60.945C30.039 62.702 29.088 63.807 27.7 64.32L30.367 68.207H27.556L27.557 68.208ZM27.605 61.041C27.605 60.016 26.887 59.485 25.719 59.485H23.333V62.61H25.767C26.936 62.61 27.605 61.987 27.605 61.071V61.042 61.041ZM36.922 68.499C33.668 68.499 31.249 65.994 31.249 62.825V62.795C31.249 59.659 33.619 57.091 37.019 57.091 39.105 57.091 40.356 57.783 41.383 58.792L39.834 60.571C38.98 59.798 38.113 59.327 37.004 59.327 35.141 59.327 33.795 60.871 33.795 62.762V62.793C33.795 64.684 35.107 66.257 37.004 66.257 38.268 66.257 39.043 65.753 39.913 64.964L41.462 66.524C40.322 67.738 39.059 68.493 36.925 68.493L36.922 68.499ZM47.885 68.499C44.47 68.499 42.021 65.962 42.021 62.825V62.795C42.021 59.659 44.503 57.091 47.915 57.091 51.327 57.091 53.779 59.628 53.779 62.765V62.795C53.779 65.931 51.297 68.499 47.885 68.499ZM51.237 62.795C51.237 60.904 49.846 59.331 47.885 59.331 45.925 59.331 44.567 60.874 44.567 62.766V62.796C44.567 64.688 45.959 66.261 47.919 66.261 49.879 66.261 51.237 64.717 51.237 62.826V62.795 62.795ZM67.001 68.217 72.374 57.091 77.746 68.218H75.052L72.374 62.681 69.705 68.218H67.001V68.217ZM66.007 57.327V68.5L57.813 61.884V68.199H55.264V57.091L63.458 63.681V57.327H66.007Z"/><defs><linearGradient id="paint0_linear_2899_1968" x1="18.1513" y1="44.7152" x2="61.4356" y2="20.9786" gradientUnits="userSpaceOnUse"><stop stop-color="#FC3519"/><stop offset="1" stop-color="#F0D136"/></linearGradient></defs></svg> |
||||
|
||||
## Get expert help { .title } |
||||
|
||||
If you need assistance, visit the community forum for comprehensive and free database knowledge, or contact our Percona Database Experts for professional support and services. |
||||
|
||||
<div class="actions" markdown> |
||||
|
||||
[:material-forum-outline: Community Forum](https://forums.percona.com/c/postgresql/pg-tde-transparent-data-encryption-tde/82) [:percona-logo: Get a Percona Expert](https://www.percona.com/about/contact) |
||||
|
||||
|
||||
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=b95a2b04-c5c7-47f9-bb4e-b7fc13c3ab0d" /> |
||||
</div></div> |
@ -0,0 +1,4 @@ |
||||
#Variables used throughout the docs |
||||
|
||||
release: 'Beta' |
||||
pgversion17: '17.2' |
@ -0,0 +1,73 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/alter_index.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SET default_table_access_method = :"tde_am"; |
||||
CREATE TABLE concur_reindex_part (c1 int, c2 int) PARTITION BY RANGE (c1); |
||||
CREATE TABLE concur_reindex_part_0 PARTITION OF concur_reindex_part |
||||
FOR VALUES FROM (0) TO (10) PARTITION BY list (c2); |
||||
CREATE TABLE concur_reindex_part_0_1 PARTITION OF concur_reindex_part_0 |
||||
FOR VALUES IN (1); |
||||
CREATE TABLE concur_reindex_part_0_2 PARTITION OF concur_reindex_part_0 |
||||
FOR VALUES IN (2); |
||||
-- This partitioned table will have no partitions. |
||||
CREATE TABLE concur_reindex_part_10 PARTITION OF concur_reindex_part |
||||
FOR VALUES FROM (10) TO (20) PARTITION BY list (c2); |
||||
-- Create some partitioned indexes |
||||
CREATE INDEX concur_reindex_part_index ON ONLY concur_reindex_part (c1); |
||||
CREATE INDEX concur_reindex_part_index_0 ON ONLY concur_reindex_part_0 (c1); |
||||
ALTER INDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_0; |
||||
-- This partitioned index will have no partitions. |
||||
CREATE INDEX concur_reindex_part_index_10 ON ONLY concur_reindex_part_10 (c1); |
||||
ALTER INDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_10; |
||||
CREATE INDEX concur_reindex_part_index_0_1 ON ONLY concur_reindex_part_0_1 (c1); |
||||
ALTER INDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_1; |
||||
CREATE INDEX concur_reindex_part_index_0_2 ON ONLY concur_reindex_part_0_2 (c1); |
||||
ALTER INDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_2; |
||||
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index') |
||||
ORDER BY relid, level; |
||||
relid | parentrelid | level |
||||
-------------------------------+-----------------------------+------- |
||||
concur_reindex_part_index | | 0 |
||||
concur_reindex_part_index_0 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_10 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2 |
||||
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2 |
||||
(5 rows) |
||||
|
||||
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index') |
||||
ORDER BY relid, level; |
||||
relid | parentrelid | level |
||||
-------------------------------+-----------------------------+------- |
||||
concur_reindex_part_index | | 0 |
||||
concur_reindex_part_index_0 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_10 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2 |
||||
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2 |
||||
(5 rows) |
||||
|
||||
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index') |
||||
ORDER BY relid, level; |
||||
relid | parentrelid | level |
||||
-------------------------------+-----------------------------+------- |
||||
concur_reindex_part_index | | 0 |
||||
concur_reindex_part_index_0 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_10 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2 |
||||
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2 |
||||
(5 rows) |
||||
|
||||
DROP TABLE concur_reindex_part; |
||||
DROP EXTENSION pg_tde; |
||||
RESET default_table_access_method; |
@ -0,0 +1,73 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/alter_index.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SET default_table_access_method = :"tde_am"; |
||||
CREATE TABLE concur_reindex_part (c1 int, c2 int) PARTITION BY RANGE (c1); |
||||
CREATE TABLE concur_reindex_part_0 PARTITION OF concur_reindex_part |
||||
FOR VALUES FROM (0) TO (10) PARTITION BY list (c2); |
||||
CREATE TABLE concur_reindex_part_0_1 PARTITION OF concur_reindex_part_0 |
||||
FOR VALUES IN (1); |
||||
CREATE TABLE concur_reindex_part_0_2 PARTITION OF concur_reindex_part_0 |
||||
FOR VALUES IN (2); |
||||
-- This partitioned table will have no partitions. |
||||
CREATE TABLE concur_reindex_part_10 PARTITION OF concur_reindex_part |
||||
FOR VALUES FROM (10) TO (20) PARTITION BY list (c2); |
||||
-- Create some partitioned indexes |
||||
CREATE INDEX concur_reindex_part_index ON ONLY concur_reindex_part (c1); |
||||
CREATE INDEX concur_reindex_part_index_0 ON ONLY concur_reindex_part_0 (c1); |
||||
ALTER INDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_0; |
||||
-- This partitioned index will have no partitions. |
||||
CREATE INDEX concur_reindex_part_index_10 ON ONLY concur_reindex_part_10 (c1); |
||||
ALTER INDEX concur_reindex_part_index ATTACH PARTITION concur_reindex_part_index_10; |
||||
CREATE INDEX concur_reindex_part_index_0_1 ON ONLY concur_reindex_part_0_1 (c1); |
||||
ALTER INDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_1; |
||||
CREATE INDEX concur_reindex_part_index_0_2 ON ONLY concur_reindex_part_0_2 (c1); |
||||
ALTER INDEX concur_reindex_part_index_0 ATTACH PARTITION concur_reindex_part_index_0_2; |
||||
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index') |
||||
ORDER BY relid, level; |
||||
relid | parentrelid | level |
||||
-------------------------------+-----------------------------+------- |
||||
concur_reindex_part_index | | 0 |
||||
concur_reindex_part_index_0 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_10 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2 |
||||
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2 |
||||
(5 rows) |
||||
|
||||
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index') |
||||
ORDER BY relid, level; |
||||
relid | parentrelid | level |
||||
-------------------------------+-----------------------------+------- |
||||
concur_reindex_part_index | | 0 |
||||
concur_reindex_part_index_0 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_10 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2 |
||||
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2 |
||||
(5 rows) |
||||
|
||||
SELECT relid, parentrelid, level FROM pg_partition_tree('concur_reindex_part_index') |
||||
ORDER BY relid, level; |
||||
relid | parentrelid | level |
||||
-------------------------------+-----------------------------+------- |
||||
concur_reindex_part_index | | 0 |
||||
concur_reindex_part_index_0 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_10 | concur_reindex_part_index | 1 |
||||
concur_reindex_part_index_0_1 | concur_reindex_part_index_0 | 2 |
||||
concur_reindex_part_index_0_2 | concur_reindex_part_index_0 | 2 |
||||
(5 rows) |
||||
|
||||
DROP TABLE concur_reindex_part; |
||||
DROP EXTENSION pg_tde; |
||||
RESET default_table_access_method; |
@ -0,0 +1,125 @@ |
||||
-- We test cache so AM doesn't matter |
||||
-- Just checking there are no mem debug WARNINGs during the cache population |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
do $$ |
||||
DECLARE idx integer; |
||||
begin |
||||
for idx in 0..700 loop |
||||
EXECUTE format('CREATE TABLE t%s (c1 int) USING tde_heap_basic', idx); |
||||
end loop; |
||||
end; $$; |
||||
DROP EXTENSION pg_tde cascade; |
||||
NOTICE: drop cascades to 701 other objects |
||||
DETAIL: drop cascades to table t0 |
||||
drop cascades to table t1 |
||||
drop cascades to table t2 |
||||
drop cascades to table t3 |
||||
drop cascades to table t4 |
||||
drop cascades to table t5 |
||||
drop cascades to table t6 |
||||
drop cascades to table t7 |
||||
drop cascades to table t8 |
||||
drop cascades to table t9 |
||||
drop cascades to table t10 |
||||
drop cascades to table t11 |
||||
drop cascades to table t12 |
||||
drop cascades to table t13 |
||||
drop cascades to table t14 |
||||
drop cascades to table t15 |
||||
drop cascades to table t16 |
||||
drop cascades to table t17 |
||||
drop cascades to table t18 |
||||
drop cascades to table t19 |
||||
drop cascades to table t20 |
||||
drop cascades to table t21 |
||||
drop cascades to table t22 |
||||
drop cascades to table t23 |
||||
drop cascades to table t24 |
||||
drop cascades to table t25 |
||||
drop cascades to table t26 |
||||
drop cascades to table t27 |
||||
drop cascades to table t28 |
||||
drop cascades to table t29 |
||||
drop cascades to table t30 |
||||
drop cascades to table t31 |
||||
drop cascades to table t32 |
||||
drop cascades to table t33 |
||||
drop cascades to table t34 |
||||
drop cascades to table t35 |
||||
drop cascades to table t36 |
||||
drop cascades to table t37 |
||||
drop cascades to table t38 |
||||
drop cascades to table t39 |
||||
drop cascades to table t40 |
||||
drop cascades to table t41 |
||||
drop cascades to table t42 |
||||
drop cascades to table t43 |
||||
drop cascades to table t44 |
||||
drop cascades to table t45 |
||||
drop cascades to table t46 |
||||
drop cascades to table t47 |
||||
drop cascades to table t48 |
||||
drop cascades to table t49 |
||||
drop cascades to table t50 |
||||
drop cascades to table t51 |
||||
drop cascades to table t52 |
||||
drop cascades to table t53 |
||||
drop cascades to table t54 |
||||
drop cascades to table t55 |
||||
drop cascades to table t56 |
||||
drop cascades to table t57 |
||||
drop cascades to table t58 |
||||
drop cascades to table t59 |
||||
drop cascades to table t60 |
||||
drop cascades to table t61 |
||||
drop cascades to table t62 |
||||
drop cascades to table t63 |
||||
drop cascades to table t64 |
||||
drop cascades to table t65 |
||||
drop cascades to table t66 |
||||
drop cascades to table t67 |
||||
drop cascades to table t68 |
||||
drop cascades to table t69 |
||||
drop cascades to table t70 |
||||
drop cascades to table t71 |
||||
drop cascades to table t72 |
||||
drop cascades to table t73 |
||||
drop cascades to table t74 |
||||
drop cascades to table t75 |
||||
drop cascades to table t76 |
||||
drop cascades to table t77 |
||||
drop cascades to table t78 |
||||
drop cascades to table t79 |
||||
drop cascades to table t80 |
||||
drop cascades to table t81 |
||||
drop cascades to table t82 |
||||
drop cascades to table t83 |
||||
drop cascades to table t84 |
||||
drop cascades to table t85 |
||||
drop cascades to table t86 |
||||
drop cascades to table t87 |
||||
drop cascades to table t88 |
||||
drop cascades to table t89 |
||||
drop cascades to table t90 |
||||
drop cascades to table t91 |
||||
drop cascades to table t92 |
||||
drop cascades to table t93 |
||||
drop cascades to table t94 |
||||
drop cascades to table t95 |
||||
drop cascades to table t96 |
||||
drop cascades to table t97 |
||||
drop cascades to table t98 |
||||
drop cascades to table t99 |
||||
and 601 other objects (see server log for list) |
@ -0,0 +1,91 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/change_access_method.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE country_table ( |
||||
country_id serial primary key, |
||||
country_name text unique not null, |
||||
continent text not null |
||||
) using :tde_am; |
||||
|
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('Japan', 'Asia'), |
||||
('UK', 'Europe'), |
||||
('USA', 'North America'); |
||||
SELECT * FROM country_table; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
(3 rows) |
||||
|
||||
SELECT pg_tde_is_encrypted('country_table'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
-- Try changing the encrypted table to an unencrypted table |
||||
ALTER TABLE country_table SET access method heap; |
||||
-- Insert some more data |
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('France', 'Europe'), |
||||
('Germany', 'Europe'), |
||||
('Canada', 'North America'); |
||||
SELECT * FROM country_table; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
4 | France | Europe |
||||
5 | Germany | Europe |
||||
6 | Canada | North America |
||||
(6 rows) |
||||
|
||||
SELECT pg_tde_is_encrypted('country_table'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
f |
||||
(1 row) |
||||
|
||||
-- Change it back to encrypted |
||||
ALTER TABLE country_table SET access method :tde_am; |
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('China', 'Asia'), |
||||
('Brazil', 'South America'), |
||||
('Australia', 'Oceania'); |
||||
SELECT * FROM country_table; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
4 | France | Europe |
||||
5 | Germany | Europe |
||||
6 | Canada | North America |
||||
7 | China | Asia |
||||
8 | Brazil | South America |
||||
9 | Australia | Oceania |
||||
(9 rows) |
||||
|
||||
SELECT pg_tde_is_encrypted('country_table'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP TABLE country_table; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,91 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/change_access_method.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE country_table ( |
||||
country_id serial primary key, |
||||
country_name text unique not null, |
||||
continent text not null |
||||
) using :tde_am; |
||||
|
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('Japan', 'Asia'), |
||||
('UK', 'Europe'), |
||||
('USA', 'North America'); |
||||
SELECT * FROM country_table; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
(3 rows) |
||||
|
||||
SELECT pg_tde_is_encrypted('country_table'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
-- Try changing the encrypted table to an unencrypted table |
||||
ALTER TABLE country_table SET access method heap; |
||||
-- Insert some more data |
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('France', 'Europe'), |
||||
('Germany', 'Europe'), |
||||
('Canada', 'North America'); |
||||
SELECT * FROM country_table; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
4 | France | Europe |
||||
5 | Germany | Europe |
||||
6 | Canada | North America |
||||
(6 rows) |
||||
|
||||
SELECT pg_tde_is_encrypted('country_table'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
f |
||||
(1 row) |
||||
|
||||
-- Change it back to encrypted |
||||
ALTER TABLE country_table SET access method :tde_am; |
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('China', 'Asia'), |
||||
('Brazil', 'South America'), |
||||
('Australia', 'Oceania'); |
||||
SELECT * FROM country_table; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
4 | France | Europe |
||||
5 | Germany | Europe |
||||
6 | Canada | North America |
||||
7 | China | Asia |
||||
8 | Brazil | South America |
||||
9 | Australia | Oceania |
||||
(9 rows) |
||||
|
||||
SELECT pg_tde_is_encrypted('country_table'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP TABLE country_table; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,36 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/keyprovider_dependency.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('mk-file','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_add_key_provider_file('free-file','/tmp/pg_tde_test_keyring_2.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
2 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_add_key_provider_vault_v2('V2-vault','vault-token','percona.com/vault-v2/percona','/mount/dev','ca-cert-auth'); |
||||
pg_tde_add_key_provider_vault_v2 |
||||
---------------------------------- |
||||
3 |
||||
(1 row) |
||||
|
||||
SELECT * FROM pg_tde_list_all_key_providers(); |
||||
id | provider_name | provider_type | options |
||||
----+---------------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------- |
||||
1 | mk-file | file | {"type" : "file", "path" : "/tmp/pg_tde_test_keyring.per"} |
||||
2 | free-file | file | {"type" : "file", "path" : "/tmp/pg_tde_test_keyring_2.per"} |
||||
3 | V2-vault | vault-v2 | {"type" : "vault-v2", "url" : "percona.com/vault-v2/percona", "token" : "vault-token", "mountPath" : "/mount/dev", "caPath" : "ca-cert-auth"} |
||||
(3 rows) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','mk-file'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,36 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/keyprovider_dependency.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('mk-file','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_add_key_provider_file('free-file','/tmp/pg_tde_test_keyring_2.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
2 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_add_key_provider_vault_v2('V2-vault','vault-token','percona.com/vault-v2/percona','/mount/dev','ca-cert-auth'); |
||||
pg_tde_add_key_provider_vault_v2 |
||||
---------------------------------- |
||||
3 |
||||
(1 row) |
||||
|
||||
SELECT * FROM pg_tde_list_all_key_providers(); |
||||
id | provider_name | provider_type | options |
||||
----+---------------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------- |
||||
1 | mk-file | file | {"type" : "file", "path" : "/tmp/pg_tde_test_keyring.per"} |
||||
2 | free-file | file | {"type" : "file", "path" : "/tmp/pg_tde_test_keyring_2.per"} |
||||
3 | V2-vault | vault-v2 | {"type" : "vault-v2", "url" : "percona.com/vault-v2/percona", "token" : "vault-token", "mountPath" : "/mount/dev", "caPath" : "ca-cert-auth"} |
||||
(3 rows) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','mk-file'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,33 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/kmip_test.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_kmip('kmip-prov','127.0.0.1', 5696, '/tmp/server_certificate.pem', '/tmp/client_key_jane_doe.pem'); |
||||
pg_tde_add_key_provider_kmip |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('kmip-principal-key','kmip-prov'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE test_enc( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
INSERT INTO test_enc (k) VALUES (1); |
||||
INSERT INTO test_enc (k) VALUES (2); |
||||
INSERT INTO test_enc (k) VALUES (3); |
||||
SELECT * from test_enc; |
||||
id | k |
||||
----+--- |
||||
1 | 1 |
||||
2 | 2 |
||||
3 | 3 |
||||
(3 rows) |
||||
|
||||
DROP TABLE test_enc; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,33 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/kmip_test.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_kmip('kmip-prov','127.0.0.1', 5696, '/tmp/server_certificate.pem', '/tmp/client_key_jane_doe.pem'); |
||||
pg_tde_add_key_provider_kmip |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('kmip-principal-key','kmip-prov'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE test_enc( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
INSERT INTO test_enc (k) VALUES (1); |
||||
INSERT INTO test_enc (k) VALUES (2); |
||||
INSERT INTO test_enc (k) VALUES (3); |
||||
SELECT * from test_enc; |
||||
id | k |
||||
----+--- |
||||
1 | 1 |
||||
2 | 2 |
||||
3 | 3 |
||||
(3 rows) |
||||
|
||||
DROP TABLE test_enc; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,97 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/merge_join.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
\getenv abs_srcdir PG_ABS_SRCDIR |
||||
CREATE TABLE tenk1 ( |
||||
unique1 int4, |
||||
unique2 int4, |
||||
two int4, |
||||
four int4, |
||||
ten int4, |
||||
twenty int4, |
||||
hundred int4, |
||||
thousand int4, |
||||
twothousand int4, |
||||
fivethous int4, |
||||
tenthous int4, |
||||
odd int4, |
||||
even int4, |
||||
stringu1 name, |
||||
stringu2 name, |
||||
string4 name |
||||
) using :tde_am; |
||||
\set filename :abs_srcdir '/data/tenk.data' |
||||
COPY tenk1 FROM :'filename'; |
||||
VACUUM ANALYZE tenk1; |
||||
CREATE INDEX tenk1_unique1 ON tenk1 USING btree(unique1 int4_ops); |
||||
CREATE INDEX tenk1_unique2 ON tenk1 USING btree(unique2 int4_ops); |
||||
CREATE INDEX tenk1_hundred ON tenk1 USING btree(hundred int4_ops); |
||||
CREATE INDEX tenk1_thous_tenthous ON tenk1 (thousand, tenthous); |
||||
-- |
||||
-- regression test: check a case where join_clause_is_movable_into() |
||||
-- used to give an imprecise result, causing an assertion failure |
||||
-- |
||||
SELECT count(*) |
||||
FROM |
||||
(SELECT t3.tenthous as x1, coalesce(t1.stringu1, t2.stringu1) as x2 |
||||
FROM tenk1 t1 |
||||
LEFT JOIN tenk1 t2 on t1.unique1 = t2.unique1 |
||||
JOIN tenk1 t3 on t1.unique2 = t3.unique2) ss, |
||||
tenk1 t4, |
||||
tenk1 t5 |
||||
WHERE t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1; |
||||
count |
||||
------- |
||||
1000 |
||||
(1 row) |
||||
|
||||
-- |
||||
-- check that we haven't screwed the data |
||||
-- |
||||
SELECT * |
||||
FROM |
||||
(SELECT t3.tenthous as x1, coalesce(t1.stringu1, t2.stringu1) as x2 |
||||
FROM tenk1 t1 |
||||
LEFT JOIN tenk1 t2 on t1.unique1 = t2.unique1 |
||||
JOIN tenk1 t3 on t1.unique2 = t3.unique2) ss, |
||||
tenk1 t4, |
||||
tenk1 t5 |
||||
WHERE t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1 LIMIT 20 OFFSET 432; |
||||
x1 | x2 | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 |
||||
-----+--------+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- |
||||
31 | FBAAAA | 31 | 4200 | 1 | 3 | 1 | 11 | 31 | 31 | 31 | 31 | 31 | 62 | 63 | FBAAAA | OFGAAA | AAAAxx | 31 | 4200 | 1 | 3 | 1 | 11 | 31 | 31 | 31 | 31 | 31 | 62 | 63 | FBAAAA | OFGAAA | AAAAxx |
||||
501 | HTAAAA | 501 | 4203 | 1 | 1 | 1 | 1 | 1 | 501 | 501 | 501 | 501 | 2 | 3 | HTAAAA | RFGAAA | VVVVxx | 501 | 4203 | 1 | 1 | 1 | 1 | 1 | 501 | 501 | 501 | 501 | 2 | 3 | HTAAAA | RFGAAA | VVVVxx |
||||
111 | HEAAAA | 111 | 4217 | 1 | 3 | 1 | 11 | 11 | 111 | 111 | 111 | 111 | 22 | 23 | HEAAAA | FGGAAA | HHHHxx | 111 | 4217 | 1 | 3 | 1 | 11 | 11 | 111 | 111 | 111 | 111 | 22 | 23 | HEAAAA | FGGAAA | HHHHxx |
||||
98 | UDAAAA | 98 | 4226 | 0 | 2 | 8 | 18 | 98 | 98 | 98 | 98 | 98 | 196 | 197 | UDAAAA | OGGAAA | OOOOxx | 98 | 4226 | 0 | 2 | 8 | 18 | 98 | 98 | 98 | 98 | 98 | 196 | 197 | UDAAAA | OGGAAA | OOOOxx |
||||
689 | NAAAAA | 689 | 4228 | 1 | 1 | 9 | 9 | 89 | 689 | 689 | 689 | 689 | 178 | 179 | NAAAAA | QGGAAA | AAAAxx | 689 | 4228 | 1 | 1 | 9 | 9 | 89 | 689 | 689 | 689 | 689 | 178 | 179 | NAAAAA | QGGAAA | AAAAxx |
||||
391 | BPAAAA | 391 | 4234 | 1 | 3 | 1 | 11 | 91 | 391 | 391 | 391 | 391 | 182 | 183 | BPAAAA | WGGAAA | OOOOxx | 391 | 4234 | 1 | 3 | 1 | 11 | 91 | 391 | 391 | 391 | 391 | 182 | 183 | BPAAAA | WGGAAA | OOOOxx |
||||
93 | PDAAAA | 93 | 4238 | 1 | 1 | 3 | 13 | 93 | 93 | 93 | 93 | 93 | 186 | 187 | PDAAAA | AHGAAA | OOOOxx | 93 | 4238 | 1 | 1 | 3 | 13 | 93 | 93 | 93 | 93 | 93 | 186 | 187 | PDAAAA | AHGAAA | OOOOxx |
||||
618 | UXAAAA | 618 | 4252 | 0 | 2 | 8 | 18 | 18 | 618 | 618 | 618 | 618 | 36 | 37 | UXAAAA | OHGAAA | AAAAxx | 618 | 4252 | 0 | 2 | 8 | 18 | 18 | 618 | 618 | 618 | 618 | 36 | 37 | UXAAAA | OHGAAA | AAAAxx |
||||
328 | QMAAAA | 328 | 4255 | 0 | 0 | 8 | 8 | 28 | 328 | 328 | 328 | 328 | 56 | 57 | QMAAAA | RHGAAA | VVVVxx | 328 | 4255 | 0 | 0 | 8 | 8 | 28 | 328 | 328 | 328 | 328 | 56 | 57 | QMAAAA | RHGAAA | VVVVxx |
||||
943 | HKAAAA | 943 | 4265 | 1 | 3 | 3 | 3 | 43 | 943 | 943 | 943 | 943 | 86 | 87 | HKAAAA | BIGAAA | HHHHxx | 943 | 4265 | 1 | 3 | 3 | 3 | 43 | 943 | 943 | 943 | 943 | 86 | 87 | HKAAAA | BIGAAA | HHHHxx |
||||
775 | VDAAAA | 775 | 4266 | 1 | 3 | 5 | 15 | 75 | 775 | 775 | 775 | 775 | 150 | 151 | VDAAAA | CIGAAA | OOOOxx | 775 | 4266 | 1 | 3 | 5 | 15 | 75 | 775 | 775 | 775 | 775 | 150 | 151 | VDAAAA | CIGAAA | OOOOxx |
||||
491 | XSAAAA | 491 | 4277 | 1 | 3 | 1 | 11 | 91 | 491 | 491 | 491 | 491 | 182 | 183 | XSAAAA | NIGAAA | HHHHxx | 491 | 4277 | 1 | 3 | 1 | 11 | 91 | 491 | 491 | 491 | 491 | 182 | 183 | XSAAAA | NIGAAA | HHHHxx |
||||
212 | EIAAAA | 212 | 4280 | 0 | 0 | 2 | 12 | 12 | 212 | 212 | 212 | 212 | 24 | 25 | EIAAAA | QIGAAA | AAAAxx | 212 | 4280 | 0 | 0 | 2 | 12 | 12 | 212 | 212 | 212 | 212 | 24 | 25 | EIAAAA | QIGAAA | AAAAxx |
||||
340 | CNAAAA | 340 | 4293 | 0 | 0 | 0 | 0 | 40 | 340 | 340 | 340 | 340 | 80 | 81 | CNAAAA | DJGAAA | HHHHxx | 340 | 4293 | 0 | 0 | 0 | 0 | 40 | 340 | 340 | 340 | 340 | 80 | 81 | CNAAAA | DJGAAA | HHHHxx |
||||
445 | DRAAAA | 445 | 4316 | 1 | 1 | 5 | 5 | 45 | 445 | 445 | 445 | 445 | 90 | 91 | DRAAAA | AKGAAA | AAAAxx | 445 | 4316 | 1 | 1 | 5 | 5 | 45 | 445 | 445 | 445 | 445 | 90 | 91 | DRAAAA | AKGAAA | AAAAxx |
||||
472 | ESAAAA | 472 | 4321 | 0 | 0 | 2 | 12 | 72 | 472 | 472 | 472 | 472 | 144 | 145 | ESAAAA | FKGAAA | HHHHxx | 472 | 4321 | 0 | 0 | 2 | 12 | 72 | 472 | 472 | 472 | 472 | 144 | 145 | ESAAAA | FKGAAA | HHHHxx |
||||
760 | GDAAAA | 760 | 4329 | 0 | 0 | 0 | 0 | 60 | 760 | 760 | 760 | 760 | 120 | 121 | GDAAAA | NKGAAA | HHHHxx | 760 | 4329 | 0 | 0 | 0 | 0 | 60 | 760 | 760 | 760 | 760 | 120 | 121 | GDAAAA | NKGAAA | HHHHxx |
||||
14 | OAAAAA | 14 | 4341 | 0 | 2 | 4 | 14 | 14 | 14 | 14 | 14 | 14 | 28 | 29 | OAAAAA | ZKGAAA | HHHHxx | 14 | 4341 | 0 | 2 | 4 | 14 | 14 | 14 | 14 | 14 | 14 | 28 | 29 | OAAAAA | ZKGAAA | HHHHxx |
||||
65 | NCAAAA | 65 | 4348 | 1 | 1 | 5 | 5 | 65 | 65 | 65 | 65 | 65 | 130 | 131 | NCAAAA | GLGAAA | AAAAxx | 65 | 4348 | 1 | 1 | 5 | 5 | 65 | 65 | 65 | 65 | 65 | 130 | 131 | NCAAAA | GLGAAA | AAAAxx |
||||
459 | RRAAAA | 459 | 4350 | 1 | 3 | 9 | 19 | 59 | 459 | 459 | 459 | 459 | 118 | 119 | RRAAAA | ILGAAA | OOOOxx | 459 | 4350 | 1 | 3 | 9 | 19 | 59 | 459 | 459 | 459 | 459 | 118 | 119 | RRAAAA | ILGAAA | OOOOxx |
||||
(20 rows) |
||||
|
||||
DROP TABLE tenk1; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,97 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/merge_join.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
\getenv abs_srcdir PG_ABS_SRCDIR |
||||
CREATE TABLE tenk1 ( |
||||
unique1 int4, |
||||
unique2 int4, |
||||
two int4, |
||||
four int4, |
||||
ten int4, |
||||
twenty int4, |
||||
hundred int4, |
||||
thousand int4, |
||||
twothousand int4, |
||||
fivethous int4, |
||||
tenthous int4, |
||||
odd int4, |
||||
even int4, |
||||
stringu1 name, |
||||
stringu2 name, |
||||
string4 name |
||||
) using :tde_am; |
||||
\set filename :abs_srcdir '/data/tenk.data' |
||||
COPY tenk1 FROM :'filename'; |
||||
VACUUM ANALYZE tenk1; |
||||
CREATE INDEX tenk1_unique1 ON tenk1 USING btree(unique1 int4_ops); |
||||
CREATE INDEX tenk1_unique2 ON tenk1 USING btree(unique2 int4_ops); |
||||
CREATE INDEX tenk1_hundred ON tenk1 USING btree(hundred int4_ops); |
||||
CREATE INDEX tenk1_thous_tenthous ON tenk1 (thousand, tenthous); |
||||
-- |
||||
-- regression test: check a case where join_clause_is_movable_into() |
||||
-- used to give an imprecise result, causing an assertion failure |
||||
-- |
||||
SELECT count(*) |
||||
FROM |
||||
(SELECT t3.tenthous as x1, coalesce(t1.stringu1, t2.stringu1) as x2 |
||||
FROM tenk1 t1 |
||||
LEFT JOIN tenk1 t2 on t1.unique1 = t2.unique1 |
||||
JOIN tenk1 t3 on t1.unique2 = t3.unique2) ss, |
||||
tenk1 t4, |
||||
tenk1 t5 |
||||
WHERE t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1; |
||||
count |
||||
------- |
||||
1000 |
||||
(1 row) |
||||
|
||||
-- |
||||
-- check that we haven't screwed the data |
||||
-- |
||||
SELECT * |
||||
FROM |
||||
(SELECT t3.tenthous as x1, coalesce(t1.stringu1, t2.stringu1) as x2 |
||||
FROM tenk1 t1 |
||||
LEFT JOIN tenk1 t2 on t1.unique1 = t2.unique1 |
||||
JOIN tenk1 t3 on t1.unique2 = t3.unique2) ss, |
||||
tenk1 t4, |
||||
tenk1 t5 |
||||
WHERE t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1 LIMIT 20 OFFSET 432; |
||||
x1 | x2 | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 |
||||
-----+--------+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- |
||||
31 | FBAAAA | 31 | 4200 | 1 | 3 | 1 | 11 | 31 | 31 | 31 | 31 | 31 | 62 | 63 | FBAAAA | OFGAAA | AAAAxx | 31 | 4200 | 1 | 3 | 1 | 11 | 31 | 31 | 31 | 31 | 31 | 62 | 63 | FBAAAA | OFGAAA | AAAAxx |
||||
501 | HTAAAA | 501 | 4203 | 1 | 1 | 1 | 1 | 1 | 501 | 501 | 501 | 501 | 2 | 3 | HTAAAA | RFGAAA | VVVVxx | 501 | 4203 | 1 | 1 | 1 | 1 | 1 | 501 | 501 | 501 | 501 | 2 | 3 | HTAAAA | RFGAAA | VVVVxx |
||||
111 | HEAAAA | 111 | 4217 | 1 | 3 | 1 | 11 | 11 | 111 | 111 | 111 | 111 | 22 | 23 | HEAAAA | FGGAAA | HHHHxx | 111 | 4217 | 1 | 3 | 1 | 11 | 11 | 111 | 111 | 111 | 111 | 22 | 23 | HEAAAA | FGGAAA | HHHHxx |
||||
98 | UDAAAA | 98 | 4226 | 0 | 2 | 8 | 18 | 98 | 98 | 98 | 98 | 98 | 196 | 197 | UDAAAA | OGGAAA | OOOOxx | 98 | 4226 | 0 | 2 | 8 | 18 | 98 | 98 | 98 | 98 | 98 | 196 | 197 | UDAAAA | OGGAAA | OOOOxx |
||||
689 | NAAAAA | 689 | 4228 | 1 | 1 | 9 | 9 | 89 | 689 | 689 | 689 | 689 | 178 | 179 | NAAAAA | QGGAAA | AAAAxx | 689 | 4228 | 1 | 1 | 9 | 9 | 89 | 689 | 689 | 689 | 689 | 178 | 179 | NAAAAA | QGGAAA | AAAAxx |
||||
391 | BPAAAA | 391 | 4234 | 1 | 3 | 1 | 11 | 91 | 391 | 391 | 391 | 391 | 182 | 183 | BPAAAA | WGGAAA | OOOOxx | 391 | 4234 | 1 | 3 | 1 | 11 | 91 | 391 | 391 | 391 | 391 | 182 | 183 | BPAAAA | WGGAAA | OOOOxx |
||||
93 | PDAAAA | 93 | 4238 | 1 | 1 | 3 | 13 | 93 | 93 | 93 | 93 | 93 | 186 | 187 | PDAAAA | AHGAAA | OOOOxx | 93 | 4238 | 1 | 1 | 3 | 13 | 93 | 93 | 93 | 93 | 93 | 186 | 187 | PDAAAA | AHGAAA | OOOOxx |
||||
618 | UXAAAA | 618 | 4252 | 0 | 2 | 8 | 18 | 18 | 618 | 618 | 618 | 618 | 36 | 37 | UXAAAA | OHGAAA | AAAAxx | 618 | 4252 | 0 | 2 | 8 | 18 | 18 | 618 | 618 | 618 | 618 | 36 | 37 | UXAAAA | OHGAAA | AAAAxx |
||||
328 | QMAAAA | 328 | 4255 | 0 | 0 | 8 | 8 | 28 | 328 | 328 | 328 | 328 | 56 | 57 | QMAAAA | RHGAAA | VVVVxx | 328 | 4255 | 0 | 0 | 8 | 8 | 28 | 328 | 328 | 328 | 328 | 56 | 57 | QMAAAA | RHGAAA | VVVVxx |
||||
943 | HKAAAA | 943 | 4265 | 1 | 3 | 3 | 3 | 43 | 943 | 943 | 943 | 943 | 86 | 87 | HKAAAA | BIGAAA | HHHHxx | 943 | 4265 | 1 | 3 | 3 | 3 | 43 | 943 | 943 | 943 | 943 | 86 | 87 | HKAAAA | BIGAAA | HHHHxx |
||||
775 | VDAAAA | 775 | 4266 | 1 | 3 | 5 | 15 | 75 | 775 | 775 | 775 | 775 | 150 | 151 | VDAAAA | CIGAAA | OOOOxx | 775 | 4266 | 1 | 3 | 5 | 15 | 75 | 775 | 775 | 775 | 775 | 150 | 151 | VDAAAA | CIGAAA | OOOOxx |
||||
491 | XSAAAA | 491 | 4277 | 1 | 3 | 1 | 11 | 91 | 491 | 491 | 491 | 491 | 182 | 183 | XSAAAA | NIGAAA | HHHHxx | 491 | 4277 | 1 | 3 | 1 | 11 | 91 | 491 | 491 | 491 | 491 | 182 | 183 | XSAAAA | NIGAAA | HHHHxx |
||||
212 | EIAAAA | 212 | 4280 | 0 | 0 | 2 | 12 | 12 | 212 | 212 | 212 | 212 | 24 | 25 | EIAAAA | QIGAAA | AAAAxx | 212 | 4280 | 0 | 0 | 2 | 12 | 12 | 212 | 212 | 212 | 212 | 24 | 25 | EIAAAA | QIGAAA | AAAAxx |
||||
340 | CNAAAA | 340 | 4293 | 0 | 0 | 0 | 0 | 40 | 340 | 340 | 340 | 340 | 80 | 81 | CNAAAA | DJGAAA | HHHHxx | 340 | 4293 | 0 | 0 | 0 | 0 | 40 | 340 | 340 | 340 | 340 | 80 | 81 | CNAAAA | DJGAAA | HHHHxx |
||||
445 | DRAAAA | 445 | 4316 | 1 | 1 | 5 | 5 | 45 | 445 | 445 | 445 | 445 | 90 | 91 | DRAAAA | AKGAAA | AAAAxx | 445 | 4316 | 1 | 1 | 5 | 5 | 45 | 445 | 445 | 445 | 445 | 90 | 91 | DRAAAA | AKGAAA | AAAAxx |
||||
472 | ESAAAA | 472 | 4321 | 0 | 0 | 2 | 12 | 72 | 472 | 472 | 472 | 472 | 144 | 145 | ESAAAA | FKGAAA | HHHHxx | 472 | 4321 | 0 | 0 | 2 | 12 | 72 | 472 | 472 | 472 | 472 | 144 | 145 | ESAAAA | FKGAAA | HHHHxx |
||||
760 | GDAAAA | 760 | 4329 | 0 | 0 | 0 | 0 | 60 | 760 | 760 | 760 | 760 | 120 | 121 | GDAAAA | NKGAAA | HHHHxx | 760 | 4329 | 0 | 0 | 0 | 0 | 60 | 760 | 760 | 760 | 760 | 120 | 121 | GDAAAA | NKGAAA | HHHHxx |
||||
14 | OAAAAA | 14 | 4341 | 0 | 2 | 4 | 14 | 14 | 14 | 14 | 14 | 14 | 28 | 29 | OAAAAA | ZKGAAA | HHHHxx | 14 | 4341 | 0 | 2 | 4 | 14 | 14 | 14 | 14 | 14 | 14 | 28 | 29 | OAAAAA | ZKGAAA | HHHHxx |
||||
65 | NCAAAA | 65 | 4348 | 1 | 1 | 5 | 5 | 65 | 65 | 65 | 65 | 65 | 130 | 131 | NCAAAA | GLGAAA | AAAAxx | 65 | 4348 | 1 | 1 | 5 | 5 | 65 | 65 | 65 | 65 | 65 | 130 | 131 | NCAAAA | GLGAAA | AAAAxx |
||||
459 | RRAAAA | 459 | 4350 | 1 | 3 | 9 | 19 | 59 | 459 | 459 | 459 | 459 | 118 | 119 | RRAAAA | ILGAAA | OOOOxx | 459 | 4350 | 1 | 3 | 9 | 19 | 59 | 459 | 459 | 459 | 459 | 118 | 119 | RRAAAA | ILGAAA | OOOOxx |
||||
(20 rows) |
||||
|
||||
DROP TABLE tenk1; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,61 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/move_large_tuples.inc |
||||
-- test pg_tde_move_encrypted_data() |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE sbtest2( |
||||
id SERIAL, |
||||
k TEXT STORAGE PLAIN, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
INSERT INTO sbtest2(k) VALUES(repeat('a', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('b', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('c', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('d', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('e', 2500)); |
||||
DELETE FROM sbtest2 WHERE id IN (2,3,4); |
||||
VACUUM sbtest2; |
||||
SELECT * FROM sbtest2; |
||||
id | k |
||||
----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
||||
1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
||||
5 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee |
||||
(2 rows) |
||||
|
||||
INSERT INTO sbtest2(k) VALUES(repeat('b', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('c', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('d', 2500)); |
||||
DELETE FROM sbtest2 WHERE id IN (7); |
||||
VACUUM sbtest2; |
||||
SELECT * FROM sbtest2; |
||||
id | k |
||||
----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
||||
1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
||||
6 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
||||
8 | dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd |
||||
5 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee |
||||
(4 rows) |
||||
|
||||
VACUUM FULL sbtest2; |
||||
SELECT * FROM sbtest2; |
||||
id | k |
||||
----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
||||
1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
||||
6 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
||||
8 | dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd |
||||
5 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee |
||||
(4 rows) |
||||
|
||||
DROP TABLE sbtest2; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,61 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/move_large_tuples.inc |
||||
-- test pg_tde_move_encrypted_data() |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE sbtest2( |
||||
id SERIAL, |
||||
k TEXT STORAGE PLAIN, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
INSERT INTO sbtest2(k) VALUES(repeat('a', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('b', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('c', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('d', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('e', 2500)); |
||||
DELETE FROM sbtest2 WHERE id IN (2,3,4); |
||||
VACUUM sbtest2; |
||||
SELECT * FROM sbtest2; |
||||
id | k |
||||
----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
||||
1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
||||
5 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee |
||||
(2 rows) |
||||
|
||||
INSERT INTO sbtest2(k) VALUES(repeat('b', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('c', 2500)); |
||||
INSERT INTO sbtest2(k) VALUES(repeat('d', 2500)); |
||||
DELETE FROM sbtest2 WHERE id IN (7); |
||||
VACUUM sbtest2; |
||||
SELECT * FROM sbtest2; |
||||
id | k |
||||
----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
||||
1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
||||
6 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
||||
8 | dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd |
||||
5 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee |
||||
(4 rows) |
||||
|
||||
VACUUM FULL sbtest2; |
||||
SELECT * FROM sbtest2; |
||||
id | k |
||||
----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
||||
1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
||||
6 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
||||
8 | dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd |
||||
5 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee |
||||
(4 rows) |
||||
|
||||
DROP TABLE sbtest2; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,105 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/multi_insert.inc |
||||
-- trigger multi_insert path |
||||
-- |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE albums ( |
||||
album_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, |
||||
artist_id INTEGER, |
||||
title TEXT NOT NULL, |
||||
released DATE NOT NULL |
||||
) USING :tde_am; |
||||
COPY albums FROM stdin CSV HEADER; |
||||
SELECT * FROM albums; |
||||
album_id | artist_id | title | released |
||||
----------+-----------+--------------------+------------ |
||||
1 | 1 | Mirror | 06-24-2009 |
||||
2 | 2 | Pretzel Logic | 02-20-1974 |
||||
3 | 3 | Under Construction | 11-12-2002 |
||||
4 | 4 | Return to Wherever | 07-11-2019 |
||||
5 | 5 | The Nightfly | 10-01-1982 |
||||
6 | 6 | It's Alive | 10-15-2013 |
||||
7 | 7 | Pure Ella | 02-15-1994 |
||||
(7 rows) |
||||
|
||||
SELECT * FROM albums where album_id > 5; |
||||
album_id | artist_id | title | released |
||||
----------+-----------+------------+------------ |
||||
6 | 6 | It's Alive | 10-15-2013 |
||||
7 | 7 | Pure Ella | 02-15-1994 |
||||
(2 rows) |
||||
|
||||
-- On replica: |
||||
-- SELECT * FROM albums; |
||||
-- album_id | artist_id | title | released |
||||
-- ----------+-----------+--------------------+------------ |
||||
-- 1 | 1 | Mirror | 2009-06-24 |
||||
-- 2 | 2 | Pretzel Logic | 1974-02-20 |
||||
-- 3 | 3 | Under Construction | 2002-11-12 |
||||
-- 4 | 4 | Return to Wherever | 2019-07-11 |
||||
-- 5 | 5 | The Nightfly | 1982-10-01 |
||||
-- 6 | 6 | It's Alive | 2013-10-15 |
||||
-- 7 | 7 | Pure Ella | 1994-02-15 |
||||
-- (7 rows) |
||||
-- |
||||
-- SELECT * FROM albums where album_id > 5; |
||||
-- album_id | artist_id | title | released |
||||
-- ----------+-----------+------------+------------ |
||||
-- 6 | 6 | It's Alive | 2013-10-15 |
||||
-- 7 | 7 | Pure Ella | 1994-02-15 |
||||
-- (2 rows) |
||||
-- |
||||
DROP TABLE albums; |
||||
-- multi_insert2 |
||||
-- more data to take multiple pages |
||||
CREATE TABLE Towns ( |
||||
id SERIAL UNIQUE NOT NULL, |
||||
code VARCHAR(10) NOT NULL, |
||||
article TEXT, |
||||
name TEXT NOT NULL, |
||||
department VARCHAR(4) NOT NULL, |
||||
UNIQUE (code, department) |
||||
) USING :tde_am; |
||||
COPY towns (id, code, article, name, department) FROM stdin; |
||||
SELECT count(*) FROM towns; |
||||
count |
||||
------- |
||||
1313 |
||||
(1 row) |
||||
|
||||
SELECT * FROM towns where id in (13, 666); |
||||
id | code | article | name | department |
||||
-----+------+-----------+----------------+------------ |
||||
13 | 014 | some_text | Arbent | 01 |
||||
666 | 252 | some_text | Cuissy-et-Geny | 02 |
||||
(2 rows) |
||||
|
||||
-- ON REPLICA |
||||
-- |
||||
-- select count(*) from towns; |
||||
-- count |
||||
-- ------- |
||||
-- 1313 |
||||
-- (1 row) |
||||
-- |
||||
-- select * from towns where id in (13, 666); |
||||
-- id | code | article | name | department |
||||
-- -----+------+-----------+----------------+------------ |
||||
-- 13 | 014 | some_text | Arbent | 01 |
||||
-- 666 | 252 | some_text | Cuissy-et-Geny | 02 |
||||
-- (2 rows) |
||||
-- |
||||
DROP TABLE towns; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,105 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/multi_insert.inc |
||||
-- trigger multi_insert path |
||||
-- |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE albums ( |
||||
album_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, |
||||
artist_id INTEGER, |
||||
title TEXT NOT NULL, |
||||
released DATE NOT NULL |
||||
) USING :tde_am; |
||||
COPY albums FROM stdin CSV HEADER; |
||||
SELECT * FROM albums; |
||||
album_id | artist_id | title | released |
||||
----------+-----------+--------------------+------------ |
||||
1 | 1 | Mirror | 06-24-2009 |
||||
2 | 2 | Pretzel Logic | 02-20-1974 |
||||
3 | 3 | Under Construction | 11-12-2002 |
||||
4 | 4 | Return to Wherever | 07-11-2019 |
||||
5 | 5 | The Nightfly | 10-01-1982 |
||||
6 | 6 | It's Alive | 10-15-2013 |
||||
7 | 7 | Pure Ella | 02-15-1994 |
||||
(7 rows) |
||||
|
||||
SELECT * FROM albums where album_id > 5; |
||||
album_id | artist_id | title | released |
||||
----------+-----------+------------+------------ |
||||
6 | 6 | It's Alive | 10-15-2013 |
||||
7 | 7 | Pure Ella | 02-15-1994 |
||||
(2 rows) |
||||
|
||||
-- On replica: |
||||
-- SELECT * FROM albums; |
||||
-- album_id | artist_id | title | released |
||||
-- ----------+-----------+--------------------+------------ |
||||
-- 1 | 1 | Mirror | 2009-06-24 |
||||
-- 2 | 2 | Pretzel Logic | 1974-02-20 |
||||
-- 3 | 3 | Under Construction | 2002-11-12 |
||||
-- 4 | 4 | Return to Wherever | 2019-07-11 |
||||
-- 5 | 5 | The Nightfly | 1982-10-01 |
||||
-- 6 | 6 | It's Alive | 2013-10-15 |
||||
-- 7 | 7 | Pure Ella | 1994-02-15 |
||||
-- (7 rows) |
||||
-- |
||||
-- SELECT * FROM albums where album_id > 5; |
||||
-- album_id | artist_id | title | released |
||||
-- ----------+-----------+------------+------------ |
||||
-- 6 | 6 | It's Alive | 2013-10-15 |
||||
-- 7 | 7 | Pure Ella | 1994-02-15 |
||||
-- (2 rows) |
||||
-- |
||||
DROP TABLE albums; |
||||
-- multi_insert2 |
||||
-- more data to take multiple pages |
||||
CREATE TABLE Towns ( |
||||
id SERIAL UNIQUE NOT NULL, |
||||
code VARCHAR(10) NOT NULL, |
||||
article TEXT, |
||||
name TEXT NOT NULL, |
||||
department VARCHAR(4) NOT NULL, |
||||
UNIQUE (code, department) |
||||
) USING :tde_am; |
||||
COPY towns (id, code, article, name, department) FROM stdin; |
||||
SELECT count(*) FROM towns; |
||||
count |
||||
------- |
||||
1313 |
||||
(1 row) |
||||
|
||||
SELECT * FROM towns where id in (13, 666); |
||||
id | code | article | name | department |
||||
-----+------+-----------+----------------+------------ |
||||
13 | 014 | some_text | Arbent | 01 |
||||
666 | 252 | some_text | Cuissy-et-Geny | 02 |
||||
(2 rows) |
||||
|
||||
-- ON REPLICA |
||||
-- |
||||
-- select count(*) from towns; |
||||
-- count |
||||
-- ------- |
||||
-- 1313 |
||||
-- (1 row) |
||||
-- |
||||
-- select * from towns where id in (13, 666); |
||||
-- id | code | article | name | department |
||||
-- -----+------+-----------+----------------+------------ |
||||
-- 13 | 014 | some_text | Arbent | 01 |
||||
-- 666 | 252 | some_text | Cuissy-et-Geny | 02 |
||||
-- (2 rows) |
||||
-- |
||||
DROP TABLE towns; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,61 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/non_sorted_off_compact.inc |
||||
-- A test case for https://github.com/percona/pg_tde/pull/21 |
||||
-- |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP TABLE IF EXISTS sbtest1; |
||||
psql:sql/non_sorted_off_compact.inc:8: NOTICE: table "sbtest1" does not exist, skipping |
||||
CREATE TABLE sbtest1( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
INSERT INTO sbtest1(k) VALUES |
||||
(1), |
||||
(2), |
||||
(3), |
||||
(4), |
||||
(5), |
||||
(6), |
||||
(7), |
||||
(8), |
||||
(9), |
||||
(10); |
||||
DELETE FROM sbtest1 WHERE id IN (4,5,6); |
||||
VACUUM sbtest1; |
||||
INSERT INTO sbtest1(k) VALUES |
||||
(11), |
||||
(12), |
||||
(13); |
||||
-- Line pointers (lp) point to non-sorted offsets (lp_off): |
||||
-- CREATE EXTENSION pageinspect; |
||||
-- SELECT lp, lp_off, t_ctid FROM heap_page_items(get_raw_page('sbtest1', 0)); |
||||
-- lp | lp_off | t_ctid |
||||
-- ----+--------+-------- |
||||
-- 1 | 8160 | (0,1) |
||||
-- 2 | 8128 | (0,2) |
||||
-- 3 | 8096 | (0,3) |
||||
-- 4 | 7936 | (0,4) |
||||
-- 5 | 7904 | (0,5) |
||||
-- 6 | 7872 | (0,6) |
||||
-- 7 | 8064 | (0,7) |
||||
-- 8 | 8032 | (0,8) |
||||
-- 9 | 8000 | (0,9) |
||||
-- 10 | 7968 | (0,10) |
||||
---- Trigger comapction |
||||
delete from sbtest1 where id in (2); |
||||
VACUUM sbtest1; |
||||
DROP TABLE sbtest1; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,61 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/non_sorted_off_compact.inc |
||||
-- A test case for https://github.com/percona/pg_tde/pull/21 |
||||
-- |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP TABLE IF EXISTS sbtest1; |
||||
psql:sql/non_sorted_off_compact.inc:8: NOTICE: table "sbtest1" does not exist, skipping |
||||
CREATE TABLE sbtest1( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
INSERT INTO sbtest1(k) VALUES |
||||
(1), |
||||
(2), |
||||
(3), |
||||
(4), |
||||
(5), |
||||
(6), |
||||
(7), |
||||
(8), |
||||
(9), |
||||
(10); |
||||
DELETE FROM sbtest1 WHERE id IN (4,5,6); |
||||
VACUUM sbtest1; |
||||
INSERT INTO sbtest1(k) VALUES |
||||
(11), |
||||
(12), |
||||
(13); |
||||
-- Line pointers (lp) point to non-sorted offsets (lp_off): |
||||
-- CREATE EXTENSION pageinspect; |
||||
-- SELECT lp, lp_off, t_ctid FROM heap_page_items(get_raw_page('sbtest1', 0)); |
||||
-- lp | lp_off | t_ctid |
||||
-- ----+--------+-------- |
||||
-- 1 | 8160 | (0,1) |
||||
-- 2 | 8128 | (0,2) |
||||
-- 3 | 8096 | (0,3) |
||||
-- 4 | 7936 | (0,4) |
||||
-- 5 | 7904 | (0,5) |
||||
-- 6 | 7872 | (0,6) |
||||
-- 7 | 8064 | (0,7) |
||||
-- 8 | 8032 | (0,8) |
||||
-- 9 | 8000 | (0,9) |
||||
-- 10 | 7968 | (0,10) |
||||
---- Trigger comapction |
||||
delete from sbtest1 where id in (2); |
||||
VACUUM sbtest1; |
||||
DROP TABLE sbtest1; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,69 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/pg_tde_is_encrypted.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT * FROM pg_tde_principal_key_info(); |
||||
psql:sql/pg_tde_is_encrypted.inc:3: ERROR: Principal key does not exists for the database |
||||
HINT: Use set_principal_key interface to set the principal key |
||||
CONTEXT: SQL function "pg_tde_principal_key_info" statement 1 |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE test_enc( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
CREATE TABLE test_norm( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING heap; |
||||
SELECT amname FROM pg_class INNER JOIN pg_am ON pg_am.oid = pg_class.relam WHERE relname = 'test_enc'; |
||||
amname |
||||
---------- |
||||
tde_heap |
||||
(1 row) |
||||
|
||||
SELECT amname FROM pg_class INNER JOIN pg_am ON pg_am.oid = pg_class.relam WHERE relname = 'test_norm'; |
||||
amname |
||||
-------- |
||||
heap |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_is_encrypted('test_enc'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_is_encrypted('test_norm'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
f |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_is_encrypted('public.test_enc'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SELECT key_provider_id, key_provider_name, principal_key_name |
||||
FROM pg_tde_principal_key_info(); |
||||
key_provider_id | key_provider_name | principal_key_name |
||||
-----------------+-------------------+----------------------- |
||||
1 | file-vault | test-db-principal-key |
||||
(1 row) |
||||
|
||||
DROP TABLE test_enc; |
||||
DROP TABLE test_norm; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,69 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/pg_tde_is_encrypted.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT * FROM pg_tde_principal_key_info(); |
||||
psql:sql/pg_tde_is_encrypted.inc:3: ERROR: Principal key does not exists for the database |
||||
HINT: Use set_principal_key interface to set the principal key |
||||
CONTEXT: SQL function "pg_tde_principal_key_info" statement 1 |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE test_enc( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING :tde_am; |
||||
CREATE TABLE test_norm( |
||||
id SERIAL, |
||||
k INTEGER DEFAULT '0' NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) USING heap; |
||||
SELECT amname FROM pg_class INNER JOIN pg_am ON pg_am.oid = pg_class.relam WHERE relname = 'test_enc'; |
||||
amname |
||||
---------------- |
||||
tde_heap_basic |
||||
(1 row) |
||||
|
||||
SELECT amname FROM pg_class INNER JOIN pg_am ON pg_am.oid = pg_class.relam WHERE relname = 'test_norm'; |
||||
amname |
||||
-------- |
||||
heap |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_is_encrypted('test_enc'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_is_encrypted('test_norm'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
f |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_is_encrypted('public.test_enc'); |
||||
pg_tde_is_encrypted |
||||
--------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
SELECT key_provider_id, key_provider_name, principal_key_name |
||||
FROM pg_tde_principal_key_info(); |
||||
key_provider_id | key_provider_name | principal_key_name |
||||
-----------------+-------------------+----------------------- |
||||
1 | file-vault | test-db-principal-key |
||||
(1 row) |
||||
|
||||
DROP TABLE test_enc; |
||||
DROP TABLE test_norm; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,32 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/subtransaction.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
BEGIN; -- Nesting level 1 |
||||
SAVEPOINT sp; |
||||
CREATE TABLE foo(s TEXT); -- Nesting level 2 |
||||
RELEASE SAVEPOINT sp; |
||||
SAVEPOINT sp; |
||||
CREATE TABLE bar(s TEXT); -- Nesting level 2 |
||||
ROLLBACK TO sp; -- Rollback should not affect first subtransaction |
||||
COMMIT; |
||||
BEGIN; -- Nesting level 1 |
||||
SAVEPOINT sp; |
||||
DROP TABLE foo; -- Nesting level 2 |
||||
RELEASE SAVEPOINT sp; |
||||
SAVEPOINT sp; |
||||
CREATE TABLE bar(s TEXT); -- Nesting level 2 |
||||
ROLLBACK TO sp; -- Rollback should not affect first subtransaction |
||||
COMMIT; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,32 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/subtransaction.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
BEGIN; -- Nesting level 1 |
||||
SAVEPOINT sp; |
||||
CREATE TABLE foo(s TEXT); -- Nesting level 2 |
||||
RELEASE SAVEPOINT sp; |
||||
SAVEPOINT sp; |
||||
CREATE TABLE bar(s TEXT); -- Nesting level 2 |
||||
ROLLBACK TO sp; -- Rollback should not affect first subtransaction |
||||
COMMIT; |
||||
BEGIN; -- Nesting level 1 |
||||
SAVEPOINT sp; |
||||
DROP TABLE foo; -- Nesting level 2 |
||||
RELEASE SAVEPOINT sp; |
||||
SAVEPOINT sp; |
||||
CREATE TABLE bar(s TEXT); -- Nesting level 2 |
||||
ROLLBACK TO sp; -- Rollback should not affect first subtransaction |
||||
COMMIT; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,41 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/tablespace.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE test(num1 bigint, num2 double precision, t text) USING :tde_am; |
||||
INSERT INTO test(num1, num2, t) |
||||
SELECT round(random()*100), random(), 'text' |
||||
FROM generate_series(1, 10) s(i); |
||||
CREATE INDEX test_idx ON test(num1); |
||||
SET allow_in_place_tablespaces = true; |
||||
CREATE TABLESPACE test_tblspace LOCATION ''; |
||||
ALTER TABLE test SET TABLESPACE test_tblspace; |
||||
SELECT count(*) FROM test; |
||||
count |
||||
------- |
||||
10 |
||||
(1 row) |
||||
|
||||
ALTER TABLE test SET TABLESPACE pg_default; |
||||
REINDEX (TABLESPACE test_tblspace, CONCURRENTLY) TABLE test; |
||||
INSERT INTO test VALUES (110, 2); |
||||
SELECT * FROM test WHERE num1=110; |
||||
num1 | num2 | t |
||||
------+------+--- |
||||
110 | 2 | |
||||
(1 row) |
||||
|
||||
DROP TABLE test; |
||||
DROP TABLESPACE test_tblspace; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,41 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/tablespace.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE test(num1 bigint, num2 double precision, t text) USING :tde_am; |
||||
INSERT INTO test(num1, num2, t) |
||||
SELECT round(random()*100), random(), 'text' |
||||
FROM generate_series(1, 10) s(i); |
||||
CREATE INDEX test_idx ON test(num1); |
||||
SET allow_in_place_tablespaces = true; |
||||
CREATE TABLESPACE test_tblspace LOCATION ''; |
||||
ALTER TABLE test SET TABLESPACE test_tblspace; |
||||
SELECT count(*) FROM test; |
||||
count |
||||
------- |
||||
10 |
||||
(1 row) |
||||
|
||||
ALTER TABLE test SET TABLESPACE pg_default; |
||||
REINDEX (TABLESPACE test_tblspace, CONCURRENTLY) TABLE test; |
||||
INSERT INTO test VALUES (110, 2); |
||||
SELECT * FROM test WHERE num1=110; |
||||
num1 | num2 | t |
||||
------+------+--- |
||||
110 | 2 | |
||||
(1 row) |
||||
|
||||
DROP TABLE test; |
||||
DROP TABLESPACE test_tblspace; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,589 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/test_issue_153_fix.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SET datestyle TO 'iso, dmy'; |
||||
SELECT * FROM pg_tde_principal_key_info(); |
||||
psql:sql/test_issue_153_fix.inc:4: ERROR: Principal key does not exists for the database |
||||
HINT: Use set_principal_key interface to set the principal key |
||||
CONTEXT: SQL function "pg_tde_principal_key_info" statement 1 |
||||
SELECT pg_tde_add_key_provider_file('file-ring','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-ring'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
-- |
||||
-- Script that creates the 'sample' tde encrypted tables, views |
||||
-- functions, triggers, etc. |
||||
-- |
||||
-- Start new transaction - commit all or nothing |
||||
-- |
||||
BEGIN; |
||||
-- |
||||
-- Create and load tables used in the documentation examples. |
||||
-- |
||||
-- Create the 'dept' table |
||||
-- |
||||
CREATE TABLE dept ( |
||||
deptno NUMERIC(2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY, |
||||
dname VARCHAR(14) CONSTRAINT dept_dname_uq UNIQUE, |
||||
loc VARCHAR(13) |
||||
)using :tde_am; |
||||
-- |
||||
-- Create the 'emp' table |
||||
-- |
||||
CREATE TABLE emp ( |
||||
empno NUMERIC(4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, |
||||
ename VARCHAR(10), |
||||
job VARCHAR(9), |
||||
mgr NUMERIC(4), |
||||
hiredate DATE, |
||||
sal NUMERIC(7,2) CONSTRAINT emp_sal_ck CHECK (sal > 0), |
||||
comm NUMERIC(7,2), |
||||
deptno NUMERIC(2) CONSTRAINT emp_ref_dept_fk |
||||
REFERENCES dept(deptno) |
||||
)using :tde_am; |
||||
-- |
||||
-- Create the 'jobhist' table |
||||
-- |
||||
CREATE TABLE jobhist ( |
||||
empno NUMERIC(4) NOT NULL, |
||||
startdate TIMESTAMP(0) NOT NULL, |
||||
enddate TIMESTAMP(0), |
||||
job VARCHAR(9), |
||||
sal NUMERIC(7,2), |
||||
comm NUMERIC(7,2), |
||||
deptno NUMERIC(2), |
||||
chgdesc VARCHAR(80), |
||||
CONSTRAINT jobhist_pk PRIMARY KEY (empno, startdate), |
||||
CONSTRAINT jobhist_ref_emp_fk FOREIGN KEY (empno) |
||||
REFERENCES emp(empno) ON DELETE CASCADE, |
||||
CONSTRAINT jobhist_ref_dept_fk FOREIGN KEY (deptno) |
||||
REFERENCES dept (deptno) ON DELETE SET NULL, |
||||
CONSTRAINT jobhist_date_chk CHECK (startdate <= enddate) |
||||
)using :tde_am; |
||||
-- |
||||
-- Create the 'salesemp' view |
||||
-- |
||||
CREATE OR REPLACE VIEW salesemp AS |
||||
SELECT empno, ename, hiredate, sal, comm FROM emp WHERE job = 'SALESMAN'; |
||||
-- |
||||
-- Sequence to generate values for function 'new_empno'. |
||||
-- |
||||
CREATE SEQUENCE next_empno START WITH 8000 INCREMENT BY 1; |
||||
-- |
||||
-- Issue PUBLIC grants |
||||
-- |
||||
GRANT ALL ON emp TO PUBLIC; |
||||
GRANT ALL ON dept TO PUBLIC; |
||||
GRANT ALL ON jobhist TO PUBLIC; |
||||
GRANT ALL ON salesemp TO PUBLIC; |
||||
GRANT ALL ON next_empno TO PUBLIC; |
||||
-- |
||||
-- Load the 'dept' table |
||||
-- |
||||
INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK'); |
||||
INSERT INTO dept VALUES (20,'RESEARCH','DALLAS'); |
||||
INSERT INTO dept VALUES (30,'SALES','CHICAGO'); |
||||
INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON'); |
||||
-- |
||||
-- Load the 'emp' table |
||||
-- |
||||
INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,'17-DEC-80',800,NULL,20); |
||||
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600,300,30); |
||||
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,'22-FEB-81',1250,500,30); |
||||
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,'02-APR-81',2975,NULL,20); |
||||
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250,1400,30); |
||||
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,'01-MAY-81',2850,NULL,30); |
||||
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,'09-JUN-81',2450,NULL,10); |
||||
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,'19-APR-87',3000,NULL,20); |
||||
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000,NULL,10); |
||||
INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,'08-SEP-81',1500,0,30); |
||||
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,'23-MAY-87',1100,NULL,20); |
||||
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,'03-DEC-81',950,NULL,30); |
||||
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,'03-DEC-81',3000,NULL,20); |
||||
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,'23-JAN-82',1300,NULL,10); |
||||
-- |
||||
-- Load the 'jobhist' table |
||||
-- |
||||
INSERT INTO jobhist VALUES (7369,'17-DEC-80',NULL,'CLERK',800,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7499,'20-FEB-81',NULL,'SALESMAN',1600,300,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7521,'22-FEB-81',NULL,'SALESMAN',1250,500,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7566,'02-APR-81',NULL,'MANAGER',2975,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7654,'28-SEP-81',NULL,'SALESMAN',1250,1400,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7698,'01-MAY-81',NULL,'MANAGER',2850,NULL,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7782,'09-JUN-81',NULL,'MANAGER',2450,NULL,10,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7788,'19-APR-87','12-APR-88','CLERK',1000,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7788,'13-APR-88','04-MAY-89','CLERK',1040,NULL,20,'Raise'); |
||||
INSERT INTO jobhist VALUES (7788,'05-MAY-90',NULL,'ANALYST',3000,NULL,20,'Promoted to Analyst'); |
||||
INSERT INTO jobhist VALUES (7839,'17-NOV-81',NULL,'PRESIDENT',5000,NULL,10,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7844,'08-SEP-81',NULL,'SALESMAN',1500,0,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7876,'23-MAY-87',NULL,'CLERK',1100,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7900,'03-DEC-81','14-JAN-83','CLERK',950,NULL,10,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7900,'15-JAN-83',NULL,'CLERK',950,NULL,30,'Changed to Dept 30'); |
||||
INSERT INTO jobhist VALUES (7902,'03-DEC-81',NULL,'ANALYST',3000,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7934,'23-JAN-82',NULL,'CLERK',1300,NULL,10,'New Hire'); |
||||
-- |
||||
-- Populate statistics table and view (pg_statistic/pg_stats) |
||||
-- |
||||
ANALYZE dept; |
||||
ANALYZE emp; |
||||
ANALYZE jobhist; |
||||
-- |
||||
-- Function that lists all employees' numbers and names |
||||
-- from the 'emp' table using a cursor. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION list_emp() RETURNS VOID |
||||
AS $$ |
||||
DECLARE |
||||
v_empno NUMERIC(4); |
||||
v_ename VARCHAR(10); |
||||
emp_cur CURSOR FOR |
||||
SELECT empno, ename FROM emp ORDER BY empno; |
||||
BEGIN |
||||
OPEN emp_cur; |
||||
RAISE INFO 'EMPNO ENAME'; |
||||
RAISE INFO '----- -------'; |
||||
LOOP |
||||
FETCH emp_cur INTO v_empno, v_ename; |
||||
EXIT WHEN NOT FOUND; |
||||
RAISE INFO '% %', v_empno, v_ename; |
||||
END LOOP; |
||||
CLOSE emp_cur; |
||||
RETURN; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that selects an employee row given the employee |
||||
-- number and displays certain columns. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION select_emp ( |
||||
p_empno NUMERIC |
||||
) RETURNS VOID |
||||
AS $$ |
||||
DECLARE |
||||
v_ename emp.ename%TYPE; |
||||
v_hiredate emp.hiredate%TYPE; |
||||
v_sal emp.sal%TYPE; |
||||
v_comm emp.comm%TYPE; |
||||
v_dname dept.dname%TYPE; |
||||
v_disp_date VARCHAR(10); |
||||
BEGIN |
||||
SELECT INTO |
||||
v_ename, v_hiredate, v_sal, v_comm, v_dname |
||||
ename, hiredate, sal, COALESCE(comm, 0), dname |
||||
FROM emp e, dept d |
||||
WHERE empno = p_empno |
||||
AND e.deptno = d.deptno; |
||||
IF NOT FOUND THEN |
||||
RAISE INFO 'Employee % not found', p_empno; |
||||
RETURN; |
||||
END IF; |
||||
v_disp_date := TO_CHAR(v_hiredate, 'MM/DD/YYYY'); |
||||
RAISE INFO 'Number : %', p_empno; |
||||
RAISE INFO 'Name : %', v_ename; |
||||
RAISE INFO 'Hire Date : %', v_disp_date; |
||||
RAISE INFO 'Salary : %', v_sal; |
||||
RAISE INFO 'Commission: %', v_comm; |
||||
RAISE INFO 'Department: %', v_dname; |
||||
RETURN; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- A RECORD type used to format the return value of |
||||
-- function, 'emp_query'. |
||||
-- |
||||
CREATE TYPE emp_query_type AS ( |
||||
empno NUMERIC, |
||||
ename VARCHAR(10), |
||||
job VARCHAR(9), |
||||
hiredate DATE, |
||||
sal NUMERIC |
||||
); |
||||
-- |
||||
-- Function that queries the 'emp' table based on |
||||
-- department number and employee number or name. Returns |
||||
-- employee number and name as INOUT parameters and job, |
||||
-- hire date, and salary as OUT parameters. These are |
||||
-- returned in the form of a record defined by |
||||
-- RECORD type, 'emp_query_type'. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_query ( |
||||
IN p_deptno NUMERIC, |
||||
INOUT p_empno NUMERIC, |
||||
INOUT p_ename VARCHAR, |
||||
OUT p_job VARCHAR, |
||||
OUT p_hiredate DATE, |
||||
OUT p_sal NUMERIC |
||||
) |
||||
AS $$ |
||||
BEGIN |
||||
SELECT INTO |
||||
p_empno, p_ename, p_job, p_hiredate, p_sal |
||||
empno, ename, job, hiredate, sal |
||||
FROM emp |
||||
WHERE deptno = p_deptno |
||||
AND (empno = p_empno |
||||
OR ename = UPPER(p_ename)); |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function to call 'emp_query_caller' with IN and INOUT |
||||
-- parameters. Displays the results received from INOUT and |
||||
-- OUT parameters. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_query_caller() RETURNS VOID |
||||
AS $$ |
||||
DECLARE |
||||
v_deptno NUMERIC; |
||||
v_empno NUMERIC; |
||||
v_ename VARCHAR; |
||||
v_rows INTEGER; |
||||
r_emp_query EMP_QUERY_TYPE; |
||||
BEGIN |
||||
v_deptno := 30; |
||||
v_empno := 0; |
||||
v_ename := 'Martin'; |
||||
r_emp_query := emp_query(v_deptno, v_empno, v_ename); |
||||
RAISE INFO 'Department : %', v_deptno; |
||||
RAISE INFO 'Employee No: %', (r_emp_query).empno; |
||||
RAISE INFO 'Name : %', (r_emp_query).ename; |
||||
RAISE INFO 'Job : %', (r_emp_query).job; |
||||
RAISE INFO 'Hire Date : %', (r_emp_query).hiredate; |
||||
RAISE INFO 'Salary : %', (r_emp_query).sal; |
||||
RETURN; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function to compute yearly compensation based on semimonthly |
||||
-- salary. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_comp ( |
||||
p_sal NUMERIC, |
||||
p_comm NUMERIC |
||||
) RETURNS NUMERIC |
||||
AS $$ |
||||
BEGIN |
||||
RETURN (p_sal + COALESCE(p_comm, 0)) * 24; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that gets the next number from sequence, 'next_empno', |
||||
-- and ensures it is not already in use as an employee number. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION new_empno() RETURNS INTEGER |
||||
AS $$ |
||||
DECLARE |
||||
v_cnt INTEGER := 1; |
||||
v_new_empno INTEGER; |
||||
BEGIN |
||||
WHILE v_cnt > 0 LOOP |
||||
SELECT INTO v_new_empno nextval('next_empno'); |
||||
SELECT INTO v_cnt COUNT(*) FROM emp WHERE empno = v_new_empno; |
||||
END LOOP; |
||||
RETURN v_new_empno; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that adds a new clerk to table 'emp'. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION hire_clerk ( |
||||
p_ename VARCHAR, |
||||
p_deptno NUMERIC |
||||
) RETURNS NUMERIC |
||||
AS $$ |
||||
DECLARE |
||||
v_empno NUMERIC(4); |
||||
v_ename VARCHAR(10); |
||||
v_job VARCHAR(9); |
||||
v_mgr NUMERIC(4); |
||||
v_hiredate DATE; |
||||
v_sal NUMERIC(7,2); |
||||
v_comm NUMERIC(7,2); |
||||
v_deptno NUMERIC(2); |
||||
BEGIN |
||||
v_empno := new_empno(); |
||||
INSERT INTO emp VALUES (v_empno, p_ename, 'CLERK', 7782, |
||||
CURRENT_DATE, 950.00, NULL, p_deptno); |
||||
SELECT INTO |
||||
v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno |
||||
empno, ename, job, mgr, hiredate, sal, comm, deptno |
||||
FROM emp WHERE empno = v_empno; |
||||
RAISE INFO 'Department : %', v_deptno; |
||||
RAISE INFO 'Employee No: %', v_empno; |
||||
RAISE INFO 'Name : %', v_ename; |
||||
RAISE INFO 'Job : %', v_job; |
||||
RAISE INFO 'Manager : %', v_mgr; |
||||
RAISE INFO 'Hire Date : %', v_hiredate; |
||||
RAISE INFO 'Salary : %', v_sal; |
||||
RAISE INFO 'Commission : %', v_comm; |
||||
RETURN v_empno; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN -1; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that adds a new salesman to table 'emp'. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION hire_salesman ( |
||||
p_ename VARCHAR, |
||||
p_sal NUMERIC, |
||||
p_comm NUMERIC |
||||
) RETURNS NUMERIC |
||||
AS $$ |
||||
DECLARE |
||||
v_empno NUMERIC(4); |
||||
v_ename VARCHAR(10); |
||||
v_job VARCHAR(9); |
||||
v_mgr NUMERIC(4); |
||||
v_hiredate DATE; |
||||
v_sal NUMERIC(7,2); |
||||
v_comm NUMERIC(7,2); |
||||
v_deptno NUMERIC(2); |
||||
BEGIN |
||||
v_empno := new_empno(); |
||||
INSERT INTO emp VALUES (v_empno, p_ename, 'SALESMAN', 7698, |
||||
CURRENT_DATE, p_sal, p_comm, 30); |
||||
SELECT INTO |
||||
v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno |
||||
empno, ename, job, mgr, hiredate, sal, comm, deptno |
||||
FROM emp WHERE empno = v_empno; |
||||
RAISE INFO 'Department : %', v_deptno; |
||||
RAISE INFO 'Employee No: %', v_empno; |
||||
RAISE INFO 'Name : %', v_ename; |
||||
RAISE INFO 'Job : %', v_job; |
||||
RAISE INFO 'Manager : %', v_mgr; |
||||
RAISE INFO 'Hire Date : %', v_hiredate; |
||||
RAISE INFO 'Salary : %', v_sal; |
||||
RAISE INFO 'Commission : %', v_comm; |
||||
RETURN v_empno; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN -1; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Rule to INSERT into view 'salesemp' |
||||
-- |
||||
CREATE OR REPLACE RULE salesemp_i AS ON INSERT TO salesemp |
||||
DO INSTEAD |
||||
INSERT INTO emp VALUES (NEW.empno, NEW.ename, 'SALESMAN', 7698, |
||||
NEW.hiredate, NEW.sal, NEW.comm, 30); |
||||
-- |
||||
-- Rule to UPDATE view 'salesemp' |
||||
-- |
||||
CREATE OR REPLACE RULE salesemp_u AS ON UPDATE TO salesemp |
||||
DO INSTEAD |
||||
UPDATE emp SET empno = NEW.empno, |
||||
ename = NEW.ename, |
||||
hiredate = NEW.hiredate, |
||||
sal = NEW.sal, |
||||
comm = NEW.comm |
||||
WHERE empno = OLD.empno; |
||||
-- |
||||
-- Rule to DELETE from view 'salesemp' |
||||
-- |
||||
CREATE OR REPLACE RULE salesemp_d AS ON DELETE TO salesemp |
||||
DO INSTEAD |
||||
DELETE FROM emp WHERE empno = OLD.empno; |
||||
-- |
||||
-- After statement-level trigger that displays a message after |
||||
-- an insert, update, or deletion to the 'emp' table. One message |
||||
-- per SQL command is displayed. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION user_audit_trig() RETURNS TRIGGER |
||||
AS $$ |
||||
DECLARE |
||||
v_action VARCHAR(24); |
||||
v_text TEXT; |
||||
BEGIN |
||||
IF TG_OP = 'INSERT' THEN |
||||
v_action := ' added employee(s) on '; |
||||
ELSIF TG_OP = 'UPDATE' THEN |
||||
v_action := ' updated employee(s) on '; |
||||
ELSIF TG_OP = 'DELETE' THEN |
||||
v_action := ' deleted employee(s) on '; |
||||
END IF; |
||||
-- v_text := 'User ' || USER || v_action || CURRENT_DATE; Changing this as we need consistent output for regression |
||||
v_text := 'User ' || v_action ; |
||||
RAISE INFO ' %', v_text; |
||||
RETURN NULL; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
CREATE TRIGGER user_audit_trig |
||||
AFTER INSERT OR UPDATE OR DELETE ON emp |
||||
FOR EACH STATEMENT EXECUTE PROCEDURE user_audit_trig(); |
||||
-- |
||||
-- Before row-level trigger that displays employee number and |
||||
-- salary of an employee that is about to be added, updated, |
||||
-- or deleted in the 'emp' table. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_sal_trig() RETURNS TRIGGER |
||||
AS $$ |
||||
DECLARE |
||||
sal_diff NUMERIC(7,2); |
||||
BEGIN |
||||
IF TG_OP = 'INSERT' THEN |
||||
RAISE INFO 'Inserting employee %', NEW.empno; |
||||
RAISE INFO '..New salary: %', NEW.sal; |
||||
RETURN NEW; |
||||
END IF; |
||||
IF TG_OP = 'UPDATE' THEN |
||||
sal_diff := NEW.sal - OLD.sal; |
||||
RAISE INFO 'Updating employee %', OLD.empno; |
||||
RAISE INFO '..Old salary: %', OLD.sal; |
||||
RAISE INFO '..New salary: %', NEW.sal; |
||||
RAISE INFO '..Raise : %', sal_diff; |
||||
RETURN NEW; |
||||
END IF; |
||||
IF TG_OP = 'DELETE' THEN |
||||
RAISE INFO 'Deleting employee %', OLD.empno; |
||||
RAISE INFO '..Old salary: %', OLD.sal; |
||||
RETURN OLD; |
||||
END IF; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
CREATE TRIGGER emp_sal_trig |
||||
BEFORE DELETE OR INSERT OR UPDATE ON emp |
||||
FOR EACH ROW EXECUTE PROCEDURE emp_sal_trig(); |
||||
COMMIT; |
||||
SELECT * FROM emp; |
||||
empno | ename | job | mgr | hiredate | sal | comm | deptno |
||||
-------+--------+-----------+------+------------+---------+---------+-------- |
||||
7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | | 20 |
||||
7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
||||
7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
||||
7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | | 20 |
||||
7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
||||
7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | | 30 |
||||
7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | | 10 |
||||
7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | | 20 |
||||
7839 | KING | PRESIDENT | | 1981-11-17 | 5000.00 | | 10 |
||||
7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
||||
7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | | 20 |
||||
7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | | 30 |
||||
7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | | 20 |
||||
7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | | 10 |
||||
(14 rows) |
||||
|
||||
SELECT * FROM dept; |
||||
deptno | dname | loc |
||||
--------+------------+---------- |
||||
10 | ACCOUNTING | NEW YORK |
||||
20 | RESEARCH | DALLAS |
||||
30 | SALES | CHICAGO |
||||
40 | OPERATIONS | BOSTON |
||||
(4 rows) |
||||
|
||||
SELECT * FROM jobhist; |
||||
empno | startdate | enddate | job | sal | comm | deptno | chgdesc |
||||
-------+---------------------+---------------------+-----------+---------+---------+--------+--------------------- |
||||
7369 | 1980-12-17 00:00:00 | | CLERK | 800.00 | | 20 | New Hire |
||||
7499 | 1981-02-20 00:00:00 | | SALESMAN | 1600.00 | 300.00 | 30 | New Hire |
||||
7521 | 1981-02-22 00:00:00 | | SALESMAN | 1250.00 | 500.00 | 30 | New Hire |
||||
7566 | 1981-04-02 00:00:00 | | MANAGER | 2975.00 | | 20 | New Hire |
||||
7654 | 1981-09-28 00:00:00 | | SALESMAN | 1250.00 | 1400.00 | 30 | New Hire |
||||
7698 | 1981-05-01 00:00:00 | | MANAGER | 2850.00 | | 30 | New Hire |
||||
7782 | 1981-06-09 00:00:00 | | MANAGER | 2450.00 | | 10 | New Hire |
||||
7788 | 1987-04-19 00:00:00 | 1988-04-12 00:00:00 | CLERK | 1000.00 | | 20 | New Hire |
||||
7788 | 1988-04-13 00:00:00 | 1989-05-04 00:00:00 | CLERK | 1040.00 | | 20 | Raise |
||||
7788 | 1990-05-05 00:00:00 | | ANALYST | 3000.00 | | 20 | Promoted to Analyst |
||||
7839 | 1981-11-17 00:00:00 | | PRESIDENT | 5000.00 | | 10 | New Hire |
||||
7844 | 1981-09-08 00:00:00 | | SALESMAN | 1500.00 | 0.00 | 30 | New Hire |
||||
7876 | 1987-05-23 00:00:00 | | CLERK | 1100.00 | | 20 | New Hire |
||||
7900 | 1981-12-03 00:00:00 | 1983-01-14 00:00:00 | CLERK | 950.00 | | 10 | New Hire |
||||
7900 | 1983-01-15 00:00:00 | | CLERK | 950.00 | | 30 | Changed to Dept 30 |
||||
7902 | 1981-12-03 00:00:00 | | ANALYST | 3000.00 | | 20 | New Hire |
||||
7934 | 1982-01-23 00:00:00 | | CLERK | 1300.00 | | 10 | New Hire |
||||
(17 rows) |
||||
|
||||
-- Now test the crash fix |
||||
DELETE FROM emp WHERE empno = 7934; |
||||
psql:sql/test_issue_153_fix.inc:465: INFO: Deleting employee 7934 |
||||
psql:sql/test_issue_153_fix.inc:465: INFO: ..Old salary: 1300.00 |
||||
psql:sql/test_issue_153_fix.inc:465: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7698; |
||||
psql:sql/test_issue_153_fix.inc:466: INFO: Deleting employee 7698 |
||||
psql:sql/test_issue_153_fix.inc:466: INFO: ..Old salary: 2850.00 |
||||
psql:sql/test_issue_153_fix.inc:466: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7782; |
||||
psql:sql/test_issue_153_fix.inc:467: INFO: Deleting employee 7782 |
||||
psql:sql/test_issue_153_fix.inc:467: INFO: ..Old salary: 2450.00 |
||||
psql:sql/test_issue_153_fix.inc:467: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7788; |
||||
psql:sql/test_issue_153_fix.inc:468: INFO: Deleting employee 7788 |
||||
psql:sql/test_issue_153_fix.inc:468: INFO: ..Old salary: 3000.00 |
||||
psql:sql/test_issue_153_fix.inc:468: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7838; |
||||
psql:sql/test_issue_153_fix.inc:469: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7900; |
||||
psql:sql/test_issue_153_fix.inc:470: INFO: Deleting employee 7900 |
||||
psql:sql/test_issue_153_fix.inc:470: INFO: ..Old salary: 950.00 |
||||
psql:sql/test_issue_153_fix.inc:470: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7654; |
||||
psql:sql/test_issue_153_fix.inc:471: INFO: Deleting employee 7654 |
||||
psql:sql/test_issue_153_fix.inc:471: INFO: ..Old salary: 1250.00 |
||||
psql:sql/test_issue_153_fix.inc:471: INFO: User deleted employee(s) on |
||||
DELETE FROM dept WHERE deptno = 40; |
||||
SELECT * FROM emp; |
||||
empno | ename | job | mgr | hiredate | sal | comm | deptno |
||||
-------+--------+-----------+------+------------+---------+--------+-------- |
||||
7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | | 20 |
||||
7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
||||
7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
||||
7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | | 20 |
||||
7839 | KING | PRESIDENT | | 1981-11-17 | 5000.00 | | 10 |
||||
7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
||||
7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | | 20 |
||||
7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | | 20 |
||||
(8 rows) |
||||
|
||||
SELECT * FROM dept; |
||||
deptno | dname | loc |
||||
--------+------------+---------- |
||||
10 | ACCOUNTING | NEW YORK |
||||
20 | RESEARCH | DALLAS |
||||
30 | SALES | CHICAGO |
||||
(3 rows) |
||||
|
||||
SELECT * FROM jobhist; |
||||
empno | startdate | enddate | job | sal | comm | deptno | chgdesc |
||||
-------+---------------------+---------+-----------+---------+--------+--------+---------- |
||||
7369 | 1980-12-17 00:00:00 | | CLERK | 800.00 | | 20 | New Hire |
||||
7499 | 1981-02-20 00:00:00 | | SALESMAN | 1600.00 | 300.00 | 30 | New Hire |
||||
7521 | 1981-02-22 00:00:00 | | SALESMAN | 1250.00 | 500.00 | 30 | New Hire |
||||
7566 | 1981-04-02 00:00:00 | | MANAGER | 2975.00 | | 20 | New Hire |
||||
7839 | 1981-11-17 00:00:00 | | PRESIDENT | 5000.00 | | 10 | New Hire |
||||
7844 | 1981-09-08 00:00:00 | | SALESMAN | 1500.00 | 0.00 | 30 | New Hire |
||||
7876 | 1987-05-23 00:00:00 | | CLERK | 1100.00 | | 20 | New Hire |
||||
7902 | 1981-12-03 00:00:00 | | ANALYST | 3000.00 | | 20 | New Hire |
||||
(8 rows) |
||||
|
||||
DROP TABLE jobhist CASCADE; |
||||
DROP TABLE emp CASCADE; |
||||
psql:sql/test_issue_153_fix.inc:480: NOTICE: drop cascades to view salesemp |
||||
DROP TABLE dept CASCADE; |
||||
DROP SEQUENCE next_empno; |
||||
DROP TYPE emp_query_type; |
||||
DROP EXTENSION pg_tde CASCADE; |
@ -0,0 +1,589 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/test_issue_153_fix.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SET datestyle TO 'iso, dmy'; |
||||
SELECT * FROM pg_tde_principal_key_info(); |
||||
psql:sql/test_issue_153_fix.inc:4: ERROR: Principal key does not exists for the database |
||||
HINT: Use set_principal_key interface to set the principal key |
||||
CONTEXT: SQL function "pg_tde_principal_key_info" statement 1 |
||||
SELECT pg_tde_add_key_provider_file('file-ring','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-ring'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
-- |
||||
-- Script that creates the 'sample' tde encrypted tables, views |
||||
-- functions, triggers, etc. |
||||
-- |
||||
-- Start new transaction - commit all or nothing |
||||
-- |
||||
BEGIN; |
||||
-- |
||||
-- Create and load tables used in the documentation examples. |
||||
-- |
||||
-- Create the 'dept' table |
||||
-- |
||||
CREATE TABLE dept ( |
||||
deptno NUMERIC(2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY, |
||||
dname VARCHAR(14) CONSTRAINT dept_dname_uq UNIQUE, |
||||
loc VARCHAR(13) |
||||
)using :tde_am; |
||||
-- |
||||
-- Create the 'emp' table |
||||
-- |
||||
CREATE TABLE emp ( |
||||
empno NUMERIC(4) NOT NULL CONSTRAINT emp_pk PRIMARY KEY, |
||||
ename VARCHAR(10), |
||||
job VARCHAR(9), |
||||
mgr NUMERIC(4), |
||||
hiredate DATE, |
||||
sal NUMERIC(7,2) CONSTRAINT emp_sal_ck CHECK (sal > 0), |
||||
comm NUMERIC(7,2), |
||||
deptno NUMERIC(2) CONSTRAINT emp_ref_dept_fk |
||||
REFERENCES dept(deptno) |
||||
)using :tde_am; |
||||
-- |
||||
-- Create the 'jobhist' table |
||||
-- |
||||
CREATE TABLE jobhist ( |
||||
empno NUMERIC(4) NOT NULL, |
||||
startdate TIMESTAMP(0) NOT NULL, |
||||
enddate TIMESTAMP(0), |
||||
job VARCHAR(9), |
||||
sal NUMERIC(7,2), |
||||
comm NUMERIC(7,2), |
||||
deptno NUMERIC(2), |
||||
chgdesc VARCHAR(80), |
||||
CONSTRAINT jobhist_pk PRIMARY KEY (empno, startdate), |
||||
CONSTRAINT jobhist_ref_emp_fk FOREIGN KEY (empno) |
||||
REFERENCES emp(empno) ON DELETE CASCADE, |
||||
CONSTRAINT jobhist_ref_dept_fk FOREIGN KEY (deptno) |
||||
REFERENCES dept (deptno) ON DELETE SET NULL, |
||||
CONSTRAINT jobhist_date_chk CHECK (startdate <= enddate) |
||||
)using :tde_am; |
||||
-- |
||||
-- Create the 'salesemp' view |
||||
-- |
||||
CREATE OR REPLACE VIEW salesemp AS |
||||
SELECT empno, ename, hiredate, sal, comm FROM emp WHERE job = 'SALESMAN'; |
||||
-- |
||||
-- Sequence to generate values for function 'new_empno'. |
||||
-- |
||||
CREATE SEQUENCE next_empno START WITH 8000 INCREMENT BY 1; |
||||
-- |
||||
-- Issue PUBLIC grants |
||||
-- |
||||
GRANT ALL ON emp TO PUBLIC; |
||||
GRANT ALL ON dept TO PUBLIC; |
||||
GRANT ALL ON jobhist TO PUBLIC; |
||||
GRANT ALL ON salesemp TO PUBLIC; |
||||
GRANT ALL ON next_empno TO PUBLIC; |
||||
-- |
||||
-- Load the 'dept' table |
||||
-- |
||||
INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK'); |
||||
INSERT INTO dept VALUES (20,'RESEARCH','DALLAS'); |
||||
INSERT INTO dept VALUES (30,'SALES','CHICAGO'); |
||||
INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON'); |
||||
-- |
||||
-- Load the 'emp' table |
||||
-- |
||||
INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,'17-DEC-80',800,NULL,20); |
||||
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600,300,30); |
||||
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,'22-FEB-81',1250,500,30); |
||||
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,'02-APR-81',2975,NULL,20); |
||||
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250,1400,30); |
||||
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,'01-MAY-81',2850,NULL,30); |
||||
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,'09-JUN-81',2450,NULL,10); |
||||
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,'19-APR-87',3000,NULL,20); |
||||
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000,NULL,10); |
||||
INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,'08-SEP-81',1500,0,30); |
||||
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,'23-MAY-87',1100,NULL,20); |
||||
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,'03-DEC-81',950,NULL,30); |
||||
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,'03-DEC-81',3000,NULL,20); |
||||
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,'23-JAN-82',1300,NULL,10); |
||||
-- |
||||
-- Load the 'jobhist' table |
||||
-- |
||||
INSERT INTO jobhist VALUES (7369,'17-DEC-80',NULL,'CLERK',800,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7499,'20-FEB-81',NULL,'SALESMAN',1600,300,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7521,'22-FEB-81',NULL,'SALESMAN',1250,500,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7566,'02-APR-81',NULL,'MANAGER',2975,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7654,'28-SEP-81',NULL,'SALESMAN',1250,1400,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7698,'01-MAY-81',NULL,'MANAGER',2850,NULL,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7782,'09-JUN-81',NULL,'MANAGER',2450,NULL,10,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7788,'19-APR-87','12-APR-88','CLERK',1000,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7788,'13-APR-88','04-MAY-89','CLERK',1040,NULL,20,'Raise'); |
||||
INSERT INTO jobhist VALUES (7788,'05-MAY-90',NULL,'ANALYST',3000,NULL,20,'Promoted to Analyst'); |
||||
INSERT INTO jobhist VALUES (7839,'17-NOV-81',NULL,'PRESIDENT',5000,NULL,10,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7844,'08-SEP-81',NULL,'SALESMAN',1500,0,30,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7876,'23-MAY-87',NULL,'CLERK',1100,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7900,'03-DEC-81','14-JAN-83','CLERK',950,NULL,10,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7900,'15-JAN-83',NULL,'CLERK',950,NULL,30,'Changed to Dept 30'); |
||||
INSERT INTO jobhist VALUES (7902,'03-DEC-81',NULL,'ANALYST',3000,NULL,20,'New Hire'); |
||||
INSERT INTO jobhist VALUES (7934,'23-JAN-82',NULL,'CLERK',1300,NULL,10,'New Hire'); |
||||
-- |
||||
-- Populate statistics table and view (pg_statistic/pg_stats) |
||||
-- |
||||
ANALYZE dept; |
||||
ANALYZE emp; |
||||
ANALYZE jobhist; |
||||
-- |
||||
-- Function that lists all employees' numbers and names |
||||
-- from the 'emp' table using a cursor. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION list_emp() RETURNS VOID |
||||
AS $$ |
||||
DECLARE |
||||
v_empno NUMERIC(4); |
||||
v_ename VARCHAR(10); |
||||
emp_cur CURSOR FOR |
||||
SELECT empno, ename FROM emp ORDER BY empno; |
||||
BEGIN |
||||
OPEN emp_cur; |
||||
RAISE INFO 'EMPNO ENAME'; |
||||
RAISE INFO '----- -------'; |
||||
LOOP |
||||
FETCH emp_cur INTO v_empno, v_ename; |
||||
EXIT WHEN NOT FOUND; |
||||
RAISE INFO '% %', v_empno, v_ename; |
||||
END LOOP; |
||||
CLOSE emp_cur; |
||||
RETURN; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that selects an employee row given the employee |
||||
-- number and displays certain columns. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION select_emp ( |
||||
p_empno NUMERIC |
||||
) RETURNS VOID |
||||
AS $$ |
||||
DECLARE |
||||
v_ename emp.ename%TYPE; |
||||
v_hiredate emp.hiredate%TYPE; |
||||
v_sal emp.sal%TYPE; |
||||
v_comm emp.comm%TYPE; |
||||
v_dname dept.dname%TYPE; |
||||
v_disp_date VARCHAR(10); |
||||
BEGIN |
||||
SELECT INTO |
||||
v_ename, v_hiredate, v_sal, v_comm, v_dname |
||||
ename, hiredate, sal, COALESCE(comm, 0), dname |
||||
FROM emp e, dept d |
||||
WHERE empno = p_empno |
||||
AND e.deptno = d.deptno; |
||||
IF NOT FOUND THEN |
||||
RAISE INFO 'Employee % not found', p_empno; |
||||
RETURN; |
||||
END IF; |
||||
v_disp_date := TO_CHAR(v_hiredate, 'MM/DD/YYYY'); |
||||
RAISE INFO 'Number : %', p_empno; |
||||
RAISE INFO 'Name : %', v_ename; |
||||
RAISE INFO 'Hire Date : %', v_disp_date; |
||||
RAISE INFO 'Salary : %', v_sal; |
||||
RAISE INFO 'Commission: %', v_comm; |
||||
RAISE INFO 'Department: %', v_dname; |
||||
RETURN; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- A RECORD type used to format the return value of |
||||
-- function, 'emp_query'. |
||||
-- |
||||
CREATE TYPE emp_query_type AS ( |
||||
empno NUMERIC, |
||||
ename VARCHAR(10), |
||||
job VARCHAR(9), |
||||
hiredate DATE, |
||||
sal NUMERIC |
||||
); |
||||
-- |
||||
-- Function that queries the 'emp' table based on |
||||
-- department number and employee number or name. Returns |
||||
-- employee number and name as INOUT parameters and job, |
||||
-- hire date, and salary as OUT parameters. These are |
||||
-- returned in the form of a record defined by |
||||
-- RECORD type, 'emp_query_type'. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_query ( |
||||
IN p_deptno NUMERIC, |
||||
INOUT p_empno NUMERIC, |
||||
INOUT p_ename VARCHAR, |
||||
OUT p_job VARCHAR, |
||||
OUT p_hiredate DATE, |
||||
OUT p_sal NUMERIC |
||||
) |
||||
AS $$ |
||||
BEGIN |
||||
SELECT INTO |
||||
p_empno, p_ename, p_job, p_hiredate, p_sal |
||||
empno, ename, job, hiredate, sal |
||||
FROM emp |
||||
WHERE deptno = p_deptno |
||||
AND (empno = p_empno |
||||
OR ename = UPPER(p_ename)); |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function to call 'emp_query_caller' with IN and INOUT |
||||
-- parameters. Displays the results received from INOUT and |
||||
-- OUT parameters. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_query_caller() RETURNS VOID |
||||
AS $$ |
||||
DECLARE |
||||
v_deptno NUMERIC; |
||||
v_empno NUMERIC; |
||||
v_ename VARCHAR; |
||||
v_rows INTEGER; |
||||
r_emp_query EMP_QUERY_TYPE; |
||||
BEGIN |
||||
v_deptno := 30; |
||||
v_empno := 0; |
||||
v_ename := 'Martin'; |
||||
r_emp_query := emp_query(v_deptno, v_empno, v_ename); |
||||
RAISE INFO 'Department : %', v_deptno; |
||||
RAISE INFO 'Employee No: %', (r_emp_query).empno; |
||||
RAISE INFO 'Name : %', (r_emp_query).ename; |
||||
RAISE INFO 'Job : %', (r_emp_query).job; |
||||
RAISE INFO 'Hire Date : %', (r_emp_query).hiredate; |
||||
RAISE INFO 'Salary : %', (r_emp_query).sal; |
||||
RETURN; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function to compute yearly compensation based on semimonthly |
||||
-- salary. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_comp ( |
||||
p_sal NUMERIC, |
||||
p_comm NUMERIC |
||||
) RETURNS NUMERIC |
||||
AS $$ |
||||
BEGIN |
||||
RETURN (p_sal + COALESCE(p_comm, 0)) * 24; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that gets the next number from sequence, 'next_empno', |
||||
-- and ensures it is not already in use as an employee number. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION new_empno() RETURNS INTEGER |
||||
AS $$ |
||||
DECLARE |
||||
v_cnt INTEGER := 1; |
||||
v_new_empno INTEGER; |
||||
BEGIN |
||||
WHILE v_cnt > 0 LOOP |
||||
SELECT INTO v_new_empno nextval('next_empno'); |
||||
SELECT INTO v_cnt COUNT(*) FROM emp WHERE empno = v_new_empno; |
||||
END LOOP; |
||||
RETURN v_new_empno; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that adds a new clerk to table 'emp'. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION hire_clerk ( |
||||
p_ename VARCHAR, |
||||
p_deptno NUMERIC |
||||
) RETURNS NUMERIC |
||||
AS $$ |
||||
DECLARE |
||||
v_empno NUMERIC(4); |
||||
v_ename VARCHAR(10); |
||||
v_job VARCHAR(9); |
||||
v_mgr NUMERIC(4); |
||||
v_hiredate DATE; |
||||
v_sal NUMERIC(7,2); |
||||
v_comm NUMERIC(7,2); |
||||
v_deptno NUMERIC(2); |
||||
BEGIN |
||||
v_empno := new_empno(); |
||||
INSERT INTO emp VALUES (v_empno, p_ename, 'CLERK', 7782, |
||||
CURRENT_DATE, 950.00, NULL, p_deptno); |
||||
SELECT INTO |
||||
v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno |
||||
empno, ename, job, mgr, hiredate, sal, comm, deptno |
||||
FROM emp WHERE empno = v_empno; |
||||
RAISE INFO 'Department : %', v_deptno; |
||||
RAISE INFO 'Employee No: %', v_empno; |
||||
RAISE INFO 'Name : %', v_ename; |
||||
RAISE INFO 'Job : %', v_job; |
||||
RAISE INFO 'Manager : %', v_mgr; |
||||
RAISE INFO 'Hire Date : %', v_hiredate; |
||||
RAISE INFO 'Salary : %', v_sal; |
||||
RAISE INFO 'Commission : %', v_comm; |
||||
RETURN v_empno; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN -1; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Function that adds a new salesman to table 'emp'. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION hire_salesman ( |
||||
p_ename VARCHAR, |
||||
p_sal NUMERIC, |
||||
p_comm NUMERIC |
||||
) RETURNS NUMERIC |
||||
AS $$ |
||||
DECLARE |
||||
v_empno NUMERIC(4); |
||||
v_ename VARCHAR(10); |
||||
v_job VARCHAR(9); |
||||
v_mgr NUMERIC(4); |
||||
v_hiredate DATE; |
||||
v_sal NUMERIC(7,2); |
||||
v_comm NUMERIC(7,2); |
||||
v_deptno NUMERIC(2); |
||||
BEGIN |
||||
v_empno := new_empno(); |
||||
INSERT INTO emp VALUES (v_empno, p_ename, 'SALESMAN', 7698, |
||||
CURRENT_DATE, p_sal, p_comm, 30); |
||||
SELECT INTO |
||||
v_empno, v_ename, v_job, v_mgr, v_hiredate, v_sal, v_comm, v_deptno |
||||
empno, ename, job, mgr, hiredate, sal, comm, deptno |
||||
FROM emp WHERE empno = v_empno; |
||||
RAISE INFO 'Department : %', v_deptno; |
||||
RAISE INFO 'Employee No: %', v_empno; |
||||
RAISE INFO 'Name : %', v_ename; |
||||
RAISE INFO 'Job : %', v_job; |
||||
RAISE INFO 'Manager : %', v_mgr; |
||||
RAISE INFO 'Hire Date : %', v_hiredate; |
||||
RAISE INFO 'Salary : %', v_sal; |
||||
RAISE INFO 'Commission : %', v_comm; |
||||
RETURN v_empno; |
||||
EXCEPTION |
||||
WHEN OTHERS THEN |
||||
RAISE INFO 'The following is SQLERRM : %', SQLERRM; |
||||
RAISE INFO 'The following is SQLSTATE: %', SQLSTATE; |
||||
RETURN -1; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
-- |
||||
-- Rule to INSERT into view 'salesemp' |
||||
-- |
||||
CREATE OR REPLACE RULE salesemp_i AS ON INSERT TO salesemp |
||||
DO INSTEAD |
||||
INSERT INTO emp VALUES (NEW.empno, NEW.ename, 'SALESMAN', 7698, |
||||
NEW.hiredate, NEW.sal, NEW.comm, 30); |
||||
-- |
||||
-- Rule to UPDATE view 'salesemp' |
||||
-- |
||||
CREATE OR REPLACE RULE salesemp_u AS ON UPDATE TO salesemp |
||||
DO INSTEAD |
||||
UPDATE emp SET empno = NEW.empno, |
||||
ename = NEW.ename, |
||||
hiredate = NEW.hiredate, |
||||
sal = NEW.sal, |
||||
comm = NEW.comm |
||||
WHERE empno = OLD.empno; |
||||
-- |
||||
-- Rule to DELETE from view 'salesemp' |
||||
-- |
||||
CREATE OR REPLACE RULE salesemp_d AS ON DELETE TO salesemp |
||||
DO INSTEAD |
||||
DELETE FROM emp WHERE empno = OLD.empno; |
||||
-- |
||||
-- After statement-level trigger that displays a message after |
||||
-- an insert, update, or deletion to the 'emp' table. One message |
||||
-- per SQL command is displayed. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION user_audit_trig() RETURNS TRIGGER |
||||
AS $$ |
||||
DECLARE |
||||
v_action VARCHAR(24); |
||||
v_text TEXT; |
||||
BEGIN |
||||
IF TG_OP = 'INSERT' THEN |
||||
v_action := ' added employee(s) on '; |
||||
ELSIF TG_OP = 'UPDATE' THEN |
||||
v_action := ' updated employee(s) on '; |
||||
ELSIF TG_OP = 'DELETE' THEN |
||||
v_action := ' deleted employee(s) on '; |
||||
END IF; |
||||
-- v_text := 'User ' || USER || v_action || CURRENT_DATE; Changing this as we need consistent output for regression |
||||
v_text := 'User ' || v_action ; |
||||
RAISE INFO ' %', v_text; |
||||
RETURN NULL; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
CREATE TRIGGER user_audit_trig |
||||
AFTER INSERT OR UPDATE OR DELETE ON emp |
||||
FOR EACH STATEMENT EXECUTE PROCEDURE user_audit_trig(); |
||||
-- |
||||
-- Before row-level trigger that displays employee number and |
||||
-- salary of an employee that is about to be added, updated, |
||||
-- or deleted in the 'emp' table. |
||||
-- |
||||
CREATE OR REPLACE FUNCTION emp_sal_trig() RETURNS TRIGGER |
||||
AS $$ |
||||
DECLARE |
||||
sal_diff NUMERIC(7,2); |
||||
BEGIN |
||||
IF TG_OP = 'INSERT' THEN |
||||
RAISE INFO 'Inserting employee %', NEW.empno; |
||||
RAISE INFO '..New salary: %', NEW.sal; |
||||
RETURN NEW; |
||||
END IF; |
||||
IF TG_OP = 'UPDATE' THEN |
||||
sal_diff := NEW.sal - OLD.sal; |
||||
RAISE INFO 'Updating employee %', OLD.empno; |
||||
RAISE INFO '..Old salary: %', OLD.sal; |
||||
RAISE INFO '..New salary: %', NEW.sal; |
||||
RAISE INFO '..Raise : %', sal_diff; |
||||
RETURN NEW; |
||||
END IF; |
||||
IF TG_OP = 'DELETE' THEN |
||||
RAISE INFO 'Deleting employee %', OLD.empno; |
||||
RAISE INFO '..Old salary: %', OLD.sal; |
||||
RETURN OLD; |
||||
END IF; |
||||
END; |
||||
$$ LANGUAGE 'plpgsql'; |
||||
CREATE TRIGGER emp_sal_trig |
||||
BEFORE DELETE OR INSERT OR UPDATE ON emp |
||||
FOR EACH ROW EXECUTE PROCEDURE emp_sal_trig(); |
||||
COMMIT; |
||||
SELECT * FROM emp; |
||||
empno | ename | job | mgr | hiredate | sal | comm | deptno |
||||
-------+--------+-----------+------+------------+---------+---------+-------- |
||||
7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | | 20 |
||||
7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
||||
7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
||||
7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | | 20 |
||||
7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 |
||||
7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850.00 | | 30 |
||||
7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | | 10 |
||||
7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | | 20 |
||||
7839 | KING | PRESIDENT | | 1981-11-17 | 5000.00 | | 10 |
||||
7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
||||
7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | | 20 |
||||
7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | | 30 |
||||
7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | | 20 |
||||
7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | | 10 |
||||
(14 rows) |
||||
|
||||
SELECT * FROM dept; |
||||
deptno | dname | loc |
||||
--------+------------+---------- |
||||
10 | ACCOUNTING | NEW YORK |
||||
20 | RESEARCH | DALLAS |
||||
30 | SALES | CHICAGO |
||||
40 | OPERATIONS | BOSTON |
||||
(4 rows) |
||||
|
||||
SELECT * FROM jobhist; |
||||
empno | startdate | enddate | job | sal | comm | deptno | chgdesc |
||||
-------+---------------------+---------------------+-----------+---------+---------+--------+--------------------- |
||||
7369 | 1980-12-17 00:00:00 | | CLERK | 800.00 | | 20 | New Hire |
||||
7499 | 1981-02-20 00:00:00 | | SALESMAN | 1600.00 | 300.00 | 30 | New Hire |
||||
7521 | 1981-02-22 00:00:00 | | SALESMAN | 1250.00 | 500.00 | 30 | New Hire |
||||
7566 | 1981-04-02 00:00:00 | | MANAGER | 2975.00 | | 20 | New Hire |
||||
7654 | 1981-09-28 00:00:00 | | SALESMAN | 1250.00 | 1400.00 | 30 | New Hire |
||||
7698 | 1981-05-01 00:00:00 | | MANAGER | 2850.00 | | 30 | New Hire |
||||
7782 | 1981-06-09 00:00:00 | | MANAGER | 2450.00 | | 10 | New Hire |
||||
7788 | 1987-04-19 00:00:00 | 1988-04-12 00:00:00 | CLERK | 1000.00 | | 20 | New Hire |
||||
7788 | 1988-04-13 00:00:00 | 1989-05-04 00:00:00 | CLERK | 1040.00 | | 20 | Raise |
||||
7788 | 1990-05-05 00:00:00 | | ANALYST | 3000.00 | | 20 | Promoted to Analyst |
||||
7839 | 1981-11-17 00:00:00 | | PRESIDENT | 5000.00 | | 10 | New Hire |
||||
7844 | 1981-09-08 00:00:00 | | SALESMAN | 1500.00 | 0.00 | 30 | New Hire |
||||
7876 | 1987-05-23 00:00:00 | | CLERK | 1100.00 | | 20 | New Hire |
||||
7900 | 1981-12-03 00:00:00 | 1983-01-14 00:00:00 | CLERK | 950.00 | | 10 | New Hire |
||||
7900 | 1983-01-15 00:00:00 | | CLERK | 950.00 | | 30 | Changed to Dept 30 |
||||
7902 | 1981-12-03 00:00:00 | | ANALYST | 3000.00 | | 20 | New Hire |
||||
7934 | 1982-01-23 00:00:00 | | CLERK | 1300.00 | | 10 | New Hire |
||||
(17 rows) |
||||
|
||||
-- Now test the crash fix |
||||
DELETE FROM emp WHERE empno = 7934; |
||||
psql:sql/test_issue_153_fix.inc:465: INFO: Deleting employee 7934 |
||||
psql:sql/test_issue_153_fix.inc:465: INFO: ..Old salary: 1300.00 |
||||
psql:sql/test_issue_153_fix.inc:465: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7698; |
||||
psql:sql/test_issue_153_fix.inc:466: INFO: Deleting employee 7698 |
||||
psql:sql/test_issue_153_fix.inc:466: INFO: ..Old salary: 2850.00 |
||||
psql:sql/test_issue_153_fix.inc:466: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7782; |
||||
psql:sql/test_issue_153_fix.inc:467: INFO: Deleting employee 7782 |
||||
psql:sql/test_issue_153_fix.inc:467: INFO: ..Old salary: 2450.00 |
||||
psql:sql/test_issue_153_fix.inc:467: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7788; |
||||
psql:sql/test_issue_153_fix.inc:468: INFO: Deleting employee 7788 |
||||
psql:sql/test_issue_153_fix.inc:468: INFO: ..Old salary: 3000.00 |
||||
psql:sql/test_issue_153_fix.inc:468: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7838; |
||||
psql:sql/test_issue_153_fix.inc:469: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7900; |
||||
psql:sql/test_issue_153_fix.inc:470: INFO: Deleting employee 7900 |
||||
psql:sql/test_issue_153_fix.inc:470: INFO: ..Old salary: 950.00 |
||||
psql:sql/test_issue_153_fix.inc:470: INFO: User deleted employee(s) on |
||||
DELETE FROM emp WHERE empno = 7654; |
||||
psql:sql/test_issue_153_fix.inc:471: INFO: Deleting employee 7654 |
||||
psql:sql/test_issue_153_fix.inc:471: INFO: ..Old salary: 1250.00 |
||||
psql:sql/test_issue_153_fix.inc:471: INFO: User deleted employee(s) on |
||||
DELETE FROM dept WHERE deptno = 40; |
||||
SELECT * FROM emp; |
||||
empno | ename | job | mgr | hiredate | sal | comm | deptno |
||||
-------+--------+-----------+------+------------+---------+--------+-------- |
||||
7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | | 20 |
||||
7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 |
||||
7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 |
||||
7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | | 20 |
||||
7839 | KING | PRESIDENT | | 1981-11-17 | 5000.00 | | 10 |
||||
7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 |
||||
7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | | 20 |
||||
7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | | 20 |
||||
(8 rows) |
||||
|
||||
SELECT * FROM dept; |
||||
deptno | dname | loc |
||||
--------+------------+---------- |
||||
10 | ACCOUNTING | NEW YORK |
||||
20 | RESEARCH | DALLAS |
||||
30 | SALES | CHICAGO |
||||
(3 rows) |
||||
|
||||
SELECT * FROM jobhist; |
||||
empno | startdate | enddate | job | sal | comm | deptno | chgdesc |
||||
-------+---------------------+---------+-----------+---------+--------+--------+---------- |
||||
7369 | 1980-12-17 00:00:00 | | CLERK | 800.00 | | 20 | New Hire |
||||
7499 | 1981-02-20 00:00:00 | | SALESMAN | 1600.00 | 300.00 | 30 | New Hire |
||||
7521 | 1981-02-22 00:00:00 | | SALESMAN | 1250.00 | 500.00 | 30 | New Hire |
||||
7566 | 1981-04-02 00:00:00 | | MANAGER | 2975.00 | | 20 | New Hire |
||||
7839 | 1981-11-17 00:00:00 | | PRESIDENT | 5000.00 | | 10 | New Hire |
||||
7844 | 1981-09-08 00:00:00 | | SALESMAN | 1500.00 | 0.00 | 30 | New Hire |
||||
7876 | 1987-05-23 00:00:00 | | CLERK | 1100.00 | | 20 | New Hire |
||||
7902 | 1981-12-03 00:00:00 | | ANALYST | 3000.00 | | 20 | New Hire |
||||
(8 rows) |
||||
|
||||
DROP TABLE jobhist CASCADE; |
||||
DROP TABLE emp CASCADE; |
||||
psql:sql/test_issue_153_fix.inc:480: NOTICE: drop cascades to view salesemp |
||||
DROP TABLE dept CASCADE; |
||||
DROP SEQUENCE next_empno; |
||||
DROP TYPE emp_query_type; |
||||
DROP EXTENSION pg_tde CASCADE; |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,216 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/trigger_on_view.inc |
||||
CREATE extension pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
-- |
||||
-- 2 -- Test triggers on a join view |
||||
-- |
||||
SET default_table_access_method TO ':tde_am'; |
||||
psql:sql/trigger_on_view.inc:9: ERROR: invalid value for parameter "default_table_access_method": ":tde_am" |
||||
DETAIL: Table access method ":tde_am" does not exist. |
||||
DROP VIEW IF EXISTS city_view CASCADE; |
||||
psql:sql/trigger_on_view.inc:11: NOTICE: view "city_view" does not exist, skipping |
||||
DROP TABLE IF exists country_table CASCADE; |
||||
psql:sql/trigger_on_view.inc:12: NOTICE: table "country_table" does not exist, skipping |
||||
DROP TABLE IF exists city_table cascade; |
||||
psql:sql/trigger_on_view.inc:13: NOTICE: table "city_table" does not exist, skipping |
||||
CREATE TABLE country_table ( |
||||
country_id serial primary key, |
||||
country_name text unique not null, |
||||
continent text not null |
||||
) using :tde_am; |
||||
|
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('Japan', 'Asia'), |
||||
('UK', 'Europe'), |
||||
('USA', 'North America') |
||||
RETURNING *; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
(3 rows) |
||||
|
||||
|
||||
CREATE TABLE city_table ( |
||||
city_id serial primary key, |
||||
city_name text not null, |
||||
population bigint, |
||||
country_id int references country_table |
||||
) using :tde_am; |
||||
|
||||
CREATE VIEW city_view AS |
||||
SELECT city_id, city_name, population, country_name, continent |
||||
FROM city_table ci |
||||
LEFT JOIN country_table co ON co.country_id = ci.country_id; |
||||
|
||||
CREATE OR REPLACE FUNCTION city_insert() RETURNS trigger LANGUAGE plpgsql AS $$ |
||||
declare |
||||
ctry_id int; |
||||
begin |
||||
if NEW.country_name IS NOT NULL then |
||||
SELECT country_id, continent INTO ctry_id, NEW.continent |
||||
FROM country_table WHERE country_name = NEW.country_name; |
||||
if NOT FOUND then |
||||
raise exception 'No such country: "%"', NEW.country_name; |
||||
end if; |
||||
else |
||||
NEW.continent := NULL; |
||||
end if; |
||||
|
||||
if NEW.city_id IS NOT NULL then |
||||
INSERT INTO city_table |
||||
VALUES(NEW.city_id, NEW.city_name, NEW.population, ctry_id); |
||||
else |
||||
INSERT INTO city_table(city_name, population, country_id) |
||||
VALUES(NEW.city_name, NEW.population, ctry_id) |
||||
RETURNING city_id INTO NEW.city_id; |
||||
end if; |
||||
|
||||
RETURN NEW; |
||||
end; |
||||
$$; |
||||
CREATE TRIGGER city_insert_trig INSTEAD OF INSERT ON city_view |
||||
FOR EACH ROW EXECUTE PROCEDURE city_insert(); |
||||
|
||||
CREATE OR REPLACE FUNCTION city_delete() RETURNS trigger LANGUAGE plpgsql AS $$ |
||||
begin |
||||
DELETE FROM city_table WHERE city_id = OLD.city_id; |
||||
if NOT FOUND then RETURN NULL; end if; |
||||
RETURN OLD; |
||||
end; |
||||
$$; |
||||
|
||||
CREATE TRIGGER city_delete_trig INSTEAD OF DELETE ON city_view |
||||
FOR EACH ROW EXECUTE PROCEDURE city_delete(); |
||||
|
||||
CREATE OR REPLACE FUNCTION city_update() RETURNS trigger LANGUAGE plpgsql AS $$ |
||||
declare |
||||
ctry_id int; |
||||
begin |
||||
if NEW.country_name IS DISTINCT FROM OLD.country_name then |
||||
SELECT country_id, continent INTO ctry_id, NEW.continent |
||||
FROM country_table WHERE country_name = NEW.country_name; |
||||
if NOT FOUND then |
||||
raise exception 'No such country: "%"', NEW.country_name; |
||||
end if; |
||||
|
||||
UPDATE city_table SET city_name = NEW.city_name, |
||||
population = NEW.population, |
||||
country_id = ctry_id |
||||
WHERE city_id = OLD.city_id; |
||||
else |
||||
UPDATE city_table SET city_name = NEW.city_name, |
||||
population = NEW.population |
||||
WHERE city_id = OLD.city_id; |
||||
NEW.continent := OLD.continent; |
||||
end if; |
||||
|
||||
if NOT FOUND then RETURN NULL; end if; |
||||
RETURN NEW; |
||||
end; |
||||
$$; |
||||
CREATE TRIGGER city_update_trig INSTEAD OF UPDATE ON city_view |
||||
FOR EACH ROW EXECUTE PROCEDURE city_update(); |
||||
|
||||
-- INSERT .. RETURNING |
||||
INSERT INTO city_view(city_name) VALUES('Tokyo') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
1 | Tokyo | | | |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view(city_name, population) VALUES('London', 7556900) RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
2 | London | 7556900 | | |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view(city_name, country_name) VALUES('Washington DC', 'USA') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+---------------+------------+--------------+--------------- |
||||
3 | Washington DC | | USA | North America |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view(city_id, city_name) VALUES(123456, 'New York') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
123456 | New York | | | |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view VALUES(234567, 'Birmingham', 1016800, 'UK', 'EU') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+------------+------------+--------------+----------- |
||||
234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
|
||||
-- UPDATE .. RETURNING |
||||
UPDATE city_view SET country_name = 'Japon' WHERE city_name = 'Tokyo'; -- error |
||||
psql:sql/trigger_on_view.inc:118: ERROR: No such country: "Japon" |
||||
CONTEXT: PL/pgSQL function city_update() line 9 at RAISE |
||||
UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Takyo'; -- no match |
||||
UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Tokyo' RETURNING *; -- OK |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
1 | Tokyo | | Japan | Asia |
||||
(1 row) |
||||
|
||||
|
||||
UPDATE city_view SET population = 13010279 WHERE city_name = 'Tokyo' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
1 | Tokyo | 13010279 | Japan | Asia |
||||
(1 row) |
||||
|
||||
UPDATE city_view SET country_name = 'UK' WHERE city_name = 'New York' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
123456 | New York | | UK | Europe |
||||
(1 row) |
||||
|
||||
UPDATE city_view SET country_name = 'USA', population = 8391881 WHERE city_name = 'New York' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+--------------- |
||||
123456 | New York | 8391881 | USA | North America |
||||
(1 row) |
||||
|
||||
UPDATE city_view SET continent = 'EU' WHERE continent = 'Europe' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+------------+------------+--------------+----------- |
||||
234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
UPDATE city_view v1 SET country_name = v2.country_name FROM city_view v2 |
||||
WHERE v2.city_name = 'Birmingham' AND v1.city_name = 'London' RETURNING *; |
||||
city_id | city_name | population | country_name | continent | city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+-----------+---------+------------+------------+--------------+----------- |
||||
2 | London | 7556900 | UK | Europe | 234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
|
||||
-- DELETE .. RETURNING |
||||
DELETE FROM city_view WHERE city_name = 'Birmingham' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+------------+------------+--------------+----------- |
||||
234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
|
||||
DROP extension pg_tde CASCADE; |
||||
psql:sql/trigger_on_view.inc:133: NOTICE: drop cascades to 3 other objects |
||||
DETAIL: drop cascades to table country_table |
||||
drop cascades to table city_table |
||||
drop cascades to view city_view |
@ -0,0 +1,216 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/trigger_on_view.inc |
||||
CREATE extension pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
-- |
||||
-- 2 -- Test triggers on a join view |
||||
-- |
||||
SET default_table_access_method TO ':tde_am'; |
||||
psql:sql/trigger_on_view.inc:9: ERROR: invalid value for parameter "default_table_access_method": ":tde_am" |
||||
DETAIL: Table access method ":tde_am" does not exist. |
||||
DROP VIEW IF EXISTS city_view CASCADE; |
||||
psql:sql/trigger_on_view.inc:11: NOTICE: view "city_view" does not exist, skipping |
||||
DROP TABLE IF exists country_table CASCADE; |
||||
psql:sql/trigger_on_view.inc:12: NOTICE: table "country_table" does not exist, skipping |
||||
DROP TABLE IF exists city_table cascade; |
||||
psql:sql/trigger_on_view.inc:13: NOTICE: table "city_table" does not exist, skipping |
||||
CREATE TABLE country_table ( |
||||
country_id serial primary key, |
||||
country_name text unique not null, |
||||
continent text not null |
||||
) using :tde_am; |
||||
|
||||
INSERT INTO country_table (country_name, continent) |
||||
VALUES ('Japan', 'Asia'), |
||||
('UK', 'Europe'), |
||||
('USA', 'North America') |
||||
RETURNING *; |
||||
country_id | country_name | continent |
||||
------------+--------------+--------------- |
||||
1 | Japan | Asia |
||||
2 | UK | Europe |
||||
3 | USA | North America |
||||
(3 rows) |
||||
|
||||
|
||||
CREATE TABLE city_table ( |
||||
city_id serial primary key, |
||||
city_name text not null, |
||||
population bigint, |
||||
country_id int references country_table |
||||
) using :tde_am; |
||||
|
||||
CREATE VIEW city_view AS |
||||
SELECT city_id, city_name, population, country_name, continent |
||||
FROM city_table ci |
||||
LEFT JOIN country_table co ON co.country_id = ci.country_id; |
||||
|
||||
CREATE OR REPLACE FUNCTION city_insert() RETURNS trigger LANGUAGE plpgsql AS $$ |
||||
declare |
||||
ctry_id int; |
||||
begin |
||||
if NEW.country_name IS NOT NULL then |
||||
SELECT country_id, continent INTO ctry_id, NEW.continent |
||||
FROM country_table WHERE country_name = NEW.country_name; |
||||
if NOT FOUND then |
||||
raise exception 'No such country: "%"', NEW.country_name; |
||||
end if; |
||||
else |
||||
NEW.continent := NULL; |
||||
end if; |
||||
|
||||
if NEW.city_id IS NOT NULL then |
||||
INSERT INTO city_table |
||||
VALUES(NEW.city_id, NEW.city_name, NEW.population, ctry_id); |
||||
else |
||||
INSERT INTO city_table(city_name, population, country_id) |
||||
VALUES(NEW.city_name, NEW.population, ctry_id) |
||||
RETURNING city_id INTO NEW.city_id; |
||||
end if; |
||||
|
||||
RETURN NEW; |
||||
end; |
||||
$$; |
||||
CREATE TRIGGER city_insert_trig INSTEAD OF INSERT ON city_view |
||||
FOR EACH ROW EXECUTE PROCEDURE city_insert(); |
||||
|
||||
CREATE OR REPLACE FUNCTION city_delete() RETURNS trigger LANGUAGE plpgsql AS $$ |
||||
begin |
||||
DELETE FROM city_table WHERE city_id = OLD.city_id; |
||||
if NOT FOUND then RETURN NULL; end if; |
||||
RETURN OLD; |
||||
end; |
||||
$$; |
||||
|
||||
CREATE TRIGGER city_delete_trig INSTEAD OF DELETE ON city_view |
||||
FOR EACH ROW EXECUTE PROCEDURE city_delete(); |
||||
|
||||
CREATE OR REPLACE FUNCTION city_update() RETURNS trigger LANGUAGE plpgsql AS $$ |
||||
declare |
||||
ctry_id int; |
||||
begin |
||||
if NEW.country_name IS DISTINCT FROM OLD.country_name then |
||||
SELECT country_id, continent INTO ctry_id, NEW.continent |
||||
FROM country_table WHERE country_name = NEW.country_name; |
||||
if NOT FOUND then |
||||
raise exception 'No such country: "%"', NEW.country_name; |
||||
end if; |
||||
|
||||
UPDATE city_table SET city_name = NEW.city_name, |
||||
population = NEW.population, |
||||
country_id = ctry_id |
||||
WHERE city_id = OLD.city_id; |
||||
else |
||||
UPDATE city_table SET city_name = NEW.city_name, |
||||
population = NEW.population |
||||
WHERE city_id = OLD.city_id; |
||||
NEW.continent := OLD.continent; |
||||
end if; |
||||
|
||||
if NOT FOUND then RETURN NULL; end if; |
||||
RETURN NEW; |
||||
end; |
||||
$$; |
||||
CREATE TRIGGER city_update_trig INSTEAD OF UPDATE ON city_view |
||||
FOR EACH ROW EXECUTE PROCEDURE city_update(); |
||||
|
||||
-- INSERT .. RETURNING |
||||
INSERT INTO city_view(city_name) VALUES('Tokyo') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
1 | Tokyo | | | |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view(city_name, population) VALUES('London', 7556900) RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
2 | London | 7556900 | | |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view(city_name, country_name) VALUES('Washington DC', 'USA') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+---------------+------------+--------------+--------------- |
||||
3 | Washington DC | | USA | North America |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view(city_id, city_name) VALUES(123456, 'New York') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
123456 | New York | | | |
||||
(1 row) |
||||
|
||||
INSERT INTO city_view VALUES(234567, 'Birmingham', 1016800, 'UK', 'EU') RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+------------+------------+--------------+----------- |
||||
234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
|
||||
-- UPDATE .. RETURNING |
||||
UPDATE city_view SET country_name = 'Japon' WHERE city_name = 'Tokyo'; -- error |
||||
psql:sql/trigger_on_view.inc:118: ERROR: No such country: "Japon" |
||||
CONTEXT: PL/pgSQL function city_update() line 9 at RAISE |
||||
UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Takyo'; -- no match |
||||
UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Tokyo' RETURNING *; -- OK |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
1 | Tokyo | | Japan | Asia |
||||
(1 row) |
||||
|
||||
|
||||
UPDATE city_view SET population = 13010279 WHERE city_name = 'Tokyo' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
1 | Tokyo | 13010279 | Japan | Asia |
||||
(1 row) |
||||
|
||||
UPDATE city_view SET country_name = 'UK' WHERE city_name = 'New York' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+----------- |
||||
123456 | New York | | UK | Europe |
||||
(1 row) |
||||
|
||||
UPDATE city_view SET country_name = 'USA', population = 8391881 WHERE city_name = 'New York' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+--------------- |
||||
123456 | New York | 8391881 | USA | North America |
||||
(1 row) |
||||
|
||||
UPDATE city_view SET continent = 'EU' WHERE continent = 'Europe' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+------------+------------+--------------+----------- |
||||
234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
UPDATE city_view v1 SET country_name = v2.country_name FROM city_view v2 |
||||
WHERE v2.city_name = 'Birmingham' AND v1.city_name = 'London' RETURNING *; |
||||
city_id | city_name | population | country_name | continent | city_id | city_name | population | country_name | continent |
||||
---------+-----------+------------+--------------+-----------+---------+------------+------------+--------------+----------- |
||||
2 | London | 7556900 | UK | Europe | 234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
|
||||
-- DELETE .. RETURNING |
||||
DELETE FROM city_view WHERE city_name = 'Birmingham' RETURNING *; |
||||
city_id | city_name | population | country_name | continent |
||||
---------+------------+------------+--------------+----------- |
||||
234567 | Birmingham | 1016800 | UK | Europe |
||||
(1 row) |
||||
|
||||
|
||||
DROP extension pg_tde CASCADE; |
||||
psql:sql/trigger_on_view.inc:133: NOTICE: drop cascades to 3 other objects |
||||
DETAIL: drop cascades to table country_table |
||||
drop cascades to table city_table |
||||
drop cascades to view city_view |
@ -0,0 +1,47 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/update.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE update_test ( |
||||
a INT DEFAULT 10, |
||||
b INT, |
||||
c TEXT |
||||
) USING tde_heap_basic; |
||||
CREATE TABLE upsert_test ( |
||||
a INT PRIMARY KEY, |
||||
b TEXT |
||||
) USING tde_heap_basic; |
||||
INSERT INTO update_test VALUES (5, 10, 'foo'); |
||||
INSERT INTO update_test(b, a) VALUES (15, 10); |
||||
INSERT INTO upsert_test VALUES (2, 'Beeble') ON CONFLICT(a) |
||||
DO UPDATE SET (b, a) = (SELECT b || ', Excluded', a from upsert_test i WHERE i.a = excluded.a) |
||||
RETURNING tableoid::regclass, xmin = pg_current_xact_id()::xid AS xmin_correct, xmax = 0 AS xmax_correct; |
||||
tableoid | xmin_correct | xmax_correct |
||||
-------------+--------------+-------------- |
||||
upsert_test | t | t |
||||
(1 row) |
||||
|
||||
-- currently xmax is set after a conflict - that's probably not good, |
||||
-- but it seems worthwhile to have to be explicit if that changes. |
||||
INSERT INTO upsert_test VALUES (2, 'Brox') ON CONFLICT(a) |
||||
DO UPDATE SET (b, a) = (SELECT b || ', Excluded', a from upsert_test i WHERE i.a = excluded.a) |
||||
RETURNING tableoid::regclass, xmin = pg_current_xact_id()::xid AS xmin_correct, xmax = pg_current_xact_id()::xid AS xmax_correct; |
||||
tableoid | xmin_correct | xmax_correct |
||||
-------------+--------------+-------------- |
||||
upsert_test | t | t |
||||
(1 row) |
||||
|
||||
DROP TABLE update_test; |
||||
DROP TABLE upsert_test; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,47 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/update.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
CREATE TABLE update_test ( |
||||
a INT DEFAULT 10, |
||||
b INT, |
||||
c TEXT |
||||
) USING tde_heap_basic; |
||||
CREATE TABLE upsert_test ( |
||||
a INT PRIMARY KEY, |
||||
b TEXT |
||||
) USING tde_heap_basic; |
||||
INSERT INTO update_test VALUES (5, 10, 'foo'); |
||||
INSERT INTO update_test(b, a) VALUES (15, 10); |
||||
INSERT INTO upsert_test VALUES (2, 'Beeble') ON CONFLICT(a) |
||||
DO UPDATE SET (b, a) = (SELECT b || ', Excluded', a from upsert_test i WHERE i.a = excluded.a) |
||||
RETURNING tableoid::regclass, xmin = pg_current_xact_id()::xid AS xmin_correct, xmax = 0 AS xmax_correct; |
||||
tableoid | xmin_correct | xmax_correct |
||||
-------------+--------------+-------------- |
||||
upsert_test | t | t |
||||
(1 row) |
||||
|
||||
-- currently xmax is set after a conflict - that's probably not good, |
||||
-- but it seems worthwhile to have to be explicit if that changes. |
||||
INSERT INTO upsert_test VALUES (2, 'Brox') ON CONFLICT(a) |
||||
DO UPDATE SET (b, a) = (SELECT b || ', Excluded', a from upsert_test i WHERE i.a = excluded.a) |
||||
RETURNING tableoid::regclass, xmin = pg_current_xact_id()::xid AS xmin_correct, xmax = pg_current_xact_id()::xid AS xmax_correct; |
||||
tableoid | xmin_correct | xmax_correct |
||||
-------------+--------------+-------------- |
||||
upsert_test | t | t |
||||
(1 row) |
||||
|
||||
DROP TABLE update_test; |
||||
DROP TABLE upsert_test; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,24 @@ |
||||
\set tde_am tde_heap |
||||
\i sql/update_compare_indexes.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP TABLE IF EXISTS pvactst; |
||||
psql:sql/update_compare_indexes.inc:6: NOTICE: table "pvactst" does not exist, skipping |
||||
CREATE TABLE pvactst (i INT, a INT[], p POINT) USING :tde_am; |
||||
INSERT INTO pvactst SELECT i, array[1,2,3], point(i, i+1) FROM generate_series(1,1000) i; |
||||
CREATE INDEX spgist_pvactst ON pvactst USING spgist (p); |
||||
UPDATE pvactst SET i = i WHERE i < 1000; |
||||
-- crash! |
||||
DROP TABLE pvactst; |
||||
DROP EXTENSION pg_tde; |
@ -0,0 +1,24 @@ |
||||
\set tde_am tde_heap_basic |
||||
\i sql/update_compare_indexes.inc |
||||
CREATE EXTENSION pg_tde; |
||||
SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); |
||||
pg_tde_add_key_provider_file |
||||
------------------------------ |
||||
1 |
||||
(1 row) |
||||
|
||||
SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); |
||||
pg_tde_set_principal_key |
||||
-------------------------- |
||||
t |
||||
(1 row) |
||||
|
||||
DROP TABLE IF EXISTS pvactst; |
||||
psql:sql/update_compare_indexes.inc:6: NOTICE: table "pvactst" does not exist, skipping |
||||
CREATE TABLE pvactst (i INT, a INT[], p POINT) USING :tde_am; |
||||
INSERT INTO pvactst SELECT i, array[1,2,3], point(i, i+1) FROM generate_series(1,1000) i; |
||||
CREATE INDEX spgist_pvactst ON pvactst USING spgist (p); |
||||
UPDATE pvactst SET i = i WHERE i < 1000; |
||||
-- crash! |
||||
DROP TABLE pvactst; |
||||
DROP EXTENSION pg_tde; |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue