Compare commits

..
535 Commits
Author SHA1 Message Date
steve-chavez 36eb72c2a0 bump version to 12.2.11 2025-04-21 17:08:00 -05:00
Taimoor ZaeemandSteve Chavez 38c596800a fix: regression with parameter charset=utf-8 in mediatype 2025-04-21 17:06:26 -05:00
steve-chavez a7f9181462 bump version to 12.2.10 2025-04-18 21:28:00 -05:00
Michal KleczekandSteve Chavez f68d5944e6 fix: purge JWT cache asynchronously in a separate thread
Otherwise performance was reduced unnecessarily.
2025-04-18 21:27:36 -05:00
Wolfgang Walther b454f29b2c bump version to 12.2.9 2025-04-16 20:39:19 +02:00
Taimoor ZaeemandWolfgang Walther a3cc762f17 fix: valid JWTs after jwt-secret is changed in a config reload 2025-04-16 18:26:42 +00:00
Taimoor ZaeemandWolfgang Walther 66cd4ca596 fix: regression that replaces an unknown media type with */* (#4013) 2025-04-14 18:00:21 +02:00
Taimoor ZaeemandWolfgang Walther 513704dc2b fix: parsing of the for parameter of plan media type (#4005) 2025-04-12 15:37:37 +00:00
Thilo HohltandWolfgang Walther 026d84a093 docs: add archtika to example apps section on ecosystem page (#4007) 2025-04-11 14:34:56 +02:00
Taimoor ZaeemandWolfgang Walther 106f193a56 docs: add note that ordering of columns is not enforced (#3999) 2025-04-10 14:44:03 +02:00
steve-chavezandWolfgang Walther 79fc43ec39 docs: redirect from broken #bulk-insert-default 2025-04-04 18:24:26 +02:00
Taimoor ZaeemandWolfgang Walther b187f09574 docs: mention that updates also supports specifying columns and missing pref 2025-04-04 18:24:25 +02:00
Taimoor ZaeemandWolfgang Walther 4f1dc72e40 docs: explain missing preference header 2025-04-04 18:24:23 +02:00
renovate[bot]andWolfgang Walther d70d5cb19d chore(deps): update peter-evans/dockerhub-description action to v4.0.2 2025-04-03 12:19:48 +00:00
renovate[bot]andWolfgang Walther 6e851cce59 chore(deps): update peter-evans/dockerhub-description action to v4.0.1 2025-04-01 20:25:14 +00:00
renovate[bot]andWolfgang Walther accf46d2ee chore(deps): update all dependencies 2025-03-27 19:51:24 +00:00
renovate[bot]andWolfgang Walther 852f833d56 chore(deps): update all dependencies 2025-03-27 19:32:19 +00:00
Wolfgang Walther 48e6267dde docs: Remove broken link 2025-03-26 17:00:31 +01:00
Wolfgang Walther ed86bbf3de docs: remove broken link 2025-03-14 23:21:41 +01:00
Wolfgang Walther 3ba4290ef0 chore: Fix style check 2025-02-22 17:01:27 +01:00
Wolfgang Walther 0be047a52f docs: Fix outdated links 2025-02-22 16:10:50 +01:00
Wolfgang Walther d2d3367046 ci: Fix cirrus FreeBSD builds
Apparently Cirrus removed the 14-1 image. When I firsted looked into
this some days ago, when the job started failing, the docs were not
updated, yet - so it wasn't clear. Now the docs mention freebsd-14-2
explicitly...
2025-02-22 14:22:29 +01:00
Laurence IslaandWolfgang Walther ba6f985dac docs: make the aggregate functions docs less verbose 2025-02-22 13:19:10 +01:00
steve-chavezandWolfgang Walther 7cb007567b docs: reduce verbosity of aggregate functions 2025-02-22 13:19:10 +01:00
Taimoor ZaeemandWolfgang Walther acb72b7c67 docs: add missing jwt claims and clock skew (#3908) 2025-02-22 13:19:10 +01:00
steve-chavezandWolfgang Walther 8649d27709 docs: correct package for installation under Nix 2025-02-22 13:19:10 +01:00
steve-chavez 4a3936f71c bump version to 12.2.8 2025-02-10 13:25:22 -05:00
M. Taimoor Zaeemandsteve-chavez 9b6b5d06ea fix: log 503 client error to stderr 2025-02-10 13:24:52 -05:00
Wolfgang Walther ec83d08be6 bump version to 12.2.7 2025-02-03 18:38:41 +01:00
Diogo BiazusandWolfgang Walther c026d0752f fix: Fix regression for schema cache reloading via NOTIFY on Windows
Upstream accidentally removed the fix, which was introduced for #2524. Fixed again.

(cherry picked from commit b285f5fba6)
2025-02-03 18:35:24 +01:00
steve-chavez dc96cdb0c3 bump version to 12.2.6 2025-01-29 15:22:22 -05:00
Taimoor Zaeemandsteve-chavez 89be285e6a fix: jwt cache is not purged (#3801) 2025-01-29 15:14:05 -05:00
renovate[bot]andWolfgang Walther c6b4fca160 chore(deps): update codecov/codecov-action action to v5.3.1 2025-01-25 12:01:21 +01:00
renovate[bot]andWolfgang Walther 31cccd3264 chore(deps): update codecov/codecov-action action to v5.3.0 2025-01-25 11:12:46 +01:00
Wolfgang Walther 0bec15fb71 bump version to 12.2.5 2025-01-20 18:24:51 +01:00
Wolfgang Walther cc22da5a02 fix: Make postgrest binary in arm64 docker image executable
This happened in 06aebfaa and caused the arm64 docker image to not start
up properly.

Resolves #3867
2025-01-20 18:24:06 +01:00
Wolfgang Walther 4d477d6e12 bump version to 12.2.4 2025-01-18 19:01:16 +01:00
Wolfgang Walther aff2a78aac Revert "ci: Remove brew install libpq for macos-14 stack build"
This partially reverts commit 53164453d8.
2025-01-18 19:01:16 +01:00
Wolfgang Walther 868f4a066b ci: Fix stack cache on Windows
Apparently the STACK_ROOT has been moved to C:\sr - for unknown reasons,
at least to me.

This should enable caching again and make the stack on windows builds
much faster than recently.
2025-01-18 17:54:42 +01:00
Wolfgang Walther 2c04b98dd9 ci: Split ci into ci and release workflows
This is now possible, after we moved to the ARM build to the GitHub
runners.
2025-01-18 17:54:42 +01:00
Wolfgang Walther 71c73b20ca ci: Remove left-over permissions setting from tag job
This has been replaced by using the SSH key.
2025-01-18 17:54:42 +01:00
Wolfgang Walther 0160b6f370 ci: Display loadtest results in step summary
Much easier to implement and should be easier to find, too.
2025-01-18 17:54:42 +01:00
Wolfgang Walther 038c05447a ci: Build the ubuntu-aarch64 binary with new ARM runners
The new GitHub arm runners are available, so we can use them to build
the ubuntu aarch64 binary instead of our custom machine.
2025-01-18 17:54:42 +01:00
Wolfgang Walther 5d5ee71dce ci: Skip cachix push when no cachix token is set
This happens in forks.
2025-01-18 17:54:42 +01:00
Wolfgang Walther f09b4f4b7d ci: Remove brew install libpq for macos-14 stack build
When macos-14 was rolled out libpq was not installed, but by now it is
by default. Thus, we don't need to do that, it only creates a warning
annotation right now.
2025-01-18 17:54:42 +01:00
Wolfgang Walther d3f9de528c ci: Fix release name of x86-64 binaries
This should have been x86-64, only x64 is not a thing.
2025-01-18 17:54:42 +01:00
Wolfgang Walther c3f88d7a1d ci: Fix release name of macos binary
This is built on macos-14, which is running on new arm based hardware,
not the old x86_64 ones.
2025-01-18 17:54:42 +01:00
Wolfgang Walther 164e6a601f ci: Update stack builder to ubuntu 24.04
Renovate doesn't seem to pick this up, because it's in a matrix
specification.
2025-01-18 17:54:42 +01:00
Andrei DziahelandWolfgang Walther c135a30515 ci: drop directories from windows release
Puts windows release in line with others which have the executable on the top level
2025-01-18 17:54:32 +01:00
renovate[bot]andWolfgang Walther 7515eb5490 chore(deps): update all dependencies 2025-01-17 20:59:24 +01:00
renovate[bot]andWolfgang Walther 629b57337c chore(deps): update haskell-actions/setup action to v2.7.8 2024-12-30 16:31:53 +01:00
M. Taimoor ZaeemandWolfgang Walther 9fcbf994cb fix: insert with missing=default uses column default before using domain default 2024-12-25 11:43:34 +01:00
renovate[bot]andWolfgang Walther 7b9027ea0a chore(deps): update all dependencies 2024-12-20 20:00:36 +01:00
renovate[bot]andWolfgang Walther 0a7ae1815c chore(deps): update dependency macos to v14 2024-12-18 13:52:31 +01:00
renovate[bot]andWolfgang Walther 06014047cb chore(deps): update actions/upload-artifact action to v4.5.0 2024-12-18 12:56:42 +01:00
renovate[bot]andWolfgang Walther 7feb755521 chore(deps): update all dependencies 2024-12-06 09:48:27 +01:00
renovate[bot]andWolfgang Walther a0e7c4f591 chore(deps): update ubuntu:noble docker digest to 80dd3c3 2024-12-04 08:45:16 +01:00
renovate[bot]andWolfgang Walther 572f24901e chore(deps): update codecov/codecov-action action to v5.0.7 2024-11-21 21:26:15 +01:00
renovate[bot]andWolfgang Walther 1e599a2319 chore(deps): update codecov/codecov-action action to v5.0.5 2024-11-20 19:36:28 +01:00
steve-chavezandWolfgang Walther 4e9601d155 fix: always show schema cache load time
It used to be that this was only enabled with log-level=debug.
But the default log-level is misleading, for example:

```
$ PGRST_DB_SCHEMAS="apflora" postgrest-with-postgresql-16  -f test/io/big_schema.sql postgrest-run

...
13/Nov/2024:22:08:20 -0500: Config reloaded
13/Nov/2024:22:08:20 -0500: Schema cache queried in 36.3 milliseconds
13/Nov/2024:22:08:20 -0500: Schema cache loaded 326 Relations, 305 Relationships, 7 Functions, 0 Domain Representations, 4 Media Type Handlers, 1194 Timezones
```

The "Schema cache loaded" can take a while to appear, yet the 22:08:20
time is the same. If we reveal the load time this is clarified:

```
13/Nov/2024:22:08:37 -0500: Schema cache loaded in 16770.1 milliseconds
```
2024-11-16 22:41:44 +01:00
renovate[bot]andWolfgang Walther 53ce2df33a chore(deps): update ubuntu:noble docker digest to 278628f 2024-11-16 22:41:14 +01:00
Laurence IslaandWolfgang Walther c7152787b9 docs: clarify usage of upsert with surrogate primary keys 2024-11-16 13:16:35 +01:00
renovate[bot]andWolfgang Walther 4d4f93da40 chore(deps): update codecov/codecov-action action to v5.0.2 2024-11-15 18:54:10 +01:00
renovate[bot]andWolfgang Walther cb22931015 chore(deps): update codecov/codecov-action action to v5 2024-11-14 19:39:58 +01:00
renovate[bot]andWolfgang Walther 4cc09c6b42 chore(deps): update all dependencies 2024-11-06 19:43:33 +01:00
Wolfgang WaltherandWolfgang Walther 3379ee3483 chore(deps): Update nixpkgs to unstable 2024-05-29
This makes actionlint happy about the new ubuntu runners.
2024-11-06 17:35:55 +01:00
Wolfgang Walther fc7f715aeb ci: Update cirrus' freebsd image to 14.1
This should fix CI which is failing lately like this:
https://cirrus-ci.com/task/4665005218463744

ld-elf.so.1: /lib/libc.so.7: version FBSD_1.8 required by
/usr/local/bin/stack not found
2024-10-26 14:52:13 +02:00
renovate[bot]andWolfgang Walther ec568efd06 chore(deps): update all dependencies 2024-10-24 05:10:55 +02:00
Wolfgang Walther 5b755b2877 docs: Remove broken link
https://github.com/PostgREST/postgrest/actions/runs/11136795565/job/30949162312
2024-10-04 16:02:33 +02:00
renovate[bot]andWolfgang Walther f1453f3c37 chore(deps): update ubuntu:noble docker digest to dfc1087 2024-09-18 20:01:57 +02:00
renovate[bot]andWolfgang Walther 9100ba3b70 chore(deps): update dependency urllib3 to v2.2.3 2024-09-12 21:01:08 +02:00
renovate[bot]andWolfgang Walther 6fe82d9e94 chore(deps): update actions/upload-artifact action to v4.4.0 2024-09-04 13:29:55 +02:00
Jason CloseandGitHub 1fff248c78 docs: rpc example for array of json objects
This change adds an explanation of how to handle an array of JSON objects within an RPC call.  To pass multiple objects, an array of JSON objects must be the JSON value, with the key being the json or jsonb variable name of the Postgres function.

For people who want to perform multiple tasks/inserts/updates within a single API call, this is a needed explanation for that use-case.
2024-08-23 13:00:19 -05:00
renovate[bot]andWolfgang Walther f5264c5aa3 chore(deps): update ubuntu:noble docker digest to 8a37d68 2024-08-18 14:04:26 +02:00
renovate[bot]andLaurence Isla 5de55ea141 chore(deps): update all dependencies 2024-08-13 13:25:12 -05:00
renovate[bot]andWolfgang Walther 1ef83d3732 chore(deps): update actions/upload-artifact action to v4.3.5 2024-08-02 21:07:44 +02:00
Laurence Isla 519615d5fb bump version to 12.2.3 2024-08-01 11:46:52 -05:00
Laurence Isla de5a8954b2 changelog: add missing entry for 3670 2024-08-01 11:18:15 -05:00
64b5a59410 fix: schema cache loading before the in-db config (#3670)
Fixes #3660. Load the config after getting the pg version but before loading the schema.

The regression happened on f09655b.

Also remove schema cache load wrapper and separate db queries in different functions.

Co-authored-by: Laurence Isla <lau.isla.c@gmail.com>
2024-08-01 17:41:07 +02:00
Dan KurinandWolfgang Walther 417a96d137 fix: Remove OpenAPI format for rowFilter params (#3661) 2024-08-01 17:41:07 +02:00
Wolfgang Walther 53593824a8 fix: Embed One-to-One relationship with different column order properly 2024-07-13 22:27:04 +02:00
Wolfgang Walther e642086d27 chore: Fix changelog after 13868983 2024-07-13 17:16:06 +02:00
steve-chavezandWolfgang Walther e451700d5d chore: remove links to gitter
We'll now use github discussions for support.
2024-07-13 17:11:06 +02:00
Salim BandWolfgang Walther 13868983af fix: update OpenAPI externalDocs URL
fixes https://github.com/PostgREST/postgrest/issues/3091
2024-07-13 17:11:06 +02:00
steve-chavez db9da0b1ca bump version to 12.2.2 2024-07-10 23:07:23 -05:00
steve-chavez f09655b7a6 fix: schema cache retrying without backoff
Fixes https://github.com/PostgREST/postgrest/issues/3523.

Now if there's a failure when obtaining the pg version OR schema cache,
we do the same retrying process. This way we don't add two retries.

Refactors and renames the "connectionWorker" to "schemaCacheLoader".
This makes more sense since what we really want is the schema cache,
the version is the pre-requisite for ensuring our
schema cache queries work.

Additionally, we no longer log ` Attempting to connect to the database...`
at startup unnecessarily. This is only logged whenever there's a retry attempt.
2024-07-10 21:11:20 -05:00
steve-chavezandWolfgang Walther 8715e426c0 chore: remove paypal links
It was tied to a personal account and donations there have been too rare.
2024-07-10 21:13:23 +02:00
Wolfgang WaltherandWolfgang Walther 9a40bc266e fix: List correct enum options when multiple types with same name are present
The schema cache and OpenAPI output would currently list the first found
enum with the same name instead of the correct type. One other case
where this comes up is when a regular type and an enum type have the
same name. For example in the spec fixtures, we have an enum called
"bit". Every "bit" type, no matter whether it's that enum or the
built-in bit type, will show those enum options in the OpenApi output.

Not adding a test, because OpenAPI is supposed to go away in the future
anyway.
2024-07-09 09:09:22 +02:00
Wolfgang WaltherandWolfgang Walther e67461b991 fix: Show number of loaded timezones in log output
There is no reason to hide those, right?
2024-07-09 09:09:22 +02:00
Wolfgang WaltherandWolfgang Walther 420933ceba fix: Make --dump-schema work with in-database pgrst.db_schemas setting
This needs to be loaded from in-database configuration first, otherwise
the dump-schema output will be for the default (public) schema.
2024-07-09 09:09:22 +02:00
Laurence IslaandWolfgang Walther 8f8dbd3425 fix: nested empty embeds no longer return empty values and are correctly omitted 2024-07-09 09:09:22 +02:00
renovate[bot]andWolfgang Walther 8d7d7e4112 chore(deps): update all dependencies 2024-07-06 11:35:11 +02:00
Sandro BauerandWolfgang Walther 521acf61cb docs: fix rendering for inline code block in operator list 2024-07-02 12:28:24 +02:00
steve-chavez d3f7cba92e bump version to 12.2.1 2024-06-27 14:59:35 -05:00
Laurence IslaandSteve Chavez a71d9ea50f changelog: add missing entries for #3592 and #3616 2024-06-27 14:08:16 -05:00
Laurence IslaandSteve Chavez 5a1e9b01e4 nix: remove texlive dependencies from postgrest-docs-render 2024-06-27 14:08:16 -05:00
Laurence IslaandSteve Chavez d3292d42de docs: use PlantUML instead of Latex to generate Schema Isolation image 2024-06-27 14:08:16 -05:00
Laurence IslaandSteve Chavez 572581cbb6 chore: organize diagrams in different folders 2024-06-27 14:08:16 -05:00
steve-chavez 9daddb549c docs: add listener recovery 2024-06-27 14:08:16 -05:00
steve-chavez 716fcbf147 fix: don't reload cache on every listener fail
Revert "prevent GSSAPI error between Listener and pool"

This reverts commit 4beac10d3d.
2024-06-27 14:08:16 -05:00
Laurence IslaandSteve Chavez 5b62501ce7 docs: improve architecture diagram
- SVG format instead of PNG
- The components now have links to their reference in the Docs
- Supports dark mode
2024-06-27 14:08:16 -05:00
Wolfgang WaltherandSteve Chavez 7860e7287f docs: Fix punctuation in install.rst 2024-06-27 14:08:16 -05:00
Michal KleczekandSteve Chavez c958f94753 docs: add pg-notify-stdout to ecosystem 2024-06-27 14:08:16 -05:00
renovate[bot]andWolfgang Walther 94f0548344 chore(deps): update ubuntu:noble docker digest to 2e863c4 2024-06-19 19:22:47 +02:00
Wolfgang Walther 16d0e1ca8c fix: Treat pre-release and docs versions correctly for new release workflow
Since we changed our release workflow, we have adjusted:
- the docs to use postgrest.org/en/v12/ -style URLs, i.e. only using the
major component.
- the pre-release / devel versions to contain only two instead of four
version parts, i.e. currently 12.3.
2024-06-19 08:42:34 +02:00
Wolfgang Walther 9657d46c42 docs: Fix linkcheck
Some URLs are still forbidden for our linkcheck tool, so disabling them
again.

Others are permanently redirected, so adjusting them.
2024-06-19 08:40:58 +02:00
renovate[bot]andWolfgang Walther 70e07ccbc6 chore(deps): update dependency urllib3 to v2.2.2 2024-06-17 21:04:03 +02:00
renovate[bot]andWolfgang Walther cc5c4ae5ef chore(deps): update codecov/codecov-action action to v4.5.0 2024-06-13 19:51:15 +02:00
renovate[bot]andWolfgang Walther af8b62ba10 chore(deps): update all dependencies 2024-06-13 08:46:23 +02:00
Laurence Isla d4e7d23268 docs: fix example of listener failure on read replicas 2024-06-12 19:46:23 -05:00
Laurence Isla 4e084b664c docs: clarify what is logged when "log-level=debug" 2024-06-12 18:30:19 -05:00
Laurence Isla 91024b6eab docs: add missing logs to stderr
- Schema cache stats are now logged to stderr
- Log when the LISTEN channel gets a notification
2024-06-12 18:30:19 -05:00
Laurence IslaandSteve Chavez 0e4fcd7387 docs: add "Listener" page
Co-authored-by: Steve Chavez <stevechavezast@gmail.com>
2024-06-12 18:30:19 -05:00
Wolfgang Walther 49a7aa9933 bump docs version to 12.2 2024-06-12 07:47:17 +02:00
steve-chavez ec89f6b90c bump version to 12.2.0 2024-06-11 09:57:05 -05:00
steve-chavez 82aa58a08f docs: deprecate EOL pg versions 2024-06-11 09:43:09 -05:00
Laurence Isla db85faf3ed docs: wrap in double quotes the filters with reserved characters in logical operators 2024-06-05 17:59:44 -05:00
Wolfgang Walther a2d00e305a nix: Make postgrest-release work on remotes without .git suffix 2024-06-05 21:32:41 +02:00
steve-chavez 4beac10d3d prevent GSSAPI error between Listener and pool
Brings back the the signaling/waiting between the connection pool and
the Listener.

Prevents the GSSAPI error shown on https://github.com/PostgREST/postgrest/issues/3569
2024-06-05 13:58:34 -05:00
Wolfgang Walther 70a8a80491 Revert "fix: Build static postgrest with GSSAPI support"
This reverts commit c94aa9ccd9.
2024-06-05 19:59:07 +02:00
Wolfgang Walther b4d235f72a nix: refactor to remove TODO
We have meanwhile received the commit in question.
2024-06-05 19:53:29 +02:00
steve-chavez 1a8b6972a8 correct exponential backoff on Listener
Clears the limitation mentioned on

https://github.com/PostgREST/postgrest/pull/3536

The Listener no longer uses the https://hackage.haskell.org/package/retry
package and instead uses a much simpler IORef in AppState for the
delays.

Additionally it no longer uses exception throwing/catching, which
is rather messy and brings some
concerns(https://github.com/PostgREST/postgrest/issues/3569#issuecomment-2146013327).
2024-06-05 08:52:18 -05:00
Laurence Isla aaf2d2e430 docs: add example for double embedding when doing OR filtering across embeds 2024-06-04 16:51:28 -05:00
Joel JakobssonandGitHub a46bea16e2 nix: fix slocat overlay with nix 2.22
This seems to happen on nix 2.22 only, v2.21 in CI and v2.20 locally work fine. The error is:

vendor folder is empty, please set 'vendorHash = null;' in your expression
For full logs, run 'nix-store -l /nix/store/kxnnr344n7gsxzc6kycj19hs19rvddjj-slocat-go-modules.drv'.
error: 1 dependencies of derivation '/nix/store/x9w480k36a11i99m6zp12d5cjijsn3lm-slocat.drv' failed to build

Since the slocat module doesn't actually have any dependencies, this shouldn't matter much.
2024-06-03 10:24:35 +02:00
Laurence Isla 50b2d302d0 docs: use "curl --get" for better readability when necessary 2024-05-31 20:24:06 -05:00
steve-chavez 82a43c2767 nix: postgrest-gen-ctags use haskdogs 2024-05-25 15:21:44 -05:00
steve-chavez a51a74b3c1 docs: shorten CLI 2024-05-24 18:05:45 -05:00
steve-chavez 1c371d7340 docs: clarify architecture 2024-05-24 18:05:45 -05:00
steve-chavez 30ca64d849 docs: improve observability 2024-05-24 18:05:45 -05:00
Laurence Isla 9c165e3edb fix: log connection pool events on log-level="debug" instead of "info" 2024-05-24 17:19:31 -05:00
Laurence Isla c8612f1df1 test: use only the first line in the logs to check the server version 2024-05-24 17:19:31 -05:00
steve-chavez da9e497ef1 changelog: add architecture doc 2024-05-23 19:34:42 -05:00
steve-chavez 47e9a2d134 refactor: Listener to own module 2024-05-23 19:34:42 -05:00
Laurence Isla 4e0ffa6d0a changelog: fix link for deprecated feature 2024-05-22 19:16:01 -05:00
Laurence Isla f5767b8d86 docs: add "config" and "schema_cache" endpoints to the admin server 2024-05-22 19:16:01 -05:00
Taimoor ZaeemandSteve Chavez 8cbcf9867b feat: add config db-hoisted-tx-settings to allow only hoisted function settings 2024-05-21 19:50:03 -05:00
Taimoor ZaeemandSteve Chavez a1582a6136 test: clean test_role_settings in io-tests 2024-05-21 19:50:03 -05:00
Laurence IslaandSteve Chavez 1ca5b6f6ba docs: ignore linkcheck for blog.frankel.ch 2024-05-21 17:23:11 -05:00
Laurence IslaandGitHub aea563bd82 fix: remove verbosity from some error logs
Error logs starting with "An error occured..." are replaced with "Failed to..."
2024-05-21 16:44:28 -05:00
Laurence IslaandGitHub 5d3d09923f refactor: unDRY PGRST prefix in errors for better search/grep 2024-05-21 14:34:00 -05:00
Wolfgang WaltherandWolfgang Walther 71711bb935 ci: Prevent caching cabal and stack cache in PRs
This was supposed to happen in c4b0bd34 and 279febe2, but somehow didn't
work, yet.
2024-05-21 20:44:41 +02:00
Wolfgang Walther ad5bb38d70 ci: Don't cancel previous runs for tag pipelines
Those create annoying "cancelled" notifications which looks like CI on
main was failing. It's not, though.

By just disabling the cancel-in-progress setting, but keeping the group
intact, this should queue multiple tag jobs / tag workflows behind each
other and still avoids the underlying problem which occurs when running
them in parallel.
2024-05-21 20:43:18 +02:00
Wolfgang Walther 89eae607f5 ci: Run build workflow in PRs which change composite actions
This should have been added in c4b0bd34 for cache-on-main and way before
that for artifact-from-cirrus.
2024-05-21 19:57:39 +02:00
Wolfgang Walther dcfc6673b7 ci: Fix out-of-sync GHC version for stack jobs 2024-05-21 19:39:15 +02:00
Laurence IslaandGitHub 7671d63f06 refactor: add isParent flag to O2O relationships
It allows to identify the side with the FK when isParent == False
2024-05-21 12:11:27 -05:00
Laurence Isla 04d6f41f45 chore: update commit prefix info in the PR template 2024-05-21 09:03:12 -05:00
Taimoor ZaeemandSteve Chavez 5cc32c7f87 fix: fix incorrect 413 error on pg 54* errors 2024-05-20 18:59:33 -05:00
renovate[bot]andWolfgang Walther 11c9e8dac9 chore(deps): update cachix/cachix-action action to v15 2024-05-20 19:26:45 +02:00
renovate[bot]andWolfgang Walther b8436fd397 chore(deps): update codecov/codecov-action action to v4.4.1 2024-05-20 19:26:18 +02:00
renovate[bot]andWolfgang Walther 4156070838 chore(deps): update haskell-actions/setup action to v2.7.3 2024-05-20 19:26:07 +02:00
Wolfgang WaltherandWolfgang Walther 9e6a89ffb8 ci: Install GHC/stack via haskell-actions/setup consistently
This action makes sure to always have the correct GHC and/or stack
version installed in all environments. This solves problem where ghc or
stack might not be available on newer macos images anymore or where
ghcup is not available by default on our new custom github runner on
arm.
2024-05-20 15:43:00 +02:00
Wolfgang WaltherandWolfgang Walther d08e5959a0 ci: Reduce stack cache size
This removes the GHC install from stack caches to reduce size.
2024-05-20 15:43:00 +02:00
Wolfgang WaltherandWolfgang Walther 279febe26b ci: Split cabal and stack work caches from regular cache
This is a first step to split up the cabal and stack caches in separate
pieces. Here we split the work folder, which just contains the
postgrest-specific build artifacts, into a separate cache.

More fine-grained caching should give us better cache hits and much
fewer upload size in the regular case, improving CI performance.

Since the work file caches are very small (about 30-40 MB) they are
cached for PRs, too. This will allow the majority of PRs, which only
change source code files, but no dependencies, to still have cached
their build files for additional commits.
2024-05-20 15:43:00 +02:00
Wolfgang WaltherandWolfgang Walther c4b0bd347b ci: Only save caches on main and release branches
This restores caches on all branches and pull requests, but only stores
them on the main branch and release branches. This prevents those caches
from being evicted early when we hit the 10 GB limit quickly.
2024-05-20 15:43:00 +02:00
steve-chavez 7e61c9deb0 feat: force read-write for listener connection 2024-05-19 23:14:19 -05:00
steve-chavez 3cf565614d fix: listener retries with exponential backoff
Also corrects the admin ready response which now considers the listener
state.
2024-05-19 20:48:59 -05:00
steve-chavez bfa4e1bedb test: isolate pg_terminate_backend to appname
The pg_terminate_backend done in the io test:

`test_fail_with_automatic_recovery_disabled_and_terminated_using_query`

Can affect other connections.
2024-05-19 19:58:27 -05:00
steve-chavez d5a4c5609e refactor: greppable 57P01 error code 2024-05-19 19:58:27 -05:00
renovate[bot]andWolfgang Walther 80783a7ee8 chore(deps): update actions/checkout action to v4.1.6 2024-05-19 21:24:42 +02:00
steve-chavez c8ba505b99 docs: linkcheck ignore patreon 2024-05-19 13:44:23 -05:00
steve-chavez ae91fd89b3 test: assert empty response text on 204 2024-05-19 13:44:23 -05:00
steve-chavez 756aad7827 fix: listener silent fail on replica
Update hasql-notifications to include the fix on
https://github.com/diogob/hasql-notifications/issues/24.

Which now reveals the following error:

```
$ postgrest-with-postgresql-16 --replica -f test/spec/fixtures/load.sql postgrest-run

17/May/2024:18:35:38 -0500: Successfully connected to PostgreSQL 16.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 13.2.0, 64-bit
17/May/2024:18:35:38 -0500: Could not listen for notifications on the "pgrst" channel. ERROR:  cannot execute LISTEN during recovery
17/May/2024:18:35:38 -0500: Retrying listening for notifications...
```

This is still not good because the LISTEN channel will be retried
forever without a backoff.
2024-05-18 23:33:04 -05:00
steve-chavez aa75412932 nix: PGRST_DB_URI preference for tmp db replica
When using `postgrest-with-postgresql-* --replica`, the PGRST_DB_URI
will set the replica host as preference. This to be able to run
quick manual tests with postgrest running on a replica.
2024-05-18 23:33:04 -05:00
Laurence IslaandWolfgang Walther ea4d1596b7 ci: fix release not executing when skipping CI for docs and tests 2024-05-17 08:09:19 +02:00
steve-chavez 33b6ba8199 refactor: move checkIsFatal logic to usePool
The fatal logic is now inside `usePool`. It centralizes the
logic which is better for Locality of Behavior.

Removes:

- The need to do checkIsFatal on other parts of the code
- SCFatalFail/ConnFatalFail states which are no longer needed.
2024-05-16 17:40:25 -05:00
renovate[bot]andWolfgang Walther 9d763aef00 chore(deps): update codecov/codecov-action action to v4.4.0 2024-05-15 09:20:39 +02:00
steve-chavez d25df459ea feat: add metric label for scache load
localhost:3001/metrics now includes:

pgrst_schema_cache_loads_total{status="FAIL"} 352.0
pgrst_schema_cache_loads_total{status="SUCCESS"} 3.0

This allows testing the failure case on:

https://github.com/PostgREST/postgrest/issues/3424#issuecomment-2104904910
2024-05-14 17:57:21 -05:00
steve-chavez 05447bae33 nix: add postgrest-gen-jwt/secret for manual tests
```
$ postgrest-gen-secret
uMd97XSQzNkA1CWhMZ7u88Pj0RNyhrpo

$ postgrest-gen-jwt postgrest_test_author
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA
```

Also modifies postgrest-run to include a default PGRST_JWT_SECRET for
quicker manual tests.
2024-05-13 12:37:08 -05:00
Wolfgang WaltherandWolfgang Walther f6b2aa5a5d chore(deps): Update stackage extra deps 2024-05-13 08:08:18 +02:00
Wolfgang WaltherandWolfgang Walther 923a271105 chore(deps): Update stackage snapshot to lts-22.20
The freebsd build is kept at 21.7 / GHC 9.4.5, because no newer GHC
versioin is supported here.
2024-05-13 08:08:18 +02:00
Wolfgang Walther b8fe512def ci: Avoid trying to upload loadtest reports for tag pipelines
In this case the loadtest doesn't run anymore, so the job would fail.
2024-05-12 15:28:13 +02:00
Wolfgang Walther 271b3b273d ci: Disable tagging releases in forks 2024-05-12 15:10:28 +02:00
Wolfgang Walther 5c040e74f5 ci: Prevent running check, docs and test suites on tags
This doesn't make sense, because each tag is only pushed when those
pipelines have already passed. Thus, we can save time and avoid wasting
resources and don't run those again.
2024-05-12 15:01:20 +02:00
Wolfgang Walther 4a3fdc175c ci: Skip release jobs on outdated tags
This happens a commit is pushed to main while the pipelines have not
finished for the previous commit. In this case the devel-tag pipelines
will run concurrently, leading to unpredictable results for the devel
release.
2024-05-12 14:58:27 +02:00
Wolfgang Walther aef29d49ba docs: Mark db_tx_end as db-configurable 2024-05-12 11:53:59 +02:00
Wolfgang Walther c6f152f5b4 refactor: Remove left-over raw_media_types from Database.hs
This was removed in #2825.
2024-05-12 11:53:45 +02:00
Taimoor ZaeemandWolfgang Walther 7a5079542c docs: update docs for pg error 53400 2024-05-12 11:47:05 +02:00
Wolfgang WaltherandWolfgang Walther 71885bdba6 test: Avoid freeport() collisions in io tests
It's very unlikely, but it can (and did) happen that both the server and
admin ports have the same number returned from freeport(). This then
leads to a situation where PostgREST will accept the same port in both
cases, because the host "localhost" will allow binding to ipv4 or ipv6
respectively. This will make the IO tests fail.

This change makes sure that the admin port will never be the same as the
server port and thus avoids this problem.
2024-05-12 11:45:06 +02:00
Wolfgang WaltherandWolfgang Walther 8392357863 test: Fix internal_schema_cache_sleep after 747c78f6
The $subject commit broke internal_schema_cache_sleep for other tests.
This reverts the order change, but keeps the scaling by x1000 to ms and
thus changes other users of this setting to the new scale.
2024-05-12 11:44:43 +02:00
Laurence IslaandSteve Chavez 334c2710f6 changelog: update to 12.0.3 2024-05-11 13:30:50 -05:00
Wolfgang Walther 07222cff7b chore: Restrict macos to v12 2024-05-10 08:19:29 +02:00
David BaynardandWolfgang Walther 575dd4cf70 nix: Make default.nix extensible
Moving values defined with `let` to the function arguments (with
defaults) means other consumers of `default.nix` can customize these
values.

One example is a `flake.nix`, which can then supply the `nixpkgs` input.
2024-05-09 22:23:06 +02:00
Wolfgang Walther d03b321659 ci: Actually pass GHC_VERSION to arm build script 2024-05-09 21:58:37 +02:00
Wolfgang Walther 5580fe0040 ci: Make arm scripts fail on error 2024-05-09 21:46:10 +02:00
Wolfgang Walther 7d713b8c53 ci: Tag arm docker image properly for releases 2024-05-09 21:46:10 +02:00
Wolfgang Walther 2cb45bd5f8 ci: Extract changelog properly for releases 2024-05-09 21:46:10 +02:00
Andrei DziahelandWolfgang Walther 3026c1f308 fix: Parse accept header case-insensitively
The Accept header is parsed case-insensitively now, introducing proper
handling of media types specified in upper- and/or mixed-case.

Fixes #3478
2024-05-09 19:30:42 +02:00
Wolfgang Walther 1fa35cb3b8 test: Fix coverage & style check from c4295b3d 2024-05-09 18:50:00 +02:00
Wolfgang Walther 01a56db7d8 test: Make unicode insert test work in parallel mode
Changing the PK here will avoid duplicate conflicts with another test.

References #1799
2024-05-09 18:05:44 +02:00
Wolfgang Walther 577a7c7598 test: Move limited delete/update tests into separate spec file
This potentially allows to run the remaining tests in those files in
parallel mode.

References #1799
2024-05-09 18:05:44 +02:00
Wolfgang Walther c4295b3d63 test: Make PgSafeUpdateSpec parallel-ready 2024-05-09 18:05:44 +02:00
Wolfgang Walther aa94e436fa test: Missing space 2024-05-09 18:05:44 +02:00
Wolfgang Walther cf7a789e9e test: Improve failing test output for requestMutation 2024-05-09 18:05:44 +02:00
Wolfgang Walther a7ed5db78a test: Sort test suites in spec/Main.hs 2024-05-09 18:05:44 +02:00
Wolfgang WaltherandWolfgang Walther d903a8a115 nix: Adjust postgrest-release to new release workflow
This changes the postgrest-release tool to work with our new workflow.
It can be run on main and the v* release branches. When on a release
branch, it will bump a patch version and push to that branch only.

When on main, it will bump a minor version by default. To bump a major
version, pass --major. This first bump will be force-pushed to the
v<major> branch. A second bump to the current development version will
then be pushed to the main branch.

The tool will not tag commits anymore - this happens in CI
automatically.

References #3113
Resolves #3082
2024-05-09 18:05:04 +02:00
Wolfgang Walther a427fb67f6 ci: Fetch tags before checking whether tag exists 2024-05-09 14:53:38 +02:00
Wolfgang Walther 3afa5f6a36 ci: Move docker-hub-readme.md to base folder
This is not related to nix tooling anymore, because a github action
without any nix tooling is updating this now.
2024-05-09 14:35:52 +02:00
renovate[bot]andWolfgang Walther fdcadb3d53 chore(deps): update actions/checkout action to v4.1.5 2024-05-09 14:08:51 +02:00
Wolfgang WaltherandWolfgang Walther 747c78f6f4 test: Prevent test_admin_ready_includes_schema_cache_state from timing out
By increasing the delays in this test by factor 400x, postgrest will not
swamp pg with connection retries after the failed schema cache anymore.

This would happen because there is no backoff included after fatal
errors. Once it does, the io tests hang indefinitely in CI.
2024-05-09 13:36:03 +02:00
Wolfgang WaltherandWolfgang Walther e96e16fa27 test: Reset statement timeout after each test
The statement timeout needs to be cleaned up after each test that
modifies it instead of before the test. Otherwise the changed timeout
leaks into other tests.
2024-05-09 13:36:03 +02:00
steve-chavez 0060abeb01 feat: /live and /ready respond with 500 on failure
503 is still used by /ready to indicate a transient state
that can be recovered from.
2024-05-08 17:19:48 -05:00
steve-chavez f9e9740999 nix: add postgrest-ctags command
Generates ctags for Haskell and Python code.
2024-05-08 12:27:26 -05:00
steve-chavez 1b584f7e9c refactor: is ready Admin logic to AppState 2024-05-08 11:27:58 -05:00
Wolfgang WaltherandWolfgang Walther 1374178f27 ci: Improve performance for nix jobs in CI
Defaulting to max-jobs = auto should improve build times by using more
cores.

Setting always-allow-substitutes to true should cause all nix
derivations to be cached on cachix, which should improve performance of
the MacOS job dramatically, when no rebuilds need to happen.
2024-05-07 14:42:12 +02:00
Wolfgang Walther cb6151eb1b ci: Make artifact-from-cirrus action succeed when cirrus job doesn't start up in PR 2024-05-07 08:29:31 +02:00
Wolfgang Walther b006016d07 ci: Make "release / tag" job detect existing tags
The release / tag job has logic to decide whether to push a new tag on
stable branches, which depends on the all the tags being fetched. The
checkout action doesn't do that by default, so enable that.
2024-05-07 08:09:00 +02:00
steve-chavez df9b373465 docs: better place for application_name 2024-05-06 11:12:45 -05:00
steve-chavez b34c00c522 changelog: add missing entry for 3184 2024-05-06 11:12:45 -05:00
steve-chavez 1d4f31514f changelog: move 3340 from fixed to added
Since it was a feature
2024-05-06 11:12:45 -05:00
steve-chavez 7e91e5311d fix: not adding application_name on all URIs 2024-05-06 11:12:45 -05:00
Taimoor ZaeemandSteve Chavez 21bc48ad9a fix: fix wrong 503 Service Unavailable on pg error 53400 2024-05-06 07:54:11 -05:00
renovate[bot]andWolfgang Walther cabe744f01 chore(deps): update ubuntu docker tag to v24 2024-05-05 18:23:53 +02:00
Wolfgang Walther 463dfb552d chore(deps): update actions/checkout hash for release/prepare job
Accidentally committed an outdated version, this aligns it with all the
other references to the same action.
2024-05-05 17:48:44 +02:00
Wolfgang Walther a57d12b102 ci: Use the new DOCKER_ vars for docker-arm job 2024-05-05 17:11:22 +02:00
Wolfgang Walther d9ba9a8208 ci: Avoid devel release failure when no assets to clean up exist 2024-05-05 14:35:40 +02:00
Wolfgang Walther 8433f9812b ci: Replace assets of existing devel release properly 2024-05-05 13:38:58 +02:00
Wolfgang Walther c67f1c398c ci: Fix docker release job after 2f98d837 2024-05-05 13:33:48 +02:00
Wolfgang Walther 2f98d837ff ci: Push docker hub description automatically on main branch 2024-05-04 21:55:52 +02:00
Wolfgang Walther eec35d4569 ci: Avoid recreating devel release
Instead, the existing release is edited, which avoids notifications
for pre-releases.
2024-05-04 21:54:46 +02:00
Wolfgang Walther 9fe90bf9a8 ci: Fix pushing of devel-arm docker tag 2024-05-04 21:53:36 +02:00
Wolfgang Walther 58d8133454 ci: Enable docker push for releases 2024-05-04 21:14:40 +02:00
Wolfgang Walther fe0f2f708a ci: Use "devel" as the pre-release name instead of the commit title 2024-05-04 21:14:23 +02:00
Wolfgang WaltherandWolfgang Walther dd8d51ab71 ci: Automate patch releases and pre-releases
This work by automatically pushing a new tag on main and release
branches after each commit. The tag will be "devel" on main and the
version from postgrest.cabal for release branches. The release
workflow then runs as a tag pipeline, making the actual release.

For release branches, the tag will only be created if a tag for this
version doesn't exist, yet. This means to actually make a new patch
release, we still need to bump the version in postgrest.cabal. We
can automate this later as part of our backport-bot.

Resolves #2006
Resolves #2997
2024-05-04 20:42:45 +02:00
Wolfgang Walther cdcab34852 nix: Make postgrest-lint fail on dead nix code 2024-05-04 20:34:59 +02:00
Wolfgang Walther 1ca2d1f8be ci: Refactor get_cirrusci_freebsd script to GitHub action
This should make it more reliable and also easier to re-use, if we need
to.

Resolves #2555
2024-05-04 14:56:57 +02:00
Wolfgang Walther 5aa62d944d ci: Force running FreeBSD build in tag and push pipelines
This now behaves similar to other CI build jobs, which always run on the
main branches, but only conditionally on PRs, depending on which files
changed.
2024-05-04 14:56:57 +02:00
renovate[bot]andWolfgang Walther 5c29742d7f chore(deps): update nixbuild/nix-quick-install-action action to v28 2024-05-04 13:35:13 +02:00
renovate[bot]andWolfgang Walther cc7165ca10 chore(deps): update codecov/codecov-action action to v4.3.1 2024-05-04 12:21:53 +02:00
renovate[bot]andWolfgang Walther 277342bf8c chore(deps): update ubuntu:jammy docker digest to a6d2b38 2024-05-04 12:21:37 +02:00
steve-chavez d9a51f23ce test: sanity tests for primary and replica
* new --replica option to `postgrest-with-postgresql-*`
* new command `postgrest-test-replica`
* new sanity tests on test_replica.py
* add postgrest-test-replica to postgrest-check and postgrest-coverage
2024-04-30 18:35:40 -05:00
steve-chavez cdb877135b test: flush stdout so readline doesn't hang 2024-04-30 13:52:51 -05:00
Taimoor ZaeemandSteve Chavez 7e5fd317e6 docs: add docs page for CLI 2024-04-29 12:51:54 -05:00
Laurence IslaandGitHub 40bd9a7769 ci: DRY the cleanup job for ARM servers 2024-04-29 12:20:00 -05:00
renovate[bot]andWolfgang Walther 5e41121551 chore(deps): update ubuntu:jammy docker digest to 6d7b5d3 2024-04-26 08:34:18 +02:00
renovate[bot]andWolfgang Walther 46d8dfde42 chore(deps): update actions/checkout action to v4.1.4 2024-04-26 08:31:33 +02:00
Laurence Isla 85a4e35a2d docs: fix http status for PGRST121 error 2024-04-24 15:04:35 -05:00
renovate[bot]andWolfgang Walther 359a14533b chore(deps): update actions/download-artifact action to v4.1.7 2024-04-24 20:53:56 +02:00
Laurence IslaandGitHub 69bbce5b32 feat: improve PGRST121 error message
* Clarify the message field
* Show failed MESSAGE or DETAIL in the the PGRST121 error's details field
* Show the correct JSON format in the hint field
2024-04-24 13:33:10 -05:00
steve-chavez 3eff4670f0 docs: metrics for schema cache and connection pool 2024-04-23 19:08:37 -05:00
steve-chavez 357400b2b8 feat: schema cache metrics 2024-04-23 19:08:37 -05:00
steve-chavez 653c7955b2 feat: connection pool metrics in admin server 2024-04-23 19:08:37 -05:00
steve-chavez 29cd7d195c nix: add instructions for haskell-packages.nix 2024-04-23 19:08:37 -05:00
Laurence IslaandGitHub e788776ec3 ci: clean ARM server even when previous steps or jobs fail 2024-04-23 16:34:55 -05:00
steve-chavez 3e615bd0d9 feat: add log-level=debug 2024-04-22 21:36:29 -05:00
renovate[bot]andWolfgang Walther bddfa2782d chore(deps): update actions/checkout action to v4.1.3 2024-04-22 21:30:23 +02:00
Wolfgang Walther 6858693291 ci: Be explicit about the version of linux and windows runner images
Using the -latest tag is potentially prone to errors, because an update of the tag
could break our CI. This recently happend with macos-latest, which we downgraded
to macos-12 earlier.

Using an explicit version reference makes this problem much less likely - in fact
renovate will pick up new versions once they exist and will suggest updates for it.
Thus, we will see the failures in a related PR instead of randomly everywhere.
2024-04-22 21:20:30 +02:00
renovate[bot]andWolfgang Walther dcb9f92b80 chore(deps): update actions/upload-artifact action to v4.3.3 2024-04-22 21:14:58 +02:00
renovate[bot]andWolfgang Walther 6a38cc098d chore(deps): update actions/download-artifact action to v4.1.6 2024-04-22 21:14:44 +02:00
Wolfgang WaltherandWolfgang Walther 81ceac8ba3 ci: revert to macos-12
GitHub Actions updated the latest macos image to macos-14 [1], which made both
of our macos build jobs fail.

This reverts to macos-12, which should fix CI for the moment. We can then look
into migrating to macos-14 explicitly.

[1]: https://github.blog/changelog/2024-04-01-macos-14-sonoma-is-generally-available-and-the-latest-macos-runner-image/
2024-04-22 21:11:03 +02:00
Taimoor ZaeemandSteve Chavez 88abf600c4 fix: fix wrong http status on pg error 42P17 infinite recursion 2024-04-22 13:40:07 -05:00
Wolfgang WaltherandWolfgang Walther 80f83f0366 nix: Update to latest nixpkgs#master 2024-04-20 17:06:29 +02:00
Wolfgang WaltherandWolfgang Walther b6a50ab8ed nix: Allow changing to a fork in nixpkgs-version.nix 2024-04-20 17:06:29 +02:00
Wolfgang Walther 87a463f857 test: fix broken io tests after last commit
Forgot to update the snapshots.
2024-04-20 16:03:53 +02:00
Wolfgang Walther ed407350ad fix: hoist function settings with memory units properly
f9ee1f7e introduced the hoisting of function settings as transaction-scoped
settings. However, this currently doesn't work with memory units, which are
case-sensitive according to the docs [1]. This removes the lowercasing of
values to make them work.

This is not added to the CHANGELOG, because this feature was not released, yet.

[1]: https://www.postgresql.org/docs/current/config-setting.html#CONFIG-SETTING-NAMES-VALUES
2024-04-20 13:58:04 +02:00
renovate[bot]andWolfgang Walther de788c9832 chore(deps): update ubuntu docker tag to v22 2024-04-20 12:39:22 +02:00
Wolfgang Walther 07dc37e66f chore: limit docutils to <0.21.0
sphinx-rtd-theme currently does not support docutils 0.21.x.

This restriction can be lifted once the upstream issue has been resolved:
https://github.com/readthedocs/sphinx_rtd_theme/issues/1557
2024-04-20 12:38:24 +02:00
renovate[bot]andWolfgang Walther c2994fb0b1 chore(deps): update ubuntu:focal docker digest to 71b82b8 2024-04-20 12:33:30 +02:00
renovate[bot]andWolfgang Walther 6863fe1e26 chore(deps): update actions/download-artifact action to v4.1.5 2024-04-20 12:33:06 +02:00
renovate[bot]andWolfgang Walther dc6399abad chore(deps): update actions/upload-artifact action to v4.3.2 2024-04-20 12:32:55 +02:00
Laurence IslaandSteve Chavez 0d13b842a6 fix: OpenAPI now tags a FK correctly on O2O relationships 2024-04-18 17:08:14 -05:00
steve-chavez 1bf0c54dd6 feat: log connection pool events on log-level=info 2024-04-15 18:31:51 -05:00
Steve ChavezandGitHub 9d1dc783bf test: use postgrest.read_stdout in io tests (#3412)
It's easier to maintain this way in case there are new log lines.
2024-04-15 13:51:23 -05:00
steve-chavez 69c6ce9c38 refactor: use LogLevel in Logger
* remove Logger dependency on Auth.
2024-04-14 20:10:01 -05:00
steve-chavez c57ec52229 refactor: make stdout explicit on Logger
Otherwise it's hard to know we're logging to stdout.
2024-04-14 20:10:01 -05:00
Taimoor ZaeemandSteve Chavez 973201a8d3 fix: remove rejected mediatype application/vnd.pgrst.object+json from response 2024-04-13 16:07:38 -05:00
steve-chavez fbc4d565ca refactor: move debounce from AppState to Logger
Will allow to capture accurate timeout metrics.
2024-04-12 14:29:39 -05:00
steve-chavez 2de32fc108 refactor: observation handler to AppConfig
With this:

- Is no longer necessary to pass observer as an argument
  to every function that needs observations.
- We can invoke the observer on every function that uses AppConfig.
  However it'd be better to just call the observer in the upper modules
  (like on App.hs).
2024-04-12 14:29:39 -05:00
Laurence IslaandGitHub 460259548d perf: fix space leaks by downgrading fuzzyset to v0.2.4 2024-04-11 14:13:20 -05:00
steve-chavez b88191299f docs: remove schema cache dep from Query 2024-04-10 19:35:23 -05:00
Laurence Isla 4bcd6725fe chore: update sponsor logos 2024-04-10 18:37:57 -05:00
Laurence Isla 70396d3f6c docs: add dark mode
- Uses sphinx-rtd-dark-mode for sphinx-rtd-theme
- Adds dark mode logos for sponsors
2024-04-10 18:37:57 -05:00
steve-chavez c9136816a2 docs: move ARCHITECTURE.md to architecture.rst 2024-04-10 15:51:08 -05:00
steve-chavez 4428253efe docs: move health_check.rst to admin_server.rst 2024-04-10 15:51:08 -05:00
steve-chavez 47a4e2bfd0 docs: add proxy and config reloading to arch 2024-04-10 13:57:49 -05:00
renovate[bot]andWolfgang Walther 5880e62d7a chore(deps): update codecov/codecov-action action to v4.3.0 2024-04-10 09:10:27 +02:00
steve-chavez 2772b78013 docs: add config/cli/developer to arch 2024-04-08 15:51:30 -05:00
steve-chavez b91908b749 docs: add architecture description 2024-04-08 13:50:00 -05:00
steve-chavez ab73624366 docs: add architecture diagram 2024-04-08 11:57:03 -05:00
steve-chavez 5ab317caa0 refactor: one entrypoint for Plan/Response/Query
- deduplicates timing calculation for the different steps
- enabling query logging later on will be simpler
2024-04-04 08:58:55 -05:00
renovate[bot]andWolfgang Walther a66738b892 chore(deps): update codecov/codecov-action action to v4.2.0 2024-04-04 07:17:26 +02:00
steve-chavez 3d55f77bae Revert "fix: slow responses on schema cache reload"
This reverts commit 727ef465c1.

Also documents requests waiting for the schema cache.
2024-04-02 23:15:09 -05:00
steve-chavez d7c64a93f8 docs: update schema cache 2024-04-01 19:03:14 -05:00
steve-chavez 2543b8d724 fix: clarify PGRST204 error message 2024-04-01 19:03:14 -05:00
Wolfgang Walther 6de3ba543d nix: Use minimal set of texlive dependencies for docs-render 2024-03-31 22:05:02 +02:00
steve-chavez 06ff56d323 refactor: move isolation/settings logic to Plan.hs 2024-03-28 18:31:42 -05:00
steve-chavez c33ca4e60c refactor: dry timings calculation for openapi 2024-03-28 18:31:42 -05:00
steve-chavez b75cc853b4 chore: fix compilation
The App.hs module was missing NamedFieldPuns.
2024-03-27 19:18:17 -05:00
steve-chavez 745e7868b0 refactor: dry some timings calculation 2024-03-27 18:22:34 -05:00
Laurence Isla 378c11104b test: fix some in-db config values
To correctly test in-db override of config file values, the former must be different from the latter.
2024-03-27 15:59:35 -05:00
Laurence Isla 428a6fef63 fix: in-db config values not loading for pgrst.server_trace_header and pgrst.server_cors_allowed_origins 2024-03-27 15:59:35 -05:00
renovate[bot]andWolfgang Walther d02540ac44 chore(deps): update codecov/codecov-action action to v4.1.1 2024-03-26 19:49:51 +01:00
Laurence IslaandGitHub 3f162535b8 nix: add example on how to use a library locally 2024-03-26 11:39:07 -05:00
steve-chavez a5bb20bbf8 refactor: remove unreacheable 404 2024-03-25 18:17:01 +01:00
renovate[bot]andWolfgang Walther f1f01f1f5c chore(deps): update actions/cache action to v4.0.2 2024-03-19 21:58:16 +01:00
Wolfgang Walther ee359192fa ci: Fix duplicated version number for actions/cache 2024-03-19 21:57:30 +01:00
steve-chavez 941ea0f929 test: notify do nothing 2024-03-19 13:22:51 +03:30
steve-chavez ee8b3ef8fe fix: log on LISTEN notification 2024-03-19 13:22:51 +03:30
Ian WijmaandGitHub 47b70b8329 chore: fix link to docs in readme
Fixed the link to the archived documentation repo.
2024-03-16 11:41:44 +01:00
steve-chavez 727ef465c1 fix: slow responses on schema cache reload 2024-03-15 11:53:29 -05:00
renovate[bot]andWolfgang Walther 210cded560 chore(deps): update nixbuild/nix-quick-install-action action to v27 2024-03-15 17:13:24 +01:00
steve-chavez 11d8da046c fix: incorrect /ready response on slow schema load 2024-03-15 11:03:01 -05:00
steve-chavez 4b289b1c97 test: requests wait for schema cache load
* nix: add postgrest-test-big-schema command
2024-03-15 06:18:26 -05:00
steve-chavez 92ac7e574e chore: clarify concurrent notifications test 2024-03-14 23:17:05 -05:00
steve-chavez ec7ab271d6 chore: add postgrest roles to big_schema.sql 2024-03-14 11:21:17 -05:00
steve-chavez 4a2c851ae5 chore: update cabal/stack new hasql-notifications 2024-03-13 20:43:46 -05:00
steve-chavez 86e15dbb77 fix: upgrade hasql-notifications to show error 2024-03-13 11:14:11 -05:00
Steve ChavezandGitHub 00f5780415 fix: don't hide error on LISTEN channel failure (#3323) 2024-03-11 19:56:35 -05:00
Steve ChavezandGitHub 650249ed29 perf: remove json_typeof (#3316) 2024-03-08 16:02:28 -05:00
steve-chavez 9405a62de8 docs: update links to cache/config notify reload 2024-03-08 10:31:55 -05:00
steve-chavez 05cdbb34c2 test: insignificant JSON whitespace on writes 2024-03-07 17:14:16 -05:00
steve-chavez 8eb88ef218 test: reduce threshold on memory tests 2024-03-07 16:01:21 -05:00
Laurence IslaandWolfgang Walther cf7b9bad08 nix: only json output for postgrest-dump-schema 2024-03-07 16:50:14 +01:00
Laurence IslaandWolfgang Walther c276e9741e nix: fix postgrest-dump-schema with optional yaml output 2024-03-07 16:50:14 +01:00
renovate[bot]andWolfgang Walther 6a2677d985 chore(deps): update ubuntu:focal docker digest to 80ef4a4 2024-03-07 16:27:56 +01:00
Steve ChavezandGitHub 58999f5102 changelog: add how to detect o2o rels on v10.0.0 (#3312) 2024-03-06 20:21:58 -05:00
Steve ChavezandGitHub 2f91853cb1 docs: add index usage section (#3299) 2024-03-02 11:00:31 -05:00
Laurence IslaandWolfgang Walther b8b957667b docs: add enums to working with data types how-to 2024-03-02 12:14:13 +01:00
renovate[bot]andWolfgang Walther db56c3eecc chore(deps): update actions/download-artifact action to v4.1.4 2024-03-02 12:10:10 +01:00
Wolfgang Walther d5cb6b57ea chore: Prevent unnecessary rebases for renovate PRs
This saves a few CI cycles.
2024-03-01 08:57:47 +01:00
Wolfgang Walther f72b47c485 chore: Add full semver comment to used actions 2024-03-01 08:54:27 +01:00
renovate[bot]andWolfgang Walther 0eda5df644 chore(deps): update actions/cache digest to ab5e6d0 2024-03-01 08:11:53 +01:00
Steve ChavezandGitHub d3f15baa4a nix: add postgrest-profiled-run (#3292) 2024-02-29 16:44:10 -05:00
Wolfgang WaltherandWolfgang Walther 29ffb9329b ci: Build on FreeBSD only when build workflow runs
This prevents running the freebsd build when only tests or docs change.
2024-02-29 21:27:05 +01:00
Wolfgang Walther a1480c758e ci: Run postgrest-test-doctests without nix-shell
Resolves #3183
2024-02-27 10:02:42 +01:00
Laurence IslaandGitHub 2479e0d4a5 changelog: clarify breaking change about dropping legacy gucs 2024-02-26 20:13:28 -05:00
renovate[bot]andWolfgang Walther 4878719b90 chore(deps): update actions/download-artifact digest to 87c5514 2024-02-26 22:13:53 +01:00
Wolfgang Walther 629ace0103 ci: Replace actions cache for macos build job with smart cachix lookup 2024-02-26 22:06:01 +01:00
Wolfgang Walther 73199127bb chore: Remove cabal.project.non-nix
We don't have any source-repository-package stanzas in there anymore, so there's no
need to keep it around anymore.
2024-02-26 22:06:01 +01:00
Wolfgang Walther a090f28cea ci: Install only the required nix tools
A previous commit allowed to select each tool separately on the toolbox.

This commit makes use of that for CI to possibly speed up loading from cachix
a little bit. It will also cause fewer cache misses when nix code is changed.

Resolves #3183
2024-02-26 22:06:01 +01:00
Wolfgang Walther c7eb4036a1 nix: Export all tools on each toolbox
This allows targeting each tool separately for installs.
2024-02-26 22:06:01 +01:00
Wolfgang Walther 08901323a3 nix: Move parallelCurl to devTools
This is not a with-tool, because it doesn't wrap another command.
2024-02-26 22:06:01 +01:00
Wolfgang Walther 1db6c04a28 ci: Remove unused .github/release script 2024-02-26 22:06:01 +01:00
Wolfgang Walther e70f001cfc ci: Remove matrix build for GHC 9.4.8 via Cabal on Linux
This is to reduce storage requirements for GitHub Actions cache. We already build with GHC 9.4.x
via Nix on Linux x64, via stack on FreeBSD, MacOS and Windows and via Cabal on Linux ARM. That
should cover 9.4.x enough.
2024-02-26 22:06:01 +01:00
Wolfgang Walther 3b497a5db4 ci: Remove useless cache- prefix for cache names
This just makes the name longer than needed.
2024-02-26 22:06:01 +01:00
renovate[bot]andWolfgang Walther 5bf0b9ca14 chore(deps): update codecov/codecov-action action to v4.1.0 2024-02-26 22:00:48 +01:00
Wolfgang Walther e5aee49891 ci: Prevent Upload Reports job from running on release branches
This won't work, since the workflows on the backbranches are structured differently
and thus the job can't find the loadtest.md file anywhere.
2024-02-24 23:33:25 +01:00
renovate[bot]andWolfgang Walther 873ac6221e chore(deps): pin dependencies 2024-02-24 21:15:38 +01:00
renovate[bot]andWolfgang Walther f97c6e3db3 chore(deps): update dependency urllib3 to v2.2.1 2024-02-24 20:38:43 +01:00
Wolfgang WaltherandWolfgang Walther d6153be67a ci: Split Lint & Style from Test workflow
The Lint & Style job needs to run on all PRs, not only when something "test" related
changes. Otherwise not all workflow, nix or other files are style-checked and linted.
2024-02-24 20:38:25 +01:00
renovate[bot]andWolfgang Walther e6cde92f11 chore(deps): update dependency sphinxext-opengraph to v0.9.1 2024-02-24 20:01:04 +01:00
renovate[bot]andWolfgang Walther f7879bd4b1 chore(deps): update dependency docutils to v0.20.1 2024-02-24 20:00:51 +01:00
Wolfgang WaltherandWolfgang Walther 11accb760a ci: Pass cachix token to all nix jobs 2024-02-24 19:59:46 +01:00
Wolfgang WaltherandWolfgang Walther 44e041282c ci: Switch action-get-latest-tag to github-action-get-previous-tag
The former is not maintained anymore and produces deprecation warnings in CI.
2024-02-24 19:59:46 +01:00
renovate[bot]andWolfgang Walther f2483dc722 chore(deps): update codecov/codecov-action action to v4 2024-02-24 18:41:06 +01:00
renovate[bot]andWolfgang Walther c18ccf5232 chore: Switch from dependabot to renovate
This allows much better configuration and customization and will keep our
release branches up2date, too.
2024-02-24 18:10:30 +01:00
Wolfgang WaltherandWolfgang Walther 79e172a65c ci: Fix failing Upload Reports job 2024-02-24 17:27:01 +01:00
Wolfgang WaltherandWolfgang Walther b49e3b1e5b ci: Only run ARM-related jobs if related settings are present
This allows CI to properly run through in a fork, which doesn't have the SSH_ARM_xxx settings.
2024-02-24 17:27:01 +01:00
Wolfgang Walther 6caaee777b nix: Simplify static.nix
The enable-executable-static flag is set by default, so doesn't make a difference.

The pkg-config improvement for libpq was merged upstream, so we can use the same
here already.
2024-02-24 15:38:02 +01:00
Wolfgang Walther 86b2e59f6f chore: Add tested-with field to postgrest.cabal
This documents supported GHC versions. GHC 9.8.1 is currently commented
out to reflect the fact that PostgREST can't currently be built with it
straight from hackage - we still require some overrides in cabal.project
for that.
2024-02-24 14:07:55 +01:00
Wolfgang Walther 0738785d72 test: Improve dump-schema snapshot test formatting
Splitting the output into separate files and adding top-level newlines makes this
much better to read and understand when looking at diffs.

Inspired by #1699
2024-02-24 14:01:19 +01:00
Wolfgang WaltherandWolfgang Walther 2c2513b9cd deps: Use libpq v16 for freebsd build 2024-02-24 13:46:05 +01:00
Wolfgang WaltherandWolfgang Walther 9314dede2d ci: Build with GHC 9.8.2 2024-02-24 13:37:24 +01:00
Wolfgang Walther ccc386cf38 nix: Add deadnix to postgrest-lint and remove dead nix code 2024-02-24 13:08:04 +01:00
Wolfgang Walther caf0a70171 nix: Clarify pkg-config usage in static.nix a bit
This will make it easier to make the switch from pkgsCross.libpq to pkgsStatic.libpq,
once that is possible to build upstream - if ever.
2024-02-24 12:08:40 +01:00
Wolfgang Walther 22e8906c40 nix: Run faster tasks first in postgrest-lint
This avoid long waiting times when waiting for the result of shellcheck or actionlint.
2024-02-23 14:02:05 +01:00
Wolfgang WaltherandWolfgang Walther 0b3f6de015 ci: Merge docs-spellcheck and docs-dictcheck jobs
Both jobs run really quick, running them separate is just a waste of resources. Plus,
they are semantically closely related anyway.
2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther c59736b902 ci: Rename release jobs for consistency 2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther 19423b0c0a ci: Only run PR workflows when files have changed 2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther e9abb64fc0 ci: Split Build workflow from CI workflow 2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther 57ef98a316 ci: Split Test workflow from CI workflow 2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther 31a3864f85 ci: Remove files from arm server immediately on non-release push
While this duplicates code a little bit, it makes it much simpler to refactor later on.
2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther 073280ad32 ci: Require docs job to pass before making a release 2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther 333f8cf592 ci: Cancel all workflows consistently in pull requests without blocking main
The previous setup would cause multiple commits on main to be stuck in a pending
state, waiting for the previous run to be finished.

The new group specification is taken from:
https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value

This also adds the same settings for the docs workflow.
2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther f9fdf666ad ci: Use if without ${{ }} where possible 2024-02-22 20:12:18 +01:00
Wolfgang WaltherandWolfgang Walther c54e0d3353 ci: Use actions/download-artifact instead of dawidd6/action-download-artifact
The "default" action now supports downloading from different workflow runs, too, so
we might as well use it.
2024-02-22 20:12:18 +01:00
steve-chavez 3a3601cbeb feat: log schema cache load time 2024-02-21 18:16:37 -05:00
Wolfgang WaltherandWolfgang Walther 1a141c19df nix: Add postgrest-docs-render to render latex documents 2024-02-21 09:40:11 +01:00
Wolfgang WaltherandWolfgang Walther b8f35d880f docs: Fix broken redirects in api.rst 2024-02-21 09:40:11 +01:00
Wolfgang WaltherandWolfgang Walther 791b86cbf6 docs: Add note about not support Stored Procedures
Resolves https://github.com/PostgREST/postgrest-docs/issues/147
2024-02-21 09:40:11 +01:00
Wolfgang WaltherandWolfgang Walther 944b02fbb8 docs: Rename Stored Procedures to Functions consistently
This avoids confusing our RPCs with actual CREATE PROCEDURE, which we don't
support.

References https://github.com/PostgREST/postgrest-docs/issues/147
2024-02-21 09:40:11 +01:00
Wolfgang WaltherandWolfgang Walther 95b8751496 docs: Simplify SQL for user management how-tos
All those DROP IF EXISTS and CREATE IF NOT EXISTS etc. just give a lot more text to
read and understand. If in fact a user creates the same thing twice, they should be
able to understand the error message from postgres.
2024-02-21 09:40:11 +01:00
Wolfgang WaltherandWolfgang Walther 9b1ff2235a docs: Simplify auth examples with OUT parameter
The jwt_token type was not created consistently in all examples, which can
be confusing when following those. To return an object with a single key
named token, it's enough to have an OUT parameter to the function.

Resolves https://github.com/PostgREST/postgrest-docs/issues/280
2024-02-21 09:40:11 +01:00
Steve ChavezandGitHub 7c6c056e92 refactor: make observation messages pure (#3250)
removes the observation messages from the Logger
2024-02-20 18:42:38 -05:00
Laurence IslaandGitHub 229bc77886 docs: using or across embedded resources 2024-02-20 17:15:42 -05:00
Wolfgang WaltherandWolfgang Walther 8a21a9c34e fix: Dump media handlers and timezones with --dump-schema
Those were left out of the schema dump when the features were introduced, probably
because ByteString doesn't have a toJSON instance. Changing the type to Text solves
this easily.

Resolves #3237
2024-02-20 18:44:17 +01:00
Steve ChavezandGitHub 6d506df6f3 refactor: add observation module (#3232) 2024-02-20 12:29:33 -05:00
Taimoor ZaeemandGitHub 32e1900370 feat: dump schema cache through admin API (#3233) 2024-02-19 21:20:29 -05:00
Wolfgang WaltherandWolfgang Walther fac7acafa3 chore: Add docs/_build to .gitignore again to allow switching to old release branches easily 2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 645217333b docs: Display version number more prominently
Resolves https://github.com/PostgREST/postgrest-docs/issues/734
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther fcd29caecf docs: Use code-block postgres consistently 2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 553ac79d9b docs: Add example on how to automatically store mimetype in files table
Resolves https://github.com/PostgREST/postgrest-docs/issues/612
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther b2ad914435 docs: Improve introduction for datatypes how-to
Not all examples on this page are strictly using string representation, especially bytea.
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 8ee4e9f0bb docs: Sort datatypes how-to alphabetically
The examples in this sections were in seemingly random order before.
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 8f2b6b1652 docs: Add hint about schema reloading with db-config=true
Resolves https://github.com/PostgREST/postgrest-docs/issues/490
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther b1deb049c8 docs: Clarify behavior of jwt-aud and tokens without aud claim
Resolves https://github.com/PostgREST/postgrest-docs/issues/479
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 51db5ce26f docs: Add example for ordering by json field
Resolves https://github.com/PostgREST/postgrest-docs/issues/364
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther e7dde2806c docs: Change tutorials to use identity column instead of serial/sequence
Resolves https://github.com/PostgREST/postgrest-docs/issues/311
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 4325a4f9d5 docs: Add links to resource embedding from insert/update/delete sections
Resolves https://github.com/PostgREST/postgrest-docs/issues/277
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 77715dcabf docs: Rename remaining instances of computed columns to computed fields
Resolves https://github.com/PostgREST/postgrest-docs/issues/368
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther aaaf0572ce docs: Remove deprecated auth0 features
As mentioned in https://github.com/PostgREST/postgrest/discussions/3088 rules and hooks are not
available to new tenants anymore, so the note is not helpful anymore.

Resolves #3088
Resolves https://github.com/PostgREST/postgrest-docs/issues/85
Resolves https://github.com/PostgREST/postgrest-docs/issues/715
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 500aad3360 docs: Clarify secret wording in tutorial 1
Resolves https://github.com/PostgREST/postgrest-docs/issues/108
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 3d95c41115 docs: Remove note about risk of asymmetric keys for JWT auth
The obviously wrong statement is, that PostgREST does not support asymmetric keys, while it
does. Extending on this type of attack is not necessary, because it is in fact covered by
the paragraph before - reading the algorithm from the JWT header is the problem in that case,
too. We don't do that.

This leaves us with the sentence about how the chosen library is the most important part. While
that is correct, the hint about high quality libraries for use on the *client* side is mis-
leading: The important part here is the library we choose to implement PostgREST with, not the
client-side lib. Thus, removing the whole paragraph is the best thing to do here.

Resolves https://github.com/PostgREST/postgrest-docs/issues/123
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 6eaaa9aa9b docs: Remove note about possible memory leak on alpine
We don't have any justification to add this hint anywhere.

Resolves https://github.com/PostgREST/postgrest-docs/issues/399
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther f33bccbcdb docs: Use port 5432 in tutorial 0 to avoid connecting to the wrong server
Some users connect PostgREST to the wrong PostgreSQL instance - likely because they are
not even aware that another instance is running. By using the standard port 5432 instead
of 5433, we avoid this problem. The user will be made aware very early that they have
another postgresql instance running - and can solve the problem at this stage. If they
decide to change the port, they are much more likely to remember that in the later stages
of the tutorial, too.

Resolves https://github.com/PostgREST/postgrest-docs/issues/304
2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 6c886b1291 docs: Update output in tutorials to latest version 2024-02-19 21:54:15 +01:00
Wolfgang WaltherandWolfgang Walther 0e7af7b77b docs: Various formatting improvements 2024-02-19 21:54:15 +01:00
Wolfgang Walther 4a796e0758 nix: Show connection hints for postgrest-with-postgresql-xx on stdout
This allows running this together with postgrest-run --dump-schema and
piping the result into jq without syntax errors.
2024-02-19 17:49:16 +01:00
Wolfgang Walther 8ff9f3292e test: Hide "cast on domain" warnings in spec tests
Also removes a few other unused settings which originate from running pg_dump.
2024-02-19 17:49:16 +01:00
Wolfgang WaltherandWolfgang Walther 5804b754e3 chore(deps): Remove useless pins in cabal.project.non-nix
Those were mistakenly added to support GHC 9.8.1, before I understood hackage revisions.
2024-02-19 17:47:37 +01:00
Wolfgang Walther 16bc853114 nix: Change default socket location for libpq back to /var/run/postgresql
Commit 85fbb233 accidentally changed the default socket location in which libpq is
looking for postgresql unix sockets. This is changed in nixpkgs via patch. By imp-
orting the default patches, this is changed back to what it was before. Without
those patches it was changed from /run/postgresql to /tmp.

Not a bugfix, because it was not released, yet.
2024-02-19 16:24:17 +01:00
Wolfgang Walther 272c1cc1e2 nix: Fix docs-spellcheck with multiple references on a single line 2024-02-18 19:35:40 +01:00
Wolfgang Walther 72de95b069 docs: Fix spelling mistakes 2024-02-18 19:35:40 +01:00
Wolfgang Walther c196d406d4 nix: Make postgrest-watch postgrest-docs-check work
This moves the _build folder into the repo root, to avoid postgrest-watch ending in an
infinite loop of restarting the build.

Also, for repeated use during development, running linkcheck is not a good idea, this
will quickly result in rate-limiting requests from various servers.
2024-02-18 16:12:20 +01:00
Wolfgang WaltherandWolfgang Walther b435f1b2d4 nix: Move docs build and serve scripts into nix
This is long overdue. We expect everyone contributing to postgrest to use the nix tools,
so it makes no sense to carry around external tools anymore.
2024-02-18 13:10:00 +01:00
Wolfgang WaltherandWolfgang Walther 3750f35e3f chore: Deduplicate static files between core and docs 2024-02-18 13:10:00 +01:00
Wolfgang WaltherandWolfgang Walther c2a333efc4 chore: Bump version docs to 12.1-dev
See c004840e.
2024-02-18 13:10:00 +01:00
Laurence IslaandWolfgang Walther a1f2ecadda nix: Move docs tools into core infrastructure 2024-02-18 13:10:00 +01:00
Wolfgang WaltherandWolfgang Walther e110fdbd2c nix: Refactor checkedShellScript's inRootDir to workingDir
This allows more flexible control over the working directory. Values for workingDir must always start
with a / and will then be relative to the repo root.
2024-02-18 13:10:00 +01:00
Wolfgang Walther 75a86ba873 ci: Change names for release branches from rel-MAJOR.MINOR to vMAJOR
This naming scheme gives us the best support for readthedocs.

References #2814
2024-02-17 17:43:03 +01:00
Wolfgang Walther b2dda6a5d3 ci: Refactor conditions to check for branch events 2024-02-17 17:38:39 +01:00
Wolfgang Walther 9a145f6931 Merge branch 'docs/main' into main 2024-02-17 15:14:44 +01:00
Wolfgang Walther 311a38193b chore: Run postgrest-style on docs files
This prevents CI from failing after the merge.
2024-02-17 13:43:50 +01:00
Wolfgang Walther 4954859d68 chore: Prepare merge of postgrest-docs into postgrest main repo
This avoids some merge conflicts to allow git blame to detect renames properly.
2024-02-17 13:43:50 +01:00
Wolfgang Walther a7afcc4de9 chore: Remove accidentally committed submodule
This was accidentally added in b22bb74.
2024-02-17 13:13:00 +01:00
Wolfgang Walther 1b855d805e docs: Replace some permanent redirections with their target
And sort the ecosystemi's _devops list again.
2024-02-16 22:36:57 +01:00
Laurence IslaandWolfgang Walther 4059e1ea76 Add tutorial for Godot 4 + PostgREST in ecosystem 2024-02-16 22:14:05 +01:00
Laurence IslaandWolfgang Walther 93e50b1d90 docs: Enable non-broken link again 2024-02-16 22:11:00 +01:00
Wolfgang WaltherandWolfgang Walther 2ae96e7733 docs: Fix broken stackoverflow link 2024-02-16 22:04:07 +01:00
Wolfgang WaltherandWolfgang Walther 9167ae9462 chore: Remove leftover .test file 2024-02-16 22:04:07 +01:00
Wolfgang WaltherandWolfgang Walther 3664343989 chore: Add build tools for translations
Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
2024-02-16 22:04:07 +01:00
Wolfgang WaltherandWolfgang Walther 18d105f8c2 nix: Update nixpkgs to same version as core repo 2024-02-16 22:04:07 +01:00
Wolfgang Walther c004840e76 Bump to v12.1
Going forward, an uneven minor version will be a development version, while an even minor will be
considered a stable version to be released. This is similar to what GHC does and was discussed in
#3113.

This bump should have happened after branching off v12.0.0, but obviously we didn't know about it
back then. This will happen immediately after branching off a new release from now on.
2024-02-16 16:38:32 +01:00
Wolfgang Walther 00fbe9ff3e fix: Avoid casting to table type when select= and media type handler are used
Previously using a generic mimetype handler failed when any kind of select= was given, because
we tried to cast the select-result to the original table type. With this change, this cast is
only applied when select=* is given implicitly or explicitly. This is the only case where this
makes sense, because this guarantees that correct columns are selected in the correct order for
this cast to succeed.

Resolves #3160
2024-02-15 19:01:12 +01:00
Wolfgang Walther 2466f4e738 fix: Return 406 instead of 415 for non-acceptable media type
415 is for Content-Type and 406 for Accept headers.
2024-02-15 19:01:12 +01:00
Andrei DziahelandGitHub 3432f75ed4 fix: fixes server timings' precision (#3227)
* test: fix test_io accordingly
2024-02-14 12:26:34 -05:00
Wolfgang Walther b22bb748f2 nix: Remove left-over commented out code in postgrest-test-doctests
This seems to be commented out for a while already, but nobody reported
problems, so far.
2024-02-11 11:38:53 +01:00
steve-chavez 21e8ca5051 feat: log full pg version to stderr on connection 2024-02-10 19:21:55 -05:00
Wolfgang WaltherandWolfgang Walther 410fa9508b nix: Make postgrest-with-postgresql-xxx postgrest-test-io work better
The upside is that postgrest-with-postgresql-xxx postgrest-test-io works as expected
now. The downside is, that postgrest-with-postgresql-xxx psql now starts without
any schema. This now needs an explicit postgrest-with-postgresql-xxx -f path/to.sql
to do anything useful.

Resolves #2864
2024-02-10 20:51:55 +01:00
Wolfgang Walther dcfdd8dfc9 ci: Only try to download loadtest artifact after conclusion of CI workflow
Removing the condition when migrating the loadtest workflow was not helpufl, this
triggers the report job a few times per pipeline. The goal was to always download
the report, even when the overall pipeline fails because of some other jobs.
Explicitly checking for both success and failure should be enough.
2024-02-10 20:42:06 +01:00
Wolfgang Walther ca777315b0 ci: Consistently put two blank lines between jobs for better visual separation 2024-02-10 20:16:22 +01:00
Wolfgang Walther f513a71c7a ci: Use latest stable nix version in CI
This was pinned to 2.13.6 in https://github.com/PostgREST/postgrest/pull/2692#issuecomment-1448938894
because of a regression in nix 2.14. Latest is 2.16.x now, so maybe this bug is already fixed.
2024-02-10 20:16:22 +01:00
Wolfgang Walther 09c5cbece5 ci: Remove workaround for ghcup on github actions runner images
This was introduced in https://github.com/PostgREST/postgrest/pull/2655.
2024-02-10 20:16:22 +01:00
Wolfgang Walther 073320133d ci: Remove matrix configuration for Build-Cabal-Arm job
This avoids the "${{ matrix.ghc }}" display when the job is skipped in PR workflows.
2024-02-10 20:16:22 +01:00
Wolfgang Walther f17f23bd9f ci: Make stack build fail when lock file is out of date
When updating stack.yaml, we need to make sure to update stack.yaml.lock, too.

This check prevents them from getting out of sync by failing CI in this case.

This improves cachability.
2024-02-10 20:16:22 +01:00
Wolfgang Walther fd1efa4635 ci: Merge CI and Loadtest workflows
The reason why those workflows were split in the first place was just to obtain loadtest
results quicker, because the in the separated workflow, only the single loadtest job
needs to finish before the artifacts can be downloaded.

However, the disadvantage of this approach was, that the results were not as easily
accessible as they could be in a single workflow. Additionally, it's possible to depend
on the "prepopulate nix" job for efficiency if the loadtest runs in the main workflow.
2024-02-10 20:15:35 +01:00
Wolfgang Walther db16683ba2 ci: Simplify loadtest workflow
The two different PR and Merge jobs were introduced to be able to test the main branch
against the latest release. However, this is now included in the PR job, too, so no need
for the two separate jobs anymore.
2024-02-10 20:15:09 +01:00
Wolfgang Walther 8a3b0c60ad ci: Remove nix actions cache and prepopulate job
The nix actions cache currently leads to repeated "no space left on
devices" errors for jobs in CI.

The prepopulate job is useless without the nix actions cache, so it
will go away at the same time.
2024-02-10 12:35:56 +01:00
steve-chavez 5424be76d9 feat: log schema cache stats to stderr
adjust the memory tests
2024-02-09 16:18:04 -05:00
Wolfgang Walther 066fa8b6aa ci: Improve cache keys and their restore prefixes
The cache key for nix now depends on default.nix and shell.nix in the root folder and all
.patch files in the nix folder. Those may change the output of our nix derivations, so
must be included. At the same time, there is no reason to include the actions/setup-nix
folder. This would only lead to new caches being created every time we update one of the
dependent actions in this file. Finally, we never restore caches with a different id any-
more. There is no point in having the style job fall back to the static cache for example.

The cache keys for cabal can be more explicit: We only have one postgrest.cabal and one
relevant cabal.project file. We were missing the cabal.project.freeze file, though, which
affects the dependencies used, too.
2024-02-09 18:43:53 +01:00
Taimoor ZaeemandSteve Chavez f9ee1f7e73 feat: apply all function settings as transaction-scoped settings 2024-02-09 11:37:01 -05:00
Laurence IslaandGitHub 4a0b93c451 Fix technical_specs in sample DB using UNIQUE instead of PRIMARY KEY 2024-02-08 14:10:17 -05:00
Wolfgang Walther 49584728b6 nix: Remove broken docker-based nix development environment
It used to be possible to spin up a nix environment via docker container this way,
but the upstream nixos/nix image has changed and the docker build doesn't succeed
anymore. Since nobody complained about that, we can assume it is not being used
anyway.
2024-02-06 18:27:20 +01:00
Wolfgang Walther 868913d179 ci: Replace seed cachix workflow with new daemon mode
cachix-action v14 added a new daemon mode, which pushes new derivations to the store
as soon as they have been built. This replaces the seed cachix workflow nicely by just
pushing from all jobs directly.
2024-02-06 10:20:02 +01:00
Wolfgang Walther 74d8ddec36 nix: Make postgrest-push-cachix more efficient by passing each derivation only once 2024-02-06 10:20:02 +01:00
Wolfgang WaltherandWolfgang Walther ea02729ebd nix: Use -split-sections with pkgsStatic to make static executable smaller again
This works around https://github.com/NixOS/nixpkgs/issues/286285 to use -split-sections
in a cross-compiling scenario. This will reduce the size of the static executable and also
remove the remaining references to /nix/store/.. reducing closure size dramatically.

This also fixes the docker image blowing up in size since we switched to pkgsStatic.
2024-02-06 10:19:31 +01:00
Wolfgang WaltherandWolfgang Walther 9fe0f50709 ci: Add freebsd executable to releases
This was temporarily disabled, because of timeouts in Cirrus. This seems to work well again.
2024-02-06 10:19:31 +01:00
Wolfgang WaltherandWolfgang Walther 1c02e1e3a0 ci: Prevent creating artifact for dynamic ubuntu build
This is not used in the release process anyway, because we are using the static build.
2024-02-06 10:19:31 +01:00
Wolfgang WaltherandWolfgang Walther 7d096e5de5 ci: Update stack.yaml.lock 2024-02-06 10:19:31 +01:00
Wolfgang WaltherandWolfgang Walther 0eca2954b3 ci: Reduce file size of cabal and stack based builds
By passing -split-sections to all dependencies, GHC will link only the
modules we actually use and not the full package for each dependency.
This does neither work on MacOS nor Windows, thus we don't do it for
stack right now.

Stripping unused symbols in CI will further decrease the size of those files.
2024-02-06 10:19:31 +01:00
Wolfgang WaltherandWolfgang Walther cc9b725005 nix: Remove libkrb5 references from static executable 2024-02-06 10:19:31 +01:00
Wolfgang WaltherandWolfgang Walther 4a1b9a4609 nix: Remove libpq reference from static executable 2024-02-06 10:19:31 +01:00
Wolfgang WaltherandWolfgang Walther f51090f3d1 nix: Check static executable for /nix/store references
This makes the static build fail in case any references to the nix store
are left over. Those will increase the closure size of the nix derivation
massively and lead to a huge docker image.

At the same time, those references will not be functional on non-nix systems,
to which the static executable is distributed, anyway.
2024-02-06 10:19:31 +01:00
Ivan KasatenkoandGitHub 71887e4b78 feat: dump config through Admin API 2024-02-05 19:16:05 -05:00
Andrei DziahelandWolfgang Walther a45058ba02 ci: reuse more previous caches (Nix & Stack) 2024-02-05 21:51:32 +01:00
Wolfgang Walther 310d04065e test: Make failing loadtest fixtures pass again
PR #2358 added a bulk insert to the loadtest. However this broke the regular insert test,
which just returned 400 Bad Request because of a missing PK value since. Adding the new
id column in the payload to the ?columns= argument fixes that.
2024-02-05 21:40:21 +01:00
Wolfgang Walther 63ff6d1f15 nix: Fix postgrest-loadtest after vegeta update
The recent nixpkgs update gave us a new version of vegeta. This version includes a new
DNS cache features - which unfortunately doesn't play well with unix sockets. Disabling
the DNS cache makes requests succeed again.
2024-02-05 21:38:23 +01:00
steve-chavez 45cabacdcc fix: wrong subquery error returning as 400 status 2024-02-02 22:08:56 -05:00
dependabot[bot]andGitHub bbc0bda6f5 build(deps): bump LouisBrunner/checks-action from 1.6.2 to 2.0.0 (#3195) 2024-01-29 09:35:22 -05:00
dependabot[bot]andGitHub c1b46ffa1b build(deps): bump codecov/codecov-action from 3.1.4 to 3.1.5 (#3196) 2024-01-29 09:34:33 -05:00
Laurence IslaandGitHub 439db880dd Simplify htmx how-to functions using Pico CSS and Ionicons 2024-01-26 20:28:58 -05:00
Wolfgang WaltherandWolfgang Walther 43f552dbab ci: Improve caching for static and dynamic postgrest nix packages 2024-01-26 23:24:12 +01:00
Wolfgang WaltherandWolfgang Walther c43696c9a6 nix: Move postgrest-check-static inside derivation of static package
This will make the static build fail if we're not producing a static binary.
2024-01-26 23:24:12 +01:00
Andrei DziahelandWolfgang Walther 411cf430ad ci: revert cache-nix-action to v4
Upgrading c-n-action seems to break restoring Nix store rendering the cache useless (nix-community/cache-nix-action#27). This rolls the change back.
2024-01-26 18:40:45 +01:00
Wolfgang Walther 071a3d436f ci: Fix Seed-Cachix jobs on linux 2024-01-26 18:10:38 +01:00
Wolfgang WaltherandWolfgang Walther c94aa9ccd9 fix: Build static postgrest with GSSAPI support
Resolves #2815
2024-01-26 17:17:05 +01:00
Wolfgang WaltherandWolfgang Walther dcb6c5bb13 nix: Bump libpq version to link against v16 2024-01-26 17:17:05 +01:00
Wolfgang WaltherandWolfgang Walther 85fbb233a7 nix: Build only libpq instead of full postgresql package 2024-01-26 17:17:05 +01:00
Wolfgang WaltherandWolfgang Walther 259d97acee nix: Build static postgrest executable via pkgsStatic
This replaces the build via static-haskell-nix and will hopefully make
it possible to cross compile in the future.
2024-01-26 17:17:05 +01:00
Wolfgang WaltherandWolfgang Walther 3a639c7172 ci: Fix FreeBSD build on cirrus 2024-01-25 21:27:17 +01:00
Wolfgang WaltherandWolfgang Walther d75be243ac ci: Build with GHC 9.8.1 via Cabal 2024-01-25 21:27:17 +01:00
Wolfgang WaltherandWolfgang Walther 2ffb97991d ci: Build with GHC 9.6.4 via Cabal
This confirms that building with GHC 9.6.x works already, even if we can't
switch to it for the nix and stack builds, yet.
2024-01-25 21:27:17 +01:00
Wolfgang WaltherandWolfgang Walther 2e298824d6 deps: Replace postgresql-libpq fork with upstream v0.10
Our changes to reduce memory usage have been merged and released
upstream, so no need for the fork anymore.
2024-01-25 21:27:17 +01:00
steve-chavez 76b1c00935 docs: fix link to op modifiers 2024-01-22 23:49:59 -05:00
Andrei DziahelandWolfgang Walther d7246b4851 ci: nix-store --realise to tools:
Since we're building only tools now, we can just specify them directly
in the `tools:` parameter of `setup-nix` action.
2024-01-22 18:17:38 +01:00
Andrei DziahelandWolfgang Walther 286103daf2 ci: do not rebuild postgrest
specify outputs to cache excluding postgrest
2024-01-22 18:17:38 +01:00
Andrei DziahelandSteve Chavez 9c78751871 ci: fix c-n-a input names 2024-01-22 11:28:41 -05:00
dependabot[bot]andSteve Chavez 820917bcb6 build(deps): bump nix-community/cache-nix-action
Bumps [nix-community/cache-nix-action](https://github.com/nix-community/cache-nix-action) from 4.0.3 to 5.0.1.
- [Release notes](https://github.com/nix-community/cache-nix-action/releases)
- [Changelog](https://github.com/nix-community/cache-nix-action/blob/main/RELEASES.md)
- [Commits](https://github.com/nix-community/cache-nix-action/compare/v4.0.3...v5.0.1)

---
updated-dependencies:
- dependency-name: nix-community/cache-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 11:28:41 -05:00
dependabot[bot]andGitHub 02312804f0 build(deps): bump actions/cache from 3 to 4 (#3179) 2024-01-22 09:13:30 -05:00
Steve ChavezandGitHub 7a387c7a30 nix: add parallel-curl wrapper (#3172)
stock curl doesn't make it easy to make many parallel requests to a
single endpoint. The endpoint has to be repeated N times.

```
curl --parallel https://example.com https://example.com ..
```

This provides a wrapper for parallel curl. It's useful for testing
scenarios like pool timeouts.

```
parallel-curl N https://example.com
```
2024-01-18 20:03:01 -05:00
Wolfgang WaltherandWolfgang Walther 6682baebd2 nix: Update nixpkgs and build with GHC 9.4.8 2024-01-18 18:54:33 +01:00
Wolfgang WaltherandWolfgang Walther e4c60889ee nix: Make postgrest-nixpkgs-upgrade take the latest stable version
Previously this command upgraded to the latest unstable version of nixpkgs,
but this was often broken. Taking the latest stable branch should give
better results.
2024-01-18 18:54:33 +01:00
Steve ChavezandGitHub c070cb9502 Revert "build(deps): bump nix-community/cache-nix-action from 4.0.3 to 5.0.1 in /.github/actions/setup-nix" (#3167) 2024-01-17 17:55:38 -05:00
dependabot[bot]andGitHub a8165a89a0 build(deps): bump nix-community/cache-nix-action (#3135) 2024-01-17 17:25:10 -05:00
Laurence IslaandGitHub 9ef0e677e0 Use -g to prevent globbing in some curl examples 2024-01-17 12:39:42 -05:00
Laurence IslaandGitHub cb5d80aff8 Remove HTTP Snippets 2024-01-17 09:07:37 -05:00
Laurence IslaandGitHub be2778edb5 Replace the term 'password' with 'secret' to clarify the Tutorial 1 2024-01-17 09:06:20 -05:00
ParashoeandLaurence Isla 0e7d507e5e Spelling correction (#740)
Spell correct "callounter" to "callcounter"
2024-01-15 20:22:42 -05:00
Laurence IslaandGitHub 74a3217bee Update sponsor logo 2024-01-15 20:17:55 -05:00
Laurence IslaandGitHub e063a29212 Fix Sphinx version error in RTD (#739) 2024-01-15 20:09:54 -05:00
Laurence IslaandGitHub f5fca59b2e chore: update sponsor logo (#3161) 2024-01-15 20:09:42 -05:00
dependabot[bot]andGitHub 740fcdf5ab build(deps): bump cachix/cachix-action in /.github/actions/setup-nix (#3159) 2024-01-15 14:54:44 -05:00
dependabot[bot]andGitHub f864437055 Bump cachix/install-nix-action from 24 to 25 (#737) 2024-01-15 14:38:23 -05:00
steve-chavez 4bb98225d8 docs: remove Heroku integration 2024-01-10 17:23:13 -05:00
steve-chavez fdaeea8fd2 fix: misleading "Starting.." logs on scache reload 2024-01-09 20:37:25 -05:00
steve-chavez 6c3d7a946d deprecate: params=single-object preference 2024-01-04 17:00:38 -05:00
steve-chavez c29d876f90 docs: add params preference 2024-01-04 16:09:07 -05:00
steve-chavez 1e4efafd9e docs: add tx preference 2024-01-04 16:09:07 -05:00
steve-chavez 50ac91d1ae docs: testing of media handlers as a note
Otherwise users think they're required steps. See the opening comment on
https://github.com/PostgREST/postgrest/issues/3124.
2024-01-02 23:44:53 -05:00
Taimoor ZaeemandSteve Chavez f73845159c add documentation for max-affected preference 2023-12-30 23:07:45 -05:00
Laurence IslaandGitHub 0ce37f8fd6 Update sponsor image (#728) 2023-12-20 19:16:48 -05:00
Laurence IslaandGitHub b2095a8ef6 chore: update sponsor image 2023-12-20 19:16:31 -05:00
Laurence Isla d99e3ac805 changelog: update to 12.0.2 2023-12-20 18:26:05 -05:00
steve-chavez 3af63cb94c fix: empty row on handler function
Closes https://github.com/PostgREST/postgrest/issues/3126
2023-12-20 16:18:09 -05:00
steve-chavez 1680a6eed3 fix: aggregates not working for all schemas
Closes https://github.com/PostgREST/postgrest/issues/3124
2023-12-20 15:20:18 -05:00
Laurence IslaandSteve Chavez c97bd1f01b Add warning and fix to htmx how-to 2023-12-19 13:30:06 -05:00
steve-chavez 9e04bd7da6 docs: soap how-to is outdated
`*/*` can now be handled with media type handlers
2023-12-18 23:58:17 -05:00
Taimoor ZaeemandGitHub 0b77098460 feat: add max-affected preference to prefer header (#3083) 2023-12-18 18:35:23 -05:00
Laurence IslaandGitHub 3ec6526467 Add new sponsor 2023-12-18 12:14:52 -05:00
Laurence IslaandGitHub 4a1dee453b chore: add new sponsor 2023-12-18 12:14:01 -05:00
dependabot[bot]andGitHub 93bdae962e build(deps): bump actions/upload-artifact from 3 to 4 (#3123) 2023-12-18 09:09:18 -05:00
dependabot[bot]andGitHub 6a34018cfc build(deps): bump dawidd6/action-download-artifact from 2 to 3 (#3122) 2023-12-18 09:09:10 -05:00
dependabot[bot]andGitHub 2aa5373a27 build(deps): bump actions/download-artifact from 3 to 4 (#3121) 2023-12-18 09:09:02 -05:00
Laurence Isla f95a8e77a6 changelog: update to 12.0.1 2023-12-14 12:10:08 -05:00
steve-chavez a59cfafe10 fix: correct any media type handler 2023-12-12 17:45:14 -05:00
steve-chavez 6b9fde59cd fix: any handler sets a default application/json
Now it sets application/octet-stream as the generic type.
2023-12-12 17:44:07 -05:00
Laurence IslaandSteve Chavez 1e65a72264 Add missing in-db configuration for jwt-cache-max-lifetime 2023-12-12 16:36:24 -05:00
Laurence IslaandGitHub 4fb521cac6 fix: add jwt_cache_max_lifetime as an in-database configuration option (#3102) 2023-12-12 16:29:50 -05:00
steve-chavez cf258ef499 fix: add missing pgrst.server_timing_enabled 2023-12-12 10:58:22 -05:00
Laurence IslaandGitHub 0938e72c5c Add new sponsor (#723) 2023-12-12 10:39:05 -05:00
Laurence IslaandSteve Chavez e31363a325 chore: add new sponsor 2023-12-12 10:38:09 -05:00
Laurence IslaandGitHub 5bd7cda308 Priorize query parameters instead of headers in limits and pagination 2023-12-07 18:47:56 -05:00
Andrei DziahelandGitHub cbfff2804d fix: replace json parser error with generic msg (#3090) 2023-12-07 18:04:51 -05:00
Andrei DziahelandSteve Chavez 41ea4e6db6 ci: cancel in-progress loadtests for PRs as well 2023-12-07 16:01:32 -05:00
Andrei DziahelandSteve Chavez f9294c5e43 ci: test only head of branch 2023-12-07 16:01:32 -05:00
Laurence IslaandGitHub d24a3c82ef Add meta tags using an Open Graph extension 2023-12-07 15:52:57 -05:00
Laurence IslaandGitHub c6b71551f4 changelog: move missplaced unreleased fix (#3094) 2023-12-07 11:00:46 -05:00
Laurence IslaandGitHub d49e3d7132 fix: allow using special characters in json keys (#3081)
* increase memory size test
2023-12-06 17:28:51 -05:00
Laurence IslaandSteve Chavez f80a33cf32 Add missing curl requests in Preferences section 2023-12-06 17:22:31 -05:00
steve-chavez 8fd4fa0d09 fix: any media type should be bytea 2023-12-05 17:48:16 -05:00
Andrei DziahelandGitHub 72083361bc ci: similar jobs use a single cache for Nix stores
Jobs that use the setup-nix action will share a single cache, which is created by a previous warm up Job.
2023-12-05 13:57:18 -05:00
Laurence IslaandGitHub 48dee75d1a Separate Admin into Observability and Health Check (#716) 2023-12-04 16:32:02 -05:00
dependabot[bot]andGitHub 92573215b9 Bump cachix/install-nix-action from 23 to 24 (#714) 2023-12-04 16:31:07 -05:00
dependabot[bot]andGitHub 6277eb43f7 build(deps): bump cachix/cachix-action in /.github/actions/setup-nix (#3085) 2023-12-04 15:39:40 -05:00
steve-chavez b04a7f0080 fix server-timing header section
Also link it to jwt caching
2023-12-02 01:41:26 -05:00
steve-chavez 0c65bf494d changelog: update to 12.0.0 2023-12-01 19:37:11 -05:00
255 changed files with 9438 additions and 6384 deletions
+32 -6
View File
@@ -1,16 +1,42 @@
freebsd_instance:
image_family: freebsd-14-0
image_family: freebsd-14-2
build_task:
# Don't change this name without adjusting .github/workflows/ci.yaml
# Don't change this name without adjusting .github/workflows/build.yaml
name: Build FreeBSD (Stack)
install_script: pkg install -y postgresql13-client hs-stack git
install_script: pkg install -y postgresql16-client hs-stack git
only_if: |
$CIRRUS_TAG != '' || $CIRRUS_BRANCH == 'main' || $CIRRUS_BRANCH =~ 'v*' ||
changesInclude(
'.github/workflows/build.yaml',
'.github/actions/artifact-from-cirrus/**',
'.cirrus.yml',
'postgrest.cabal',
'stack.yaml*',
'**.hs'
)
stack_cache:
folders: /.stack
fingerprint_script: cat postgrest.cabal stack.yaml.lock
reupload_on_changes: false
fingerprint_script:
- echo $CIRRUS_OS
- stack --version
- md5sum postgrest.cabal
- md5sum stack.yaml.lock
stack_work_cache:
folders: .stack-work
fingerprint_script:
- echo $CIRRUS_OS
- stack --version
- md5sum postgrest.cabal
- md5sum stack.yaml.lock
- find main src -type f -iname '*.hs' -exec md5sum "{}" +
build_script: |
stack build -j 1 --local-bin-path . --copy-bins --stack-yaml stack-21.7.yaml
strip postgrest
build_script: stack build -j 1 --local-bin-path . --copy-bins
bin_artifacts:
path: postgrest
+3 -1
View File
@@ -7,12 +7,14 @@ When submitting a new feature or fix:
+ `fix`, bug fixes
+ `feat`, new features added
+ `perf`, performance improvements
+ `docs`, updating the documentation
+ `nix`, related to the Nix development environment
+ `ci`, related to the Continuous Integration modules
+ `test`, related to the testing modules
+ `refactor`, refactoring code
+ `deprecate`, deprecating a feature
+ `chore`, maintenance (changelog, build process, etc.)
+ `changelog`, updating the CHANGELOG
+ `chore`, maintenance (build process, updating sponsors, etc.)
+ Other prefixes may be used if necessary
- If there's a breaking change, add `BREAKING CHANGE` and an explanation to your commit message
-->
+5
View File
@@ -0,0 +1,5 @@
# TODO: Remove this once a new actionlint release has been cut
# and made its way to us through nixpkgs.
self-hosted-runner:
labels:
- ubuntu-24.04-arm
@@ -112,7 +112,7 @@ runs:
echo "artifacts=${artifacts}" >> "$GITHUB_OUTPUT"
- name: Save artifact to GitHub Actions
if: steps.find-task.outputs.task_found
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ inputs.upload }}
path: ${{ steps.download.outputs.artifacts }}
+35
View File
@@ -0,0 +1,35 @@
name: Cache on main
description: Stores caches on main and release branches only, but restores them on all branches.
inputs:
path:
description: Path(s) to cache
required: true
save-prs:
description: Whether to additionally store the cache in a pull request, too. Should only be used for very small caches.
type: boolean
prefix:
description: Cache key prefix to be used in both primary key and restore-keys.
required: true
suffix:
description: Cache key suffix to be used only in primary key.
required: true
runs:
using: composite
steps:
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
if: ${{ startsWith(github.ref, 'refs/heads/') || (inputs.save-prs && startsWith(github.ref, 'refs/pull/')) }}
with:
path: ${{ inputs.path }}
key: ${{ runner.os }}-${{ inputs.prefix }}-${{ inputs.suffix }}
restore-keys: |
${{ runner.os }}-${{ inputs.prefix }}-
- uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
if: ${{ !startsWith(github.ref, 'refs/heads/') && !(inputs.save-prs && startsWith(github.ref, 'refs/pull/')) }}
with:
path: ${{ inputs.path }}
key: ${{ runner.os }}-${{ inputs.prefix }}-${{ inputs.suffix }}
restore-keys: |
${{ runner.os }}-${{ inputs.prefix }}-
+3 -2
View File
@@ -11,15 +11,16 @@ inputs:
runs:
using: composite
steps:
- uses: nixbuild/nix-quick-install-action@60e9c39264d4714139af3cdf15f691b19eec3530 # v28
- uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30
with:
nix_conf: |-
always-allow-substitutes = true
max-jobs = auto
- uses: cachix/cachix-action@18cf96c7c98e048e10a83abd92116114cd8504be # v14
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
name: postgrest
authToken: ${{ inputs.authToken }}
skipPush: ${{ inputs.authToken == '' }}
- if: ${{ inputs.tools }}
run: nix-env -f default.nix -iA ${{ inputs.tools }}
shell: bash
-11
View File
@@ -1,11 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: github-actions
directory: /.github/actions/setup-nix
schedule:
interval: weekly
-12
View File
@@ -1,12 +0,0 @@
#!/usr/bin/env bash
# Tag a release that will be built with Github Actions. The version is
# read from 'postgrest.cabal'.
version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
echo "Tagging version v$version"
git tag -f "v$version"
echo "Pushing tag..."
git push -f origin "refs/tags/v$version"
+25
View File
@@ -0,0 +1,25 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:best-practices"
],
"baseBranches": [
"main",
"/^v[0-9]+/"
],
"rebaseWhen": "conflicted",
"packageRules": [
{
"matchBaseBranches": [ "/^v[0-9]+/" ],
"groupName": "all dependencies"
},
{
"matchPackageNames": ["docutils"],
"allowedVersions": "<0.21.0"
},
{
"matchPackageNames": ["macos"],
"allowedVersions": "<13"
}
]
}
-69
View File
@@ -1,69 +0,0 @@
#!/bin/bash
set -Eeuo pipefail
# This script builds PostgREST in a remote ARM server
[ -z "$1" ] && { echo "Missing 1st argument: PostgREST github commit SHA"; exit 1; }
[ -z "$2" ] && { echo "Missing 2nd argument: Build environment directory name"; exit 1; }
[ -z "$3" ] && { echo "Missing 3rd argument: GHC version"; exit 1; }
PGRST_GITHUB_COMMIT="$1"
SCRIPT_DIR="$2"
DOCKER_BUILD_DIR="$SCRIPT_DIR/docker-env"
# latest is a shortcut documented on https://www.haskell.org/ghcup/guide/#tags-and-shortcuts
CABAL_VERSION="latest"
GHC_VERSION="$3"
install_packages() {
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install -y git build-essential curl libffi-dev libffi7 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5 llvm libnuma-dev zlib1g-dev libpq-dev jq gcc
sudo apt-get clean
}
install_ghcup() {
export BOOTSTRAP_HASKELL_NONINTERACTIVE=1
export BOOTSTRAP_HASKELL_MINIMAL=1
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
source ~/.ghcup/env
}
install_cabal() {
ghcup upgrade
ghcup install cabal $CABAL_VERSION
ghcup set cabal $CABAL_VERSION
}
install_ghc() {
ghcup upgrade
ghcup install ghc $GHC_VERSION
ghcup set ghc $GHC_VERSION
}
install_packages
# Add ghcup to the PATH for this session
[ -f ~/.ghcup/env ] && source ~/.ghcup/env
ghcup --version || install_ghcup
ghcup set cabal $CABAL_VERSION || install_cabal
ghcup set ghc $GHC_VERSION || install_ghc
cd ~/$SCRIPT_DIR
# Clone the repository and build the project
git clone https://github.com/PostgREST/postgrest.git
cd postgrest
git checkout $PGRST_GITHUB_COMMIT
cabal v2-update && cabal v2-build
# Copy the built binary to the Dockerfile directory
PGRST_BIN=$(cabal exec which postgrest | tail -1)
cp $PGRST_BIN ~/$DOCKER_BUILD_DIR
# Move and compress the built binary
mkdir -p ~/$SCRIPT_DIR/result
mv $PGRST_BIN ~/$SCRIPT_DIR/result
cd ~/$SCRIPT_DIR
tar -cJf result.tar.xz result
-50
View File
@@ -1,50 +0,0 @@
#!/bin/bash
set -Eeuo pipefail
# This script publishes the Docker ARM images to Docker Hub.
[ -z "$1" ] && { echo "Missing 1st argument: PostgREST github commit SHA"; exit 1; }
[ -z "$2" ] && { echo "Missing 2nd argument: Docker repo"; exit 1; }
[ -z "$3" ] && { echo "Missing 3rd argument: Docker username"; exit 1; }
[ -z "$4" ] && { echo "Missing 4th argument: Docker password"; exit 1; }
[ -z "$5" ] && { echo "Missing 5th argument: Build environment directory name"; exit 1; }
[ -z "$6" ] && { echo "Missing 6th argument: PostgREST version"; exit 1; }
PGRST_GITHUB_COMMIT="$1"
DOCKER_REPO="$2"
DOCKER_USER="$3"
DOCKER_PASS="$4"
SCRIPT_DIR="$5"
PGRST_VERSION="$6"
DOCKER_BUILD_DIR="$SCRIPT_DIR/docker-env"
clean_env()
{
sudo docker logout
}
# Login to Docker
sudo docker logout
{ echo $DOCKER_PASS | sudo docker login -u $DOCKER_USER --password-stdin; } || { echo "Couldn't login to docker"; exit 1; }
trap clean_env sigint sigterm exit
# Move to the docker build environment
cd ~/$DOCKER_BUILD_DIR
# Push final images to Docker hub
# NOTE: This command publishes a separate ARM image because the builds cannot
# be added to the manifest if they are not in the registry beforehand.
# This image must be manually deleted from Docker Hub at the end of the process.
sudo docker buildx build --build-arg PGRST_GITHUB_COMMIT=$PGRST_GITHUB_COMMIT \
-t $DOCKER_REPO/postgrest:$PGRST_VERSION-arm \
--push .
# Add the arm images to the manifest
# NOTE: This assumes that there already is a `postgrest:<version>` image
# for the amd64 architecture pushed to Docker Hub
sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:$PGRST_VERSION $DOCKER_REPO/postgrest:$PGRST_VERSION-arm
[ "$PGRST_VERSION" != "devel" ] && sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:latest $DOCKER_REPO/postgrest:$PGRST_VERSION-arm
sudo docker logout
+201
View File
@@ -0,0 +1,201 @@
name: Build
on:
workflow_call:
secrets:
CACHIX_AUTH_TOKEN:
required: false
pull_request:
branches:
- main
- v[0-9]+
paths:
- .github/workflows/build.yaml
- .github/actions/**
- .github/scripts/**
- .github/*
- '*.nix'
- nix/**
- .cirrus.yml
- cabal.project*
- postgrest.cabal
- stack.yaml*
- '**.hs'
- '!**.md'
concurrency:
# Terminate all previous runs of the same workflow for pull requests
group: build-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
static:
name: Nix - Linux x86-64 static
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build static executable
run: nix-build -A postgrestStatic
- name: Save built executable as artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: postgrest-linux-static-x86-64
path: result/bin/postgrest
if-no-files-found: error
- name: Build Docker image
run: nix-build -A docker.image --out-link postgrest-docker.tar.gz
- name: Save built Docker image as artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: postgrest-docker-x86-64
path: postgrest-docker.tar.gz
if-no-files-found: error
macos:
name: Nix - MacOS
runs-on: macos-14
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Install gnu sed
run: brew install gnu-sed
- name: Build everything
run: |
# The --dry-run will give us a list of derivations to download from cachix and
# derivations to build. We only take those that would have to be built and then build
# those explicitly. This has the advantage that pure verification will not include
# a download anymore, making it much faster. If something needs to be built, only
# the dependencies required to do so will be downloaded, but not everything.
nix-build --dry-run 2>&1 \
| gsed -e '1,/derivations will be built:$/d' -e '/paths will be fetched/Q' \
| xargs nix-build
stack:
strategy:
fail-fast: false
matrix:
include:
- name: Linux aarch64
runs-on: ubuntu-24.04-arm
cache: |
~/.stack/pantry
~/.stack/snapshots
~/.stack/stack.sqlite3
artifact: postgrest-ubuntu-aarch64
deps: sudo apt-get update && sudo apt-get install libpq-dev
- name: MacOS
runs-on: macos-14
cache: |
~/.stack/pantry
~/.stack/snapshots
~/.stack/stack.sqlite3
artifact: postgrest-macos-aarch64
deps: brew link --force libpq
- name: Windows
runs-on: windows-2022
cache: |
C:\sr\pantry
C:\sr\snapshots
C:\sr\stack.sqlite3
deps: Add-Content $env:GITHUB_PATH $env:PGBIN
artifact: postgrest-windows-x86-64
name: Stack - ${{ matrix.name }}
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: haskell-actions/setup@d9b5b3fcf7ca56b8fe585c9b77d3b0ce466affd2 # v2.7.10
with:
# This must match the version in stack.yaml's resolver
ghc-version: 9.6.5
enable-stack: true
stack-no-global: true
stack-setup-ghc: true
- name: Cache ~/.stack
uses: ./.github/actions/cache-on-main
with:
path: ${{ matrix.cache }}
prefix: stack
suffix: ${{ hashFiles('postgrest.cabal', 'stack.yaml.lock') }}
- name: Cache .stack-work
uses: ./.github/actions/cache-on-main
with:
path: .stack-work
save-prs: true
prefix: stack-work-${{ hashFiles('postgrest.cabal', 'stack.yaml.lock') }}
suffix: ${{ hashFiles('main/**/*.hs', 'src/**/*.hs') }}
- name: Install dependencies
if: matrix.deps
run: ${{ matrix.deps }}
- name: Build with Stack
run: stack build --lock-file error-on-write --local-bin-path result --copy-bins
- name: Strip Executable
run: strip result/postgrest*
- name: Save built executable as artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ matrix.artifact }}
path: |
result/postgrest
result/postgrest.exe
if-no-files-found: error
freebsd:
name: Stack - FreeBSD from CirrusCI
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: ./.github/actions/artifact-from-cirrus
with:
token: ${{ github.token }}
task: Build FreeBSD (Stack)
download: bin
upload: postgrest-freebsd-x86-64
cabal:
strategy:
matrix:
ghc: ['9.6.4', '9.8.2']
fail-fast: false
name: Cabal - Linux x86-64 - GHC ${{ matrix.ghc }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: haskell-actions/setup@d9b5b3fcf7ca56b8fe585c9b77d3b0ce466affd2 # v2.7.10
with:
ghc-version: ${{ matrix.ghc }}
- name: Cache .cabal
uses: ./.github/actions/cache-on-main
with:
path: |
~/.cabal/packages
~/.cabal/store
prefix: cabal-${{ matrix.ghc }}
suffix: ${{ hashFiles('postgrest.cabal', 'cabal.project', 'cabal.project.freeze') }}
- name: Cache dist-newstyle
uses: ./.github/actions/cache-on-main
with:
path: dist-newstyle
save-prs: true
prefix: cabal-${{ matrix.ghc }}-dist-newstyle-${{ hashFiles('postgrest.cabal', 'cabal.project', 'cabal.project.freeze') }}
suffix: ${{ hashFiles('**/*.hs') }}
- name: Install dependencies
run: cabal build --only-dependencies --enable-tests --enable-benchmarks
- name: Build
run: cabal build --enable-tests --enable-benchmarks all
-78
View File
@@ -1,78 +0,0 @@
name: Cachix
# This workflow serves to
# - keep cachix up to date with the main branch
# - incrementally update cachix for large dependency
# updates, e.g. after running postgrest-nixpkgs-upgrade,
# which can cause the main CI workflow to time out
on:
workflow_dispatch:
push:
branches:
- main
- rel-*
tags:
- v*
jobs:
Seed-Cachix:
strategy:
fail-fast: false
matrix:
include:
- os: Linux
runs-on: ubuntu-22.04
- os: MacOS
runs-on: macos-12
name: Seed ${{ matrix.os }}
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Install cachix tooling
run: |
nix-env -f default.nix -iA devTools.pushCachix.bin
postgrest-push-cachix
- name: Seed dynamic postgrest build
run: |
nix-build -A postgrestPackage
postgrest-push-cachix
- name: Seed style tools
run: |
nix-build -A style
postgrest-push-cachix
- name: Seed test tools
run: |
nix-build -A tests
postgrest-push-cachix
- name: Seed static toolchain
if: matrix.os == 'Linux'
run: |
nix-build -A packagesStatic.haskellPackages.hello
postgrest-push-cachix
- name: Seed static postgresql build (for libpq)
if: matrix.os == 'Linux'
run: |
nix-build -A packagesStatic.pkgs.postgresql
postgrest-push-cachix
- name: Seed static postgrest build
if: matrix.os == 'Linux'
run: |
nix-build -A postgrestStatic
postgrest-push-cachix
- name: Build and push everything to Cachix
run: |
nix-build
postgrest-push-cachix
+32
View File
@@ -0,0 +1,32 @@
name: Check
on:
workflow_call:
secrets:
CACHIX_AUTH_TOKEN:
required: false
pull_request:
branches:
- main
- v[0-9]+
concurrency:
# Terminate all previous runs of the same workflow for pull requests
group: style-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
lint-style:
name: Lint & Style
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: style.lint.bin style.styleCheck.bin
- name: Run linter (check locally with `nix-shell --run postgrest-lint`)
run: postgrest-lint
- name: Run style check (auto-format with `nix-shell --run postgrest-style`)
run: postgrest-style-check
+34 -518
View File
@@ -5,329 +5,52 @@ on:
branches:
- main
- v[0-9]+
tags:
- devel
- v*
pull_request:
branches:
- main
- v[0-9]+
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
# Terminate all previous runs of the same workflow for pull requests
cancel-in-progress: "${{ github.event_name == 'pull_request' }}"
jobs:
Lint-Style:
name: Lint & check code style
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: style
- name: Run linter (check locally with `nix-shell --run postgrest-lint`)
run: postgrest-lint
- name: Run style check (auto-format with `nix-shell --run postgrest-style`)
run: postgrest-style-check
check:
name: Check
uses: ./.github/workflows/check.yaml
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
Test-Nix:
name: Test (Nix)
runs-on: ubuntu-22.04
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: tests
- name: Run coverage (IO tests and Spec tests against PostgreSQL 15)
run: postgrest-coverage
- name: Upload coverage to codecov
uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # v4.3.1
with:
files: ./coverage/codecov.json
token: ${{ secrets.CODECOV_TOKEN }}
- name: Run doctests
if: always()
run: nix-shell --run postgrest-test-doctests
- name: Check the spec tests for idempotence
if: always()
run: postgrest-test-spec-idempotence
docs:
name: Docs
uses: ./.github/workflows/docs.yaml
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
Test-Pg-Nix:
strategy:
fail-fast: false
matrix:
pgVersion: [9.6, 10, 11, 12, 13, 14, 15, 16]
name: Test PG ${{ matrix.pgVersion }} (Nix)
runs-on: ubuntu-22.04
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: tests withTools
- name: Run spec tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} postgrest-test-spec
- name: Run IO tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} -f test/io/fixtures.sql postgrest-test-io -vv
test:
name: Test
uses: ./.github/workflows/test.yaml
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
Test-Memory-Nix:
name: Test memory (Nix)
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: memory
- name: Run memory tests
run: postgrest-test-memory
build:
name: Build
uses: ./.github/workflows/build.yaml
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
Build-Static-Nix:
name: Build Linux static (Nix)
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: tests
- name: Build static executable
run: nix-build -A postgrestStatic
- name: Check static executable
run: postgrest-check-static result/bin/postgrest
- name: Save built executable as artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: postgrest-linux-static-x64
path: result/bin/postgrest
if-no-files-found: error
- name: Build Docker image
run: nix-build -A docker.image --out-link postgrest-docker.tar.gz
- name: Save built Docker image as artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: postgrest-docker-x64
path: postgrest-docker.tar.gz
if-no-files-found: error
Build-Macos-Nix:
name: Build MacOS (Nix)
runs-on: macos-12
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
- name: Build everything
run: |
nix-build
Build-Stack:
strategy:
fail-fast: false
matrix:
include:
- name: Linux
runs-on: ubuntu-22.04
cache: |
~/.stack
.stack-work
artifact: postgrest-ubuntu-x64
- name: MacOS
runs-on: macos-12
cache: |
~/.stack
.stack-work
artifact: postgrest-macos-x64
- name: Windows
runs-on: windows-2022
cache: |
~\AppData\Roaming\stack
~\AppData\Local\Programs\stack
.stack-work
deps: Add-Content $env:GITHUB_PATH $env:PGBIN
artifact: postgrest-windows-x64
name: Build ${{ matrix.name }} (Stack)
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Stack working files cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ matrix.cache }}
key: cache-stack-${{ runner.os }}-${{ hashFiles('stack.yaml.lock') }}
- name: Install dependencies
if: ${{ matrix.deps }}
run: ${{ matrix.deps }}
- name: Build with Stack
run: stack build --local-bin-path result --copy-bins
- name: Save built executable as artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: ${{ matrix.artifact }}
path: |
result/postgrest
result/postgrest.exe
if-no-files-found: error
Get-FreeBSD-CirrusCI:
name: Get FreeBSD build from CirrusCI
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: ./.github/actions/artifact-from-cirrus
with:
token: ${{ github.token }}
task: Build FreeBSD (Stack)
download: bin
upload: postgrest-freebsd-x64
Build-Cabal:
strategy:
matrix:
ghc: ['9.0.2', '9.2.4']
fail-fast: false
name: Build Linux (Cabal, GHC ${{ matrix.ghc }})
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Workaround runner image issue
# https://github.com/actions/runner-images/issues/7061
run: sudo chown -R "$USER" /usr/local/.ghcup
- name: ghcup
run: |
ghcup install ghc ${{ matrix.ghc }}
ghcup set ghc ${{ matrix.ghc }}
- name: Copy cabal.project & fix caching
run: |
mkdir ~/.cabal
cp cabal.project.non-nix cabal.project
- name: Cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: |
~/.cabal/packages
~/.cabal/store
dist-newstyle
key: cache-cabal-${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('**/*.cabal', '**/cabal.project') }}
restore-keys: |
cache-cabal-${{ runner.os }}-${{ matrix.ghc }}-
- name: Install dependencies
run: |
cabal update
cabal build --only-dependencies --enable-tests --enable-benchmarks
- name: Build
run: cabal build --enable-tests --enable-benchmarks all
Build-Cabal-Arm:
strategy:
matrix:
ghc: ['9.2.4']
fail-fast: false
name: Build aarch64 (Cabal, GHC ${{ matrix.ghc }})
if: "${{ github.event_name == 'push' }}"
runs-on: ubuntu-22.04
outputs:
remotepath: ${{ steps.Remote-Dir.outputs.remotepath }}
env:
GITHUB_COMMIT: ${{ github.sha }}
GHC_VERSION: ${{ matrix.ghc }}
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- id: Remote-Dir
name: Unique directory name for the remote build
run: echo "remotepath=postgrest-build-$(uuidgen)" >> "$GITHUB_OUTPUT"
- name: Copy script files to the remote server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
source: ".github/scripts/arm/*"
target: ${{ steps.Remote-Dir.outputs.remotepath }}
strip_components: 3
- name: Build ARM
uses: appleboy/ssh-action@master
env:
REMOTE_DIR: ${{ steps.Remote-Dir.outputs.remotepath }}
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
command_timeout: 120m
script_stop: true
envs: GITHUB_COMMIT,REMOTE_DIR,GHC_VERSION
script: bash ~/$REMOTE_DIR/build.sh "$GITHUB_COMMIT" "$REMOTE_DIR" "$GHC_VERSION"
- name: Download binaries from remote server
uses: nicklasfrahm/scp-action@main
with:
direction: download
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
source: "${{ steps.Remote-Dir.outputs.remotepath }}/result.tar.xz"
target: "result.tar.xz"
- name: Extract downloaded binaries
run: tar -xvf result.tar.xz && rm result.tar.xz
- name: Save aarch64 executable as artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: postgrest-ubuntu-aarch64
path: result/postgrest
if-no-files-found: error
Tag-Release:
name: Tag Release
if: startsWith(github.ref, 'refs/heads/')
permissions:
contents: write
runs-on: ubuntu-22.04
tag:
name: Tag
concurrency:
# Never tag outdated commits on the main branch by skipping superseded commits
group: ci-tag-${{ (github.ref == 'refs/heads/main' && github.ref) || github.run_id }}
# TODO: Enable this once https://github.com/orgs/community/discussions/13015 is solved
cancel-in-progress: false
if: vars.RELEASE_ENABLED
runs-on: ubuntu-24.04
needs:
- Lint-Style
- Test-Nix
- Test-Pg-Nix
- Test-Memory-Nix
- Build-Static-Nix
- Build-Stack
- Get-FreeBSD-CirrusCI
- Build-Cabal-Arm
- docs
- test
- build
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ssh-key: ${{ secrets.POSTGREST_SSH_KEY }}
- name: Tag latest commit
@@ -345,210 +68,3 @@ jobs:
git tag -f "devel"
git push -f origin "devel"
fi
Prepare-Release:
name: Prepare release
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-22.04
needs:
- Lint-Style
- Test-Nix
- Test-Pg-Nix
- Test-Memory-Nix
- Build-Static-Nix
- Build-Stack
- Get-FreeBSD-CirrusCI
- Build-Cabal-Arm
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Check the version to be released
run: |
cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
if [ "${GITHUB_REF_NAME}" != "devel" ] && [ "${GITHUB_REF_NAME}" != "v$cabal_version" ]; then
echo "Tagged version ($GITHUB_REF_NAME) does not match the one in postgrest.cabal (v$cabal_version). Aborting release..."
exit 1
fi
- name: Identify changes from CHANGELOG.md
run: |
if [ "${GITHUB_REF_NAME}" == "devel" ]; then
echo "Getting unreleased changes..."
sed -n "1,/## Unreleased/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
else
version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
echo "Propper release, getting changes for version $version ..."
sed -n "1,/## \[$version\]/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
fi
echo "Relevant extract from CHANGELOG.md:"
cat CHANGES.md
- name: Save CHANGES.md as artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: release-changes
path: CHANGES.md
if-no-files-found: error
Release-GitHub:
name: Release on GitHub
permissions:
contents: write
runs-on: ubuntu-22.04
needs: Prepare-Release
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Download all artifacts
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
path: artifacts
- name: Create release bundle with archives for all builds
run: |
find artifacts -type f -iname postgrest -exec chmod +x {} \;
mkdir -p release-bundle
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-linux-static-x64.tar.xz" \
-C artifacts/postgrest-linux-static-x64 postgrest
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-macos-x64.tar.xz" \
-C artifacts/postgrest-macos-x64 postgrest
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-freebsd-x64.tar.xz" \
-C artifacts/postgrest-freebsd-x64 postgrest
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-ubuntu-aarch64.tar.xz" \
-C artifacts/postgrest-ubuntu-aarch64 postgrest
zip "release-bundle/postgrest-${GITHUB_REF_NAME}-windows-x64.zip" \
artifacts/postgrest-windows-x64/postgrest.exe
- name: Save release bundle
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: release-bundle
path: release-bundle
if-no-files-found: error
- name: Publish release on GitHub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Releasing version ${GITHUB_REF_NAME} on GitHub..."
if [ "${GITHUB_REF_NAME}" == "devel" ]; then
# To replace the existing release, we must first delete the old assets,
# then modify the release, then add the new assets.
gh release view devel --json assets \
| jq -r '.assets[] | .name' \
| xargs -rn1 \
gh release delete-asset -y devel
gh release edit devel \
-t devel \
--verify-tag \
-F artifacts/release-changes/CHANGES.md \
--prerelease
gh release upload --clobber devel release-bundle/*
else
gh release create "${GITHUB_REF_NAME}" \
-t "${GITHUB_REF_NAME}" \
--verify-tag \
-F artifacts/release-changes/CHANGES.md \
release-bundle/*
fi
Release-Docker:
name: Release on Docker Hub
runs-on: ubuntu-22.04
needs:
- Prepare-Release
env:
DOCKER_REPO: ${{ vars.DOCKER_REPO }}
DOCKER_USER: ${{ vars.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Download Docker image
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: postgrest-docker-x64
- name: Publish images on Docker Hub
run: |
docker login -u "$DOCKER_USER" -p "$DOCKER_PASS"
docker load -i postgrest-docker.tar.gz
docker tag postgrest:latest "$DOCKER_REPO/postgrest:${GITHUB_REF_NAME}"
docker push "$DOCKER_REPO/postgrest:${GITHUB_REF_NAME}"
# Only tag 'latest' for full releases
if [ "${GITHUB_REF_NAME}" != "devel" ]; then
echo "Pushing to 'latest' tag for full release of ${GITHUB_REF_NAME} ..."
docker tag postgrest:latest "$DOCKER_REPO"/postgrest:latest
docker push "$DOCKER_REPO"/postgrest:latest
else
echo "Skipping push to 'latest' tag for pre-release..."
fi
# TODO: Enable dockerhub description update again, once a solution for the permission problem is found:
# https://github.com/docker/hub-feedback/issues/1927
# - name: Update descriptions on Docker Hub
# env:
# DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
# run: |
# if [[ -z "$ISPRERELEASE" ]]; then
# echo "Updating description on Docker Hub..."
# postgrest-release-dockerhub-description
# else
# echo "Skipping updating description for pre-release..."
# fi
Release-Docker-Arm:
name: Release Arm Builds on Docker Hub
runs-on: ubuntu-22.04
needs:
- Build-Cabal-Arm
- Release-Docker
env:
GITHUB_COMMIT: ${{ github.sha }}
DOCKER_REPO: ${{ vars.DOCKER_REPO }}
DOCKER_USER: ${{ vars.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Publish images for ARM builds on Docker Hub
uses: appleboy/ssh-action@master
env:
REMOTE_DIR: ${{ needs.Build-Cabal-Arm.outputs.remotepath }}
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
script_stop: true
envs: GITHUB_COMMIT,DOCKER_REPO,DOCKER_USER,DOCKER_PASS,REMOTE_DIR,GITHUB_REF_NAME
script: bash ~/$REMOTE_DIR/docker-publish.sh "$GITHUB_COMMIT" "$DOCKER_REPO" "$DOCKER_USER" "$DOCKER_PASS" "$REMOTE_DIR" "$GITHUB_REF_NAME"
Clean-Arm-Server:
name: Remove copied files from server
needs:
- Build-Cabal-Arm
- Release-Docker-Arm
if: success() ||
needs.Build-Cabal-Arm.result == 'failure' ||
needs.Build-Cabal-Arm.result == 'cancelled' ||
(needs.Build-Cabal-Arm.result == 'success' && !startsWith(github.ref, 'refs/tags/v'))
runs-on: ubuntu-22.04
env:
REMOTE_DIR: ${{ needs.Build-Cabal-Arm.outputs.remotepath }}
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Remove uploaded files from server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
envs: REMOTE_DIR
script: rm -rf $REMOTE_DIR
+48 -31
View File
@@ -1,50 +1,67 @@
name: Docs
on:
push:
branches:
- main
- v[0-9]+
workflow_call:
secrets:
CACHIX_AUTH_TOKEN:
required: false
pull_request:
branches:
- main
- v[0-9]+
- main
- v[0-9]+
paths:
- .github/workflows/docs.yaml
- .github/actions/setup-nix/**
- default.nix
- nix/**
- docs/**
- '!**.md'
concurrency:
# Terminate all previous runs of the same workflow for pull requests
group: docs-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
build:
name: Build docs
runs-on: ubuntu-22.04
name: Build
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: cachix/install-nix-action@8887e596b4ee1134dae06b98d573bd674693f47c # v26
- run: nix-env -f docs/default.nix -iA build
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: docs.build.bin
- run: postgrest-docs-build
- run: git diff --exit-code HEAD locales || echo "Please commit changes to the locales/ folder after running postgrest-docs-build."
spellcheck:
name: Run spellcheck
runs-on: ubuntu-22.04
name: Spellcheck
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: cachix/install-nix-action@8887e596b4ee1134dae06b98d573bd674693f47c # v26
- run: nix-env -f docs/default.nix -iA spellcheck
- run: postgrest-docs-spellcheck
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: docs.spellcheck.bin docs.dictcheck.bin
- name: Run spellcheck
run: postgrest-docs-spellcheck
- name: Run dictcheck
run: postgrest-docs-dictcheck
dictcheck:
name: Run dictcheck
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: cachix/install-nix-action@8887e596b4ee1134dae06b98d573bd674693f47c # v26
- run: nix-env -f docs/default.nix -iA dictcheck
- run: postgrest-docs-dictcheck
linkcheck:
name: Run linkcheck
name: Linkcheck
if: github.base_ref == 'main'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- uses: cachix/install-nix-action@8887e596b4ee1134dae06b98d573bd674693f47c # v26
- run: nix-env -f docs/default.nix -iA linkcheck
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: docs.linkcheck.bin
- run: postgrest-docs-linkcheck
-70
View File
@@ -1,70 +0,0 @@
name: Loadtest
on:
push:
branches:
- main
tags:
- v*
pull_request:
branches:
- main
jobs:
Loadtest-PR-Nix:
name: Loadtest PR (Nix)
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-22.04
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
fetch-depth: 0
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: loadtest
- uses: WyriHaximus/github-action-get-previous-tag@04e8485ecb6487243907e330d522ff60f02283ce # v1.4.0
id: get-latest-tag
with:
prefix: v
- name: Run loadtest
run: |
postgrest-loadtest-against main ${{ steps.get-latest-tag.outputs.tag }}
postgrest-loadtest-report > loadtest/loadtest.md
- name: Upload report
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: loadtest.md
path: loadtest/loadtest.md
if-no-files-found: error
Loadtest-Merge-Nix:
name: Loadtest Merge (Nix)
if: ${{ github.event_name == 'push' }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
with:
fetch-depth: 0
- uses: WyriHaximus/github-action-get-previous-tag@04e8485ecb6487243907e330d522ff60f02283ce # v1.4.0
id: get-latest-tag
with:
prefix: v
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: loadtest
- name: Run loadtest
run: |
postgrest-loadtest-against ${{ steps.get-latest-tag.outputs.tag }}
postgrest-loadtest-report > loadtest/loadtest.md
- name: Upload report
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: loadtest.md
path: loadtest/loadtest.md
if-no-files-found: error
+202
View File
@@ -0,0 +1,202 @@
name: Release
on:
push:
tags:
- devel
- v*
concurrency:
# Terminate all previous runs of the same workflow for the same tag.
group: release-${{ github.ref }}
# TODO: Enable this once https://github.com/orgs/community/discussions/13015 is solved
cancel-in-progress: false
jobs:
build:
name: Build
uses: ./.github/workflows/build.yaml
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
prepare:
name: Prepare
runs-on: ubuntu-24.04
needs:
- build
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Check the version to be released
run: |
cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
if [ "${GITHUB_REF_NAME}" != "devel" ] && [ "${GITHUB_REF_NAME}" != "v$cabal_version" ]; then
echo "Tagged version ($GITHUB_REF_NAME) does not match the one in postgrest.cabal (v$cabal_version). Aborting release..."
exit 1
fi
- name: Identify changes from CHANGELOG.md
run: |
if [ "${GITHUB_REF_NAME}" == "devel" ]; then
echo "Getting unreleased changes..."
sed -n "1,/## Unreleased/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
else
version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
echo "Propper release, getting changes for version $version ..."
sed -n "1,/## \[$version\]/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
fi
echo "Relevant extract from CHANGELOG.md:"
cat CHANGES.md
- name: Save CHANGES.md as artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: release-changes
path: CHANGES.md
if-no-files-found: error
github:
name: GitHub
permissions:
contents: write
runs-on: ubuntu-24.04
needs:
- prepare
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download all artifacts
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
path: artifacts
- name: Create release bundle with archives for all builds
run: |
find artifacts -type f -iname postgrest -exec chmod +x {} \;
mkdir -p release-bundle
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-linux-static-x86-64.tar.xz" \
-C artifacts/postgrest-linux-static-x86-64 postgrest
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-macos-aarch64.tar.xz" \
-C artifacts/postgrest-macos-aarch64 postgrest
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-freebsd-x86-64.tar.xz" \
-C artifacts/postgrest-freebsd-x86-64 postgrest
tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-ubuntu-aarch64.tar.xz" \
-C artifacts/postgrest-ubuntu-aarch64 postgrest
zip --junk-paths "release-bundle/postgrest-${GITHUB_REF_NAME}-windows-x86-64.zip" \
artifacts/postgrest-windows-x86-64/postgrest.exe
- name: Save release bundle
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: release-bundle
path: release-bundle
if-no-files-found: error
- name: Publish release on GitHub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Releasing version ${GITHUB_REF_NAME} on GitHub..."
if [ "${GITHUB_REF_NAME}" == "devel" ]; then
# To replace the existing release, we must first delete the old assets,
# then modify the release, then add the new assets.
gh release view devel --json assets \
| jq -r '.assets[] | .name' \
| xargs -rn1 \
gh release delete-asset -y devel
gh release edit devel \
-t devel \
--verify-tag \
-F artifacts/release-changes/CHANGES.md \
--prerelease
gh release upload --clobber devel release-bundle/*
else
gh release create "${GITHUB_REF_NAME}" \
-t "${GITHUB_REF_NAME}" \
--verify-tag \
-F artifacts/release-changes/CHANGES.md \
release-bundle/*
fi
docker:
name: Docker Hub
runs-on: ubuntu-24.04-arm
needs:
- prepare
if: |
vars.DOCKER_REPO && vars.DOCKER_USER
env:
DOCKER_REPO: ${{ vars.DOCKER_REPO }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download x86-64 Docker image
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
name: postgrest-docker-x86-64
- name: Download aarch64 binary
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1
with:
name: postgrest-ubuntu-aarch64
- uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
username: ${{ vars.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
- name: Build aarch64 Docker image
run: |
# This only pushes the image via digest, not a tag. This will not appear
# in the image list on Docker Hub, yet. It will be later added to the main
# tag's manifest.
docker buildx build \
-t "$DOCKER_REPO/postgrest" \
--platform linux/arm64 \
--output push-by-digest=true,type=image,push=true \
--metadata-file metadata.json \
.
echo "SHA256_ARM=$(jq -r '."containerimage.digest"' metadata.json)" >> "$GITHUB_ENV"
- name: Publish images on Docker Hub
run: |
docker load -i postgrest-docker.tar.gz
docker tag postgrest:latest "$DOCKER_REPO/postgrest:${GITHUB_REF_NAME}"
docker push "$DOCKER_REPO/postgrest:${GITHUB_REF_NAME}"
docker buildx imagetools create --append \
-t "$DOCKER_REPO/postgrest:${GITHUB_REF_NAME}" \
"$DOCKER_REPO/postgrest@$SHA256_ARM"
# Only tag 'latest' for full releases
if [ "${GITHUB_REF_NAME}" != "devel" ]; then
echo "Pushing to 'latest' tag for full release of ${GITHUB_REF_NAME} ..."
docker tag postgrest:latest "$DOCKER_REPO"/postgrest:latest
docker push "$DOCKER_REPO"/postgrest:latest
docker buildx imagetools create --append \
-t "$DOCKER_REPO/postgrest:latest" \
"$DOCKER_REPO/postgrest@$SHA256_ARM"
else
echo "Skipping push to 'latest' tag for pre-release..."
fi
docker-description:
name: Docker Hub Description
runs-on: ubuntu-24.04
if: |
vars.DOCKER_REPO && vars.DOCKER_USER &&
github.ref == 'refs/tags/devel'
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: peter-evans/dockerhub-description@432a30c9e07499fd01da9f8a49f0faf9e0ca5b77 # v4.0.2
with:
username: ${{ vars.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
repository: ${{ vars.DOCKER_REPO }}/postgrest
short-description: ${{ github.event.repository.description }}
readme-filepath: ./docker-hub-readme.md
-33
View File
@@ -1,33 +0,0 @@
name: Upload Reports
on:
workflow_run:
workflows: ["Loadtest"]
types:
- completed
jobs:
upload:
name: Loadtest
permissions:
checks: write
runs-on: ubuntu-22.04
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Download from Artifacts
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
github-token: ${{ github.token }}
run-id: ${{ github.event.workflow_run.id }}
name: loadtest.md
path: artifacts
- name: Upload to GitHub Checks
uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23 # v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
sha: ${{ github.event.workflow_run.head_sha }}
name: Loadtest Results
conclusion: neutral
output: |
{"summary":""}
output_text_description_file: artifacts/loadtest.md
+132
View File
@@ -0,0 +1,132 @@
name: Test
on:
workflow_call:
secrets:
CACHIX_AUTH_TOKEN:
required: false
CODECOV_TOKEN:
required: false
pull_request:
branches:
- main
- v[0-9]+
paths:
- .github/workflows/test.yaml
- .github/workflows/report.yaml
- .github/actions/setup-nix/**
- default.nix
- nix/**
- .stylish-haskell.yaml
- cabal.project
- postgrest.cabal
- '**.hs'
- test/**
- '!**.md'
concurrency:
# Terminate all previous runs of the same workflow for pull requests
group: test-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
coverage:
name: Coverage
runs-on: ubuntu-24.04
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: tests.coverage.bin tests.testDoctests.bin tests.testSpecIdempotence.bin
- name: Run coverage (IO tests and Spec tests against PostgreSQL 15)
run: postgrest-coverage
- name: Upload coverage to codecov
uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0
with:
files: ./coverage/codecov.json
token: ${{ secrets.CODECOV_TOKEN }}
- name: Run doctests
if: always()
run: postgrest-test-doctests
- name: Check the spec tests for idempotence
if: always()
run: postgrest-test-spec-idempotence
postgres:
strategy:
fail-fast: false
matrix:
pgVersion: ["9_6", 10, 11, 12, 13, 14, 15, 16]
name: PG ${{ matrix.pgVersion }}
runs-on: ubuntu-24.04
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: tests.testSpec.bin tests.testIO.bin tests.testBigSchema.bin withTools.postgresql-${{ matrix.pgVersion }}.bin
- name: Run spec tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} postgrest-test-spec
- name: Run IO tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} postgrest-test-io -vv
- name: Run IO tests on a big schema
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} postgrest-test-big-schema -vv
memory:
name: Memory
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: memory.test.bin
- name: Run memory tests
run: postgrest-test-memory
loadtest:
name: Loadtest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: loadtest.loadtestAgainst.bin loadtest.report.bin
- uses: WyriHaximus/github-action-get-previous-tag@04e8485ecb6487243907e330d522ff60f02283ce # v1.4.0
id: get-latest-tag
with:
prefix: v
- name: Run loadtest
run: |
postgrest-loadtest-against main ${{ steps.get-latest-tag.outputs.tag }}
postgrest-loadtest-report >> "$GITHUB_STEP_SUMMARY"
View File
-68
View File
@@ -1,68 +0,0 @@
# Architecture
This document describes the high-level architecture of PostgREST.
## Bird's Eye View
```haskell
postgrest :: Request -> Either Error SQLStatement -> Response
```
On the highest level, PostgREST processes an HTTP request, if it's accepted it builds a SQL statement for it, executes it, and produces a response.
## Code Map
This section talks briefly about various important modules.
The starting point of the program is `main/Main.hs`, which calls `src/PostgREST/CLI.hs` which then calls `src/PostgREST/App.hs`.
`App.hs` is then in charge of composing the different modules.
### ApiRequest.hs
PostgREST operates over two types of resources: database relations(tables or views) and database functions; providing different representations(depending on the media type)
for them.
This module is in charge of representing the operation over an `ApiRequest` type. It parses the URL querystring following PostgREST syntax, the request headers, and the request body
(if possible it avoids parsing the body and sends it directly to the db).
A request might be rejected at this level if it's invalid, e.g. providing an unknown media type to PostgREST or using an unknown HTTP method.
### Plan.hs
Using the Schema Cache, this module enables more complex functionality(like resource embedding) by enriching the ApiRequest. It generates Plan types(`ReadPlan`, `MutatePlan`)
that then will be used to generate a SQL statement.
A request might be rejected at this level if it's invalid, e.g. by doing resource embedding on a nonexistent resource.
An OPTIONS request doesn't require a plan to be generated.
### Query.hs
This module constructs single SQL statements that can be parametrized and prepared. Only at this stage a PostgreSQL connection from the pool is used.
A query might fail(and be rollbacked) at this level if it doesn't comply to certain conditions, e.g. by not returning a single row when a ``Accept: application/vnd.pgrst.object`` header is specified.
An OPTIONS request doesn't require a query to be executed.
### Response.hs
This module constructs the HTTP response body with the right headers.
It builds the OpenAPI response using the schema cache.
### Auth.hs
This module provides functions to deal with JWT authorization.
### SchemaCache.hs
This queries the PostgreSQL system catalogs and caches the metadata into a SchemaCache type,
### AppState.hs
The state of the App which is kept across requests.
This spawns threads which are used to execute concurrent jobs.
Jobs include connection recover and a listener for the PostgreSQL LISTEN command.
+4 -4
View File
@@ -9,7 +9,7 @@ PostgREST ongoing development is only possible thanks to our Sponsors and Backer
<tr>
<td align="center" valign="middle">
<a href="https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest" target="_blank">
<img width="296px" src="static/cybertec-new.png">
<img width="296px" src="static/cybertec.svg">
</a>
</td>
<td align="center" valign="middle">
@@ -32,7 +32,7 @@ PostgREST ongoing development is only possible thanks to our Sponsors and Backer
</td>
<td align="center" valign="middle">
<a href="https://supabase.io?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage" target="_blank">
<img width="296px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/supabase.png">
<img width="296px" src="static/supabase.png">
</a>
</td>
<td align="center" valign="middle">
@@ -75,12 +75,12 @@ PostgREST ongoing development is only possible thanks to our Sponsors and Backer
<tr>
<td align="center" valign="middle">
<a href="https://www.timescale.com?utm_campaign=postgrest&utm_source=sponsor&utm_medium=referral&utm_content=github" target="_blank">
<img width="222px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/timescaledb.png">
<img width="222px" src="static/timescaledb.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://tryretool.com/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
<img max-width="222px" height="88" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/retool.png">
<img max-width="222px" height="88" src="static/retool.png">
</a>
</td>
<td align="center" valign="middle">
+135
View File
@@ -5,6 +5,135 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
## [12.2.11] - 2025-04-21
### Fixed
- #4030, Fix regression with parameter `charset=utf-8` in mediatype - @taimoorzaeem
## [12.2.10] - 2025-04-18
### Fixed
- #3889, Fix: JWT cache purging on every request decreases performance - @mkleczek
## [12.2.9] - 2025-04-16
### Fixed
- #3498, Fix incorrect parsing of the `for` parameter of the `application/vnd.pgrst.plan` media type - @taimoorzaeem
- #4014, Fix JWT cache allows old tokens after the jwt-secret is changed in a config reload - @taimoorzaeem
## [12.2.8] - 2025-02-10
### Fixed
- #3841, Log `503` client error to stderr - @taimoorzaeem
## [12.2.7] - 2025-02-03
### Fixed
- #2524, Fix schema reloading notice on windows - @diogob
## [12.2.6] - 2025-01-29
### Fixed
- #3788, Fix jwt cache does not remove expired entries - @taimoorzaeem
## [12.2.5] - 2025-01-20
### Fixed
- #3867, Fix startup for arm64 docker image - @wolfgangwalther
## [12.2.4] - 2025-01-18
### Fixed
- #3779, Always log the schema cache load time - @steve-chavez
- #3706, Fix insert with `missing=default` uses default value of domain instead of column - @taimoorzaeem
## [12.2.3] - 2024-08-01
### Fixed
- #3091, Broken link in OpenAPI description `externalDocs` - @salim-b
- #3659, Embed One-to-One relationship with different column order properly - @wolfgangwalther
- #3504, Remove `format` from `rowFilter` parameters in OpenAPI - @dantheman2865
- #3660, Fix regression that loaded the schema cache before the in-database configuration - @steve-chavez, @laurenceisla
## [12.2.2] - 2024-07-10
### Fixed
- #3093, Nested empty embeds no longer show empty values and are correctly omitted - @laurenceisla
- #3644, Make --dump-schema work with in-database pgrst.db_schemas setting - @wolfgangwalther
- #3644, Show number of timezones in schema cache load report - @wolfgangwalther
- #3644, List correct enum options in OpenApi output when multiple types with same name are present - @wolfgangwalther
- #3523, Fix schema cache loading retry without backoff - @steve-chavez
## [12.2.1] - 2024-06-27
### Fixed
- #3147, Don't reload schema cache on every listener failure - @steve-chavez
### Documentation
- #3592, Architecture diagram now supports dark mode and has links - @laurenceisla
- #3616, The schema isolation diagram now supports dark mode and uses well-known schemas - @laurenceisla
## [12.2.0] - 2024-06-11
### Added
- #2887, Add Preference `max-affected` to limit affected resources - @taimoorzaeem
- #3171, Add an ability to dump config via admin API - @skywriter
- #3171, #3046, Log schema cache stats to stderr - @steve-chavez
- #3210, Dump schema cache through admin API - @taimoorzaeem
- #2676, Performance improvement on bulk json inserts, around 10% increase on requests per second by removing `json_typeof` from write queries - @steve-chavez
- #3435, Add log-level=debug, for development purposes - @steve-chavez
- #1526, Add `/metrics` endpoint on admin server - @steve-chavez
- Exposes connection pool metrics, schema cache metrics
- #3404, Show the failed MESSAGE or DETAIL in the `details` field of the `PGRST121` (could not parse RAISE 'PGRST') error - @laurenceisla
- #3404, Show extra information in the `PGRST121` (could not parse RAISE 'PGRST') error - @laurenceisla
+ Shows the failed MESSAGE or DETAIL in the `details` field
+ Shows the correct JSON format in the `hints` field
- #3340, Log when the LISTEN channel gets a notification - @steve-chavez
- #3184, Log full pg version to stderr on connection - @steve-chavez
- #3242. Add config `db-hoisted-tx-settings` to apply only hoisted function settings - @taimoorzaeem
- #3214, #3229 Log connection pool events on log-level=debug - @steve-chavez, @laurenceisla
### Fixed
- #3237, Dump media handlers and timezones with --dump-schema - @wolfgangwalther
- #3323, #3324, Don't hide error on LISTEN channel failure - @steve-chavez
- #3330, Incorrect admin server `/ready` response on slow schema cache loads - @steve-chavez
- #3345, Fix in-database configuration values not loading for `pgrst.server_trace_header` and `pgrst.server_cors_allowed_origins` - @laurenceisla
- #3404, Clarify the `PGRST121` (could not parse RAISE 'PGRST') error message - @laurenceisla
- #3267, Fix wrong `503 Service Unavailable` on pg error `53400` - @taimoorzaeem
- #2985, Fix not adding `application_name` on all connection strings - @steve-chavez
- #3424, Admin `/live` and `/ready` now differentiates a failure as 500 status - @steve-chavez
+ 503 status is still given when postgREST is in a recovering state
- #3478, Media Types are parsed case insensitively - @develop7
- #3533, #3536, Fix listener silently failing on read replica - @steve-chavez
+ If the LISTEN connection fails, it's retried with exponential backoff
- #3414, Force listener to connect to read-write instances using `target_session_attrs` - @steve-chavez
- #3255, Fix incorrect `413 Request Entity Too Large` on pg errors `54*` - @taimoorzaeem
- #3549, Remove verbosity from error logs starting with "An error occurred..." and replacing it with "Failed to..." - @laurenceisla
### Deprecated
- Support for PostgreSQL versions 9.6, 10 and 11 is deprecated. From this on version onwards, PostgREST will only support non-end-of-life PostgreSQL versions. See https://www.postgresql.org/support/versioning/.
- `Prefer: params=single-object` is deprecated. Use [a function with a single unnamed JSON parameter](https://postgrest.org/en/latest/references/api/functions.html#function-single-json) instead. - @steve-chavez
### Documentation
- #3289, Add dark mode. Can be toggled by a button in the bottom right corner. - @laurenceisla
- #3384, Add architecture diagram and documentation - @steve-chavez
## [12.0.3] - 2024-05-09
### Fixed
@@ -72,6 +201,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Removed `application/octet-stream`, `text/plain`, `text/xml` [builtin support for scalar results](https://postgrest.org/en/v11.1/references/api/resource_representation.html#scalar-function-response-format) - @steve-chavez
- Removed default `application/openapi+json` media type for [db-root-spec](https://postgrest.org/en/v11.1/references/configuration.html#db-root-spec) - @steve-chavez
- Removed [db-use-legacy-gucs](https://postgrest.org/en/v11.2/references/configuration.html#db-use-legacy-gucs) - @laurenceisla
+ All PostgreSQL versions now use GUCs in JSON format for [Headers, Cookies and JWT claims](https://postgrest.org/en/v12/references/transactions.html#request-headers-cookies-and-jwt-claims).
## [11.2.2] - 2023-10-25
@@ -375,6 +505,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #2312, Using `Prefer: return=representation` no longer returns a `Location` header - @laurenceisla
- #1984, For the cases where one to one relationships are detected, json objects will be returned instead of json arrays of length 1
+ If you wish to override this behavior, you can use computed relationships to return arrays again
+ You can get the newly detected one-to-one relationships by using the `--dump-schema` option and filtering with [jq](https://github.com/jqlang/jq).
```
./postgrest --dump-schema \
| jq '[.dbRelationships | .[] | .[1] | .[] | select(.relCardinality.tag == "O2O" and .relFTableIsView == false and .relTableIsView == false) | del(.relFTableIsView,.relTableIsView,.tag,.relIsSelf)]'
```
## [9.0.1] - 2022-06-03
@@ -1,6 +1,8 @@
# PostgREST docker hub image
# PostgREST Docker Hub image for aarch64.
# The x86-64 is a single-static-binary image built via Nix, see:
# nix/tools/docker/README.md
FROM ubuntu:noble@sha256:3f85b7caad41a95462cf5b787d8a04604c8262cdcdf9a472b8c52ef83375fe15 AS postgrest
FROM ubuntu:noble@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782 AS postgrest
RUN apt-get update -y \
&& apt install -y --no-install-recommends libpq-dev zlib1g-dev jq gcc libnuma-dev \
@@ -8,6 +10,7 @@ RUN apt-get update -y \
&& rm -rf /var/lib/apt/lists/*
COPY postgrest /usr/bin/postgrest
RUN chmod +x /usr/bin/postgrest
EXPOSE 3000
+5 -11
View File
@@ -1,8 +1,6 @@
![Logo](static/bigger-logo.png "Logo")
![Logo](static/postgrest.png "Logo")
[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)](https://www.patreon.com/postgrest)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/postgrest)
[![Join the chat at https://gitter.im/begriffs/postgrest](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/begriffs/postgrest)
[![Docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](http://postgrest.org)
[![Docker Stars](https://img.shields.io/docker/pulls/postgrest/postgrest.svg)](https://hub.docker.com/r/postgrest/postgrest/)
[![Build Status](https://github.com/postgrest/postgrest/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/PostgREST/postgrest/actions?query=branch%3Amain)
@@ -20,7 +18,7 @@ API than you are likely to write from scratch.
<tr>
<td align="center" valign="middle">
<a href="https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest" target="_blank">
<img width="296px" src="static/cybertec-new.png">
<img width="296px" src="static/cybertec.svg">
</a>
</td>
<td align="center" valign="middle">
@@ -43,7 +41,7 @@ API than you are likely to write from scratch.
</td>
<td align="center" valign="middle">
<a href="https://supabase.io?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage" target="_blank">
<img width="296px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/supabase.png">
<img width="296px" src="static/supabase.png">
</a>
</td>
<td align="center" valign="middle">
@@ -68,7 +66,7 @@ Big thanks to our sponsors! You can join them by supporting PostgREST on [Patreo
```
## [Documentation](http://postgrest.org)
Latest documentation is at [postgrest.org](http://postgrest.org). You can contribute to the docs in [PostgREST/postgrest-docs](https://github.com/PostgREST/postgrest-docs).
Latest documentation is at [postgrest.org](http://postgrest.org). You can contribute to the docs in [PostgREST/postgrest/docs](https://github.com/PostgREST/postgrest/tree/main/docs).
## Performance
@@ -145,11 +143,7 @@ and the [API guide](http://postgrest.org/en/stable/api.html).
## Supporting development
You can help PostgREST ongoing maintenance and development by:
- Making a regular donation through Patreon https://www.patreon.com/postgrest
- Alternatively, you can make a one-time donation via Paypal https://www.paypal.me/postgrest
You can help PostgREST ongoing maintenance and development by making a regular donation through Patreon https://www.patreon.com/postgrest
Every donation will be spent on making PostgREST better for the whole community.
+4
View File
@@ -0,0 +1,4 @@
packages: postgrest.cabal
tests: true
package *
ghc-options: -split-sections
+1 -1
View File
@@ -1 +1 @@
index-state: hackage.haskell.org 2023-10-13T13:54:33Z
index-state: hackage.haskell.org 2025-02-01T14:59:33Z
-20
View File
@@ -1,20 +0,0 @@
-- Settings to allow building with plain cabal. If this was
-- named just cabal.project, it would interfere with the default
-- nix build.
packages: .
-- Example of depending on a forked repository (the same dependency
-- would be mentioned in nix/overlays/haskell-packages.nix and
-- stack.yaml, and should refer to a main branch commit of the
-- repository.
--
-- source-repository-package
-- type: git
-- location: https://github.com/PostgREST/hasql-pool.git
-- tag: 4d462c4d47d762effefc7de6c85eaed55f144f1d
source-repository-package
type: git
location: https://github.com/PostgREST/postgresql-libpq.git
tag: 890a0a16cf57dd401420fdc6c7d576fb696003bc
+28 -49
View File
@@ -1,12 +1,23 @@
{ system ? builtins.currentSystem }:
{ system ? builtins.currentSystem
, compiler ? "ghc948"
, # Commit of the Nixpkgs repository that we want to use.
nixpkgsVersion ? import nix/nixpkgs-version.nix
, # Nix files that describe the Nixpkgs repository. We evaluate the expression
# using `import` below.
nixpkgs ? let inherit (nixpkgsVersion) owner repo rev tarballHash; in
builtins.fetchTarball {
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz";
sha256 = tarballHash;
}
}:
let
name =
"postgrest";
compiler =
"ghc924";
# PostgREST source files, filtered based on the rules in the .gitignore files
# and file extensions. We want to include as litte as possible, as the files
# added here will increase the space used in the Nix store and trigger the
@@ -16,18 +27,6 @@ let
(pkgs.gitignoreSource ./.)
[ ".cabal" ".hs" ".lhs" "LICENSE" ];
# Commit of the Nixpkgs repository that we want to use.
nixpkgsVersion =
import nix/nixpkgs-version.nix;
# Nix files that describe the Nixpkgs repository. We evaluate the expression
# using `import` below.
nixpkgs =
builtins.fetchTarball {
url = "https://github.com/nixos/nixpkgs/archive/${nixpkgsVersion.rev}.tar.gz";
sha256 = nixpkgsVersion.tarballHash;
};
allOverlays =
import nix/overlays;
@@ -36,10 +35,10 @@ let
allOverlays.build-toolbox
allOverlays.checked-shell-script
allOverlays.gitignore
allOverlays.postgis
(allOverlays.postgresql-default { inherit patches; })
allOverlays.postgresql-libpq
allOverlays.postgresql-legacy
allOverlays.postgresql-future
allOverlays.postgis
(allOverlays.haskell-packages { inherit compiler; })
allOverlays.slocat
];
@@ -50,52 +49,28 @@ let
postgresqlVersions =
[
{
name = "postgresql-16";
postgresql = pkgs.postgresql_16.withPackages (p: [
p.postgis
(p.pg_safeupdate.overrideAttrs (old: {
installPhase = ''
mkdir -p $out/bin
cp safeupdate.dylib safeupdate.so || true
install -D safeupdate.so -t $out/lib
'';
}))
]);
}
{ name = "postgresql-16"; postgresql = pkgs.postgresql_16.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-15"; postgresql = pkgs.postgresql_15.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-14"; postgresql = pkgs.postgresql_14.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-13"; postgresql = pkgs.postgresql_13.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-12"; postgresql = pkgs.postgresql_12.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-11"; postgresql = pkgs.postgresql_11.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-10"; postgresql = pkgs.postgresql_10.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-9.6"; postgresql = pkgs.postgresql_9_6.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-9_6"; postgresql = pkgs.postgresql_9_6.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
];
patches =
pkgs.callPackage nix/patches { };
# Dynamic derivation for PostgREST
postgrest =
pkgs.haskell.packages."${compiler}".callCabal2nix name src { };
# Functionality that derives a fully static Haskell package based on
# nh2/static-haskell-nix
staticHaskellPackage =
import nix/static-haskell-package.nix { inherit nixpkgs system compiler patches allOverlays; };
# Static executable.
postgrestStatic =
lib.justStaticExecutables (lib.dontCheck (staticHaskellPackage name src).package);
packagesStatic = (staticHaskellPackage name src).survey;
staticHaskellPackage = import nix/static.nix { inherit compiler name pkgs src; };
# Options passed to cabal in dev tools and tests
devCabalOptions =
"-f dev --test-show-detail=direct";
profiledHaskellPackages =
pkgs.haskell.packages."${compiler}".extend (self: super:
pkgs.haskell.packages."${compiler}".extend (_: super:
{
mkDerivation =
args:
@@ -136,12 +111,16 @@ rec {
pkgs.callPackage nix/tools/cabalTools.nix { inherit devCabalOptions postgrest; };
withTools =
pkgs.callPackage nix/tools/withTools.nix { inherit cabalTools devCabalOptions postgresqlVersions postgrest; };
pkgs.callPackage nix/tools/withTools.nix { inherit postgresqlVersions postgrest; };
# Development tools.
devTools =
pkgs.callPackage nix/tools/devTools.nix { inherit tests style devCabalOptions hsie withTools; };
# Documentation tools.
docs =
pkgs.callPackage nix/tools/docs.nix { };
# Load testing tools.
loadtest =
pkgs.callPackage nix/tools/loadtest.nix { inherit withTools; };
@@ -172,8 +151,8 @@ rec {
};
} // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux rec {
# Static executable.
inherit postgrestStatic;
inherit packagesStatic;
inherit (staticHaskellPackage) postgrestStatic;
inherit (staticHaskellPackage) packagesStatic;
# Docker images and loading script.
docker =
@@ -1,8 +1,6 @@
# PostgREST
[![Join the chat at https://gitter.im/begriffs/postgrest](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/begriffs/postgrest)
[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)](https://www.patreon.com/postgrest)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/postgrest)
[![Docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](http://postgrest.org)
[![Build Status](https://github.com/postgrest/postgrest/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/PostgREST/postgrest/actions?query=branch%3Amain)
@@ -17,7 +15,7 @@ write from scratch.
<tr>
<td align="center" valign="middle">
<a href="https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest" target="_blank">
<img width="296px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/cybertec-new.png">
<img width="296px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/cybertec.svg">
</a>
</td>
<td align="center" valign="middle">
@@ -68,3 +66,5 @@ The image is built from scratch using
no commands are listed in the image history. See the [PostgREST
respository](https://github.com/PostgREST/postgrest/tree/main/nix/tools/docker) for
details on the build process and how to inspect the image.
This does not apply to the arm64 variant, which is based on Ubuntu.
+1 -1
View File
@@ -5,4 +5,4 @@ Pipfile.lock
_diagrams/db.pdf
misspellings
unuseddict
.history
*.mo
+19 -11
View File
@@ -2,19 +2,27 @@
PostgREST docs use the reStructuredText format, check this [cheatsheet](https://github.com/ralsina/rst-cheatsheet/blob/master/rst-cheatsheet.rst) to get acquainted with it.
To build the docs locally, use [nix](https://nixos.org/nix/):
```bash
nix-shell
```
Once in the nix-shell you have the following commands available:
- `postgrest-docs-build`: Build the docs.
- `postgrest-docs-serve`: Build the docs and start a livereload server on `http://localhost:5500`.
- `postgrest-docs-spellcheck`: Run aspell.
To build the docs locally, see [the Nix development readme](/nix/README.md#documentation).
## Documentation structure
This documentation is structured according to tutorials-howtos-topics-references. For more details on the rationale of this structure,
see https://www.divio.com/blog/documentation.
## Translating
To create `.po` files for translation into a new language pass the language code as the first argument to `postgrest-docs-build`.
Example to add German/de:
```
postgrest-docs-build de
```
The livereload server also supports a language/locale argument to show the translated docs during translation:
```
postgrest-docs-serve de
```
Spellcheck is currently only available for the default language.
+8 -26
View File
@@ -5,38 +5,20 @@ The ER diagrams were created with https://github.com/BurntSushi/erd/.
You can go download erd from https://github.com/BurntSushi/erd/releases and then do:
```bash
./erd_static-x86-64 -i film.er -o ../_static/film.png
./erd_static-x86-64 -i ./er/film.er -o ../_static/film.png
```
The fonts used belong to the GNU FreeFont family. You can download them here: http://ftp.gnu.org/gnu/freefont/
## LaTeX
## UML
The schema structure diagram is done with LaTeX. You can use a GUI like https://www.mathcha.io/editor to create the .tex file.
The UML diagrams are created with https://plantuml.com/.
Then use this command to generate the png file.
PlantUML only creates one diagram per file.
That's why we need to create another one for dark mode.
For example, for the file [uml/arch.uml](uml/arch.uml) there's [uml/dark/arch-dark.uml](uml/dark/arch-dark.uml) which includes the first one:
```bash
pdflatex --shell-escape -halt-on-error db.tex
## and move it to the static folder(it's not easy to do it in one go with the pdflatex)
mv db.png ../_static/
```
LaTeX is used because it's a tweakable plain text format.
You can install the full latex suite with `nix`:
```
nix-env -iA texlive.combined.scheme-full
```
To tweak the file with a live reload environment use:
```bash
# open the pdf(zathura used as an example)
zathura db.pdf &
# live reload with entr
echo db.tex | entr pdflatex --shell-escape -halt-on-error db.tex
plantuml -tsvg uml/arch.uml -o ../../_static
plantuml -tsvg -darkmode uml/dark/arch-dark.uml -o ../../../_static
```
-71
View File
@@ -1,71 +0,0 @@
\documentclass[convert]{standalone}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage{mathdots}
\usepackage{yhmath}
\usepackage{cancel}
\usepackage{color}
\usepackage{siunitx}
\usepackage{array}
\usepackage{multirow}
\usepackage{amssymb}
\usepackage{gensymb}
\usepackage{tabularx}
\usepackage{booktabs}
\usetikzlibrary{fadings}
\usetikzlibrary{patterns}
\usetikzlibrary{shadows.blur}
\usetikzlibrary{shapes}
\begin{document}
\newcommand\customScale{0.35}
\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1, scale=\customScale, every node/.style={scale=\customScale}]
%Shape: Can [id:dp7234864758664346]
\draw [fill={rgb, 255:red, 47; green, 97; blue, 144 } ,fill opacity=1 ] (497.5,51.5) -- (497.5,255.5) .. controls (497.5,275.66) and (423.18,292) .. (331.5,292) .. controls (239.82,292) and (165.5,275.66) .. (165.5,255.5) -- (165.5,51.5) .. controls (165.5,31.34) and (239.82,15) .. (331.5,15) .. controls (423.18,15) and (497.5,31.34) .. (497.5,51.5) .. controls (497.5,71.66) and (423.18,88) .. (331.5,88) .. controls (239.82,88) and (165.5,71.66) .. (165.5,51.5) ;
%Shape: Rectangle [id:dp7384065579958246]
\draw [fill={rgb, 255:red, 236; green, 227; blue, 227 } ,fill opacity=1 ] (189,115) -- (252.5,115) -- (252.5,155) -- (189,155) -- cycle ;
%Shape: Rectangle [id:dp24763906430298177]
\draw [fill={rgb, 255:red, 236; green, 227; blue, 227 } ,fill opacity=1 ] (292,118) -- (362,118) -- (362,158) -- (292,158) -- cycle ;
%Shape: Rectangle [id:dp3775601612537265]
\draw [fill={rgb, 255:red, 236; green, 227; blue, 227 } ,fill opacity=1 ] (397,114) -- (467,114) -- (467,154) -- (397,154) -- cycle ;
%Shape: Rectangle [id:dp7071457022893852]
\draw [fill={rgb, 255:red, 248; green, 231; blue, 28 } ,fill opacity=1 ] (269,199) -- (397.5,199) -- (397.5,273) -- (269,273) -- cycle ;
%Straight Lines [id:da8846759047437789]
\draw (268,234) -- (226.44,155.77) ;
\draw [shift={(225.5,154)}, rotate = 422.02] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Straight Lines [id:da6908444738113828]
\draw (309.5,198) -- (307.6,161) ;
\draw [shift={(307.5,159)}, rotate = 447.06] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Straight Lines [id:da7168757864413169]
\draw (398.5,233) -- (431.72,154.84) ;
\draw [shift={(432.5,153)}, rotate = 473.03] [color={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.75] (10.93,-3.29) .. controls (6.95,-1.4) and (3.31,-0.3) .. (0,0) .. controls (3.31,0.3) and (6.95,1.4) .. (10.93,3.29) ;
%Up Down Arrow [id:dp14059754167108496]
\draw [fill={rgb, 255:red, 126; green, 211; blue, 33 } ,fill opacity=1 ] (312.5,288.5) -- (330,273) -- (347.5,288.5) -- (338.75,288.5) -- (338.75,319.5) -- (347.5,319.5) -- (330,335) -- (312.5,319.5) -- (321.25,319.5) -- (321.25,288.5) -- cycle ;
% Text Node
\draw (201,129) node [anchor=north west][inner sep=0.75pt] [align=left] {tables};
% Text Node
\draw (307,130) node [anchor=north west][inner sep=0.75pt] [align=left ] {tables};
% Text Node
\draw (414,127) node [anchor=north west][inner sep=0.75pt] [align=left] {tables};
% Text Node
\draw (272,203) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 0; green, 0; blue, 0 } ,opacity=1 ] [align=center] { \\ views \\ + \\ \ \ stored procedures};
% Text Node
\draw (322,178) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{api}};
% Text Node
\draw (190,97) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{internal}};
% Text Node
\draw (300,99) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{private}};
% Text Node
\draw (417,101) node [anchor=north west][inner sep=0.75pt] [color={rgb, 255:red, 255; green, 255; blue, 255 } ,opacity=1 ] [align=left] {\large\textbf{core}};
% Text Node
\draw (358,306) node [anchor=north west][inner sep=0.75pt] [align=left] {REST};
\end{tikzpicture}
\end{document}
+84
View File
@@ -0,0 +1,84 @@
@startuml
skinparam backgroundColor transparent
package "PostgREST" {
() HTTP as HTTPAPI
HTTPAPI - [Auth]
[Auth] -r.> [ApiRequest]
[ApiRequest] -r.> [Plan]
[Plan] -r.> [Query]
[Query] - () "Connection Pool" : "\t"
[Plan] -u-> [Schema Cache]:uses
[Schema Cache] <- () Listener : reloads
() HTTP as HTTPADMIN
[Admin] -r- () HTTPADMIN
[Config] -l- () CLI
[Config] <-r~ Listener
HTTPADMIN -[hidden]r- CLI
[Schema Cache] -l[hidden]- [Config]
[Schema Cache] -l[hidden]- [Admin]
[Schema Cache] -l[hidden]- CLI
}
database "PostgreSQL" {
node Authorization {
rectangle "Roles, GRANT, RLS"
}
node "API schema" as API {
rectangle "Functions, Views"
}
rectangle "Tables, extensions" as tbs
API -d- tbs
API -l[hidden]- Authorization
}
:user:
hexagon Proxy
:user: .r-> Proxy
HTTPAPI <.l- Proxy
:operator: .d-> HTTPADMIN
:operator: .d-> CLI
PostgreSQL <.developer : "\t"
Listener -r.> "PostgreSQL"
"Connection Pool" -r.> "PostgreSQL" : "\t\t"
note bottom of Auth
Authenticates the user request
end note
note bottom of ApiRequest
Parses the URL syntax
end note
note bottom of Query
Generates the SQL
end note
note top of Listener
LISTEN session
end note
url of Admin is [[../references/admin_server.html#admin-server]]
url of API is [[../explanations/schema_isolation.html]]
url of Auth is [[../references/auth.html#authn]]
url of Authorization is [[../explanations/db_authz.html]]
url of CLI is [[../references/cli.html#cli]]
url of "Connection Pool" is [[../references/connection_pool.html]]
url of Config is [[../references/configuration.html#configuration]]
url of HTTPADMIN is [[https://aosabook.org/en/posa/warp.html]]
url of HTTPAPI is [[https://aosabook.org/en/posa/warp.html]]
url of Listener is [[../references/listener.html#listener]]
url of Proxy is [[../explanations/nginx.html]]
url of "Schema Cache" is [[../references/schema_cache.html#schema-cache]]
@enduml
+3
View File
@@ -0,0 +1,3 @@
@startuml
!include ../arch.uml
@enduml
+3
View File
@@ -0,0 +1,3 @@
@startuml
!include ../sch-iso.uml
@enduml
+29
View File
@@ -0,0 +1,29 @@
@startuml
skinparam backgroundColor transparent
skinparam linetype ortho
skinparam node {
backgroundColor transparent
borderThickness 1
}
database "PostgreSQL" {
node public {
rectangle tables_public as "tables"
}
node extensions as "**extensions**" {
}
node API as "<size:20>api" {
rectangle vf_api as "views + functions"
}
tables_public <-- vf_api
extensions <-- vf_api
}
vf_api <-[thickness=3]-> () PostgREST
@enduml
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

+1
View File
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

+1
View File
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

+60
View File
@@ -28,6 +28,7 @@ div.line-block {
#sponsors img{
margin: 10px;
width: 13em; /* ".. image::" does not apply width properly to SVGs */
}
#thanks{
@@ -93,3 +94,62 @@ div.line-block {
#api span.caption-text {
display: none;
}
/* Tweaks for dark mode from extension: sphinx-rtd-dark-theme */
html[data-theme="dark"] .highlight {
background-color: #17181c !important;
}
html[data-theme="dark"] .sphinx-tabs-tab {
color: var(--dark-link-color);
}
html[data-theme="dark"] .sphinx-tabs-panel {
border: 1px solid #404040;
border-top: 0;
background: #141414;
}
html[data-theme="dark"] .sphinx-tabs-tab[aria-selected="true"] {
border: 1px solid #404040;
border-bottom: 1px solid #141414;
background-color: #141414;
}
html[data-theme="dark"] [role="tablist"] {
border-bottom: 1px solid #404040;
}
html[data-theme="dark"] .btn-neutral {
color: white !important;
}
html[data-theme="dark"] .img-dark {
display: inline;
}
html:not([data-theme="dark"]) .img-dark {
display: none;
}
html[data-theme="dark"] .img-light {
display: none;
}
html:not([data-theme="dark"]) .img-light {
display: inline;
}
html[data-theme="dark"] .img-translucent img {
background-color: #cccccc;
}
.img-translucent img {
transition: background-color 0.3s;
margin-bottom: 24px;
}
.svg-container-md {
max-width: 400px;
}
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="411px" preserveAspectRatio="none" style="width:315px;height:411px;" version="1.1" viewBox="0 0 315 411" width="315px" zoomAndPan="magnify"><defs/><g><!--cluster PostgreSQL--><g id="cluster_PostgreSQL"><path d="M6,16 C6,6 152,6 152,6 C152,6 298,6 298,16 L298,309.14 C298,319.14 152,319.14 152,319.14 C152,319.14 6,319.14 6,309.14 L6,16 " fill="none" style="stroke:#E7E7E7;stroke-width:1.0;"/><path d="M6,16 C6,26 152,26 152,26 C152,26 298,26 298,16 " fill="none" style="stroke:#E7E7E7;stroke-width:1.0;"/><text fill="#FFFFFF" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="81.375" x="111.3125" y="42.9659">PostgreSQL</text></g><!--cluster public--><g id="cluster_public"><polygon fill="none" points="30,77,40,67,150,67,150,155.07,140,165.07,30,165.07,30,77" style="stroke:#E7E7E7;stroke-width:1.0;"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="140" x2="150" y1="77" y2="67"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="30" x2="140" y1="77" y2="77"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="140" x2="140" y1="77" y2="165.07"/><text fill="#FFFFFF" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="44.625" x="63.6875" y="94.9659">public</text></g><!--cluster API--><g id="cluster_API"><polygon fill="none" points="68,199.07,78,189.07,236,189.07,236,285.14,226,295.14,68,295.14,68,199.07" style="stroke:#E7E7E7;stroke-width:1.0;"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="226" x2="236" y1="199.07" y2="189.07"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="68" x2="226" y1="199.07" y2="199.07"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="226" x2="226" y1="199.07" y2="295.14"/><text fill="#FFFFFF" font-family="sans-serif" font-size="20" font-weight="bold" lengthAdjust="spacing" textLength="29.875" x="133.0625" y="223.45">api</text></g><!--entity tables_public--><g id="elem_tables_public"><rect fill="#313139" height="39.0679" rx="2.5" ry="2.5" style="stroke:#E7E7E7;stroke-width:0.5;" width="61" x="69.5" y="110"/><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="41" x="79.5" y="134.9659">tables</text></g><!--entity extensions--><g id="elem_extensions"><polygon fill="none" points="165.81,115,175.81,105,282.185,105,282.185,144.0679,272.185,154.0679,165.81,154.0679,165.81,115" style="stroke:#E7E7E7;stroke-width:1.0;"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="272.185" x2="282.185" y1="115" y2="105"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="165.81" x2="272.185" y1="115" y2="115"/><line style="stroke:#E7E7E7;stroke-width:1.0;" x1="272.185" x2="272.185" y1="115" y2="154.0679"/><text fill="#FFFFFF" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="76.375" x="180.81" y="139.9659">extensions</text></g><!--entity vf_api--><g id="elem_vf_api"><rect fill="#313139" height="39.0679" rx="2.5" ry="2.5" style="stroke:#E7E7E7;stroke-width:0.5;" width="136" x="84" y="240.07"/><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="116" x="94" y="265.0359">views + functions</text></g><!--entity PostgREST--><g id="elem_PostgREST"><ellipse cx="152" cy="371.14" fill="#313139" rx="8" ry="8" style="stroke:#E7E7E7;stroke-width:0.5;"/><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="70" x="117" y="403.1059">PostgREST</text></g><!--reverse link tables_public to vf_api--><g id="link_tables_public_vf_api"><path d="M107.25,155.29 C107.25,179.74 107.25,215.13 107.25,239.67 " fill="none" id="tables_public-backto-vf_api" style="stroke:#E7E7E7;stroke-width:1.0;"/><polygon fill="#E7E7E7" points="107.25,149.29,103.25,158.29,107.25,154.29,111.25,158.29,107.25,149.29" style="stroke:#E7E7E7;stroke-width:1.0;"/></g><!--reverse link extensions to vf_api--><g id="link_extensions_vf_api"><path d="M192.91,160.31 C192.91,185.07 192.91,216.68 192.91,239.61 " fill="none" id="extensions-backto-vf_api" style="stroke:#E7E7E7;stroke-width:1.0;"/><polygon fill="#E7E7E7" points="192.91,154.31,188.91,163.31,192.91,159.31,196.91,163.31,192.91,154.31" style="stroke:#E7E7E7;stroke-width:1.0;"/></g><!--link vf_api to PostgREST--><g id="link_vf_api_PostgREST"><path d="M152,285.55 C152,309.98 152,338.34 152,356.18 " fill="none" id="vf_api-PostgREST" style="stroke:#E7E7E7;stroke-width:3.0;"/><polygon fill="#E7E7E7" points="152,279.55,148,288.55,152,284.55,156,288.55,152,279.55" style="stroke:#E7E7E7;stroke-width:3.0;"/><polygon fill="#E7E7E7" points="152,362.18,156,353.18,152,357.18,148,353.18,152,362.18" style="stroke:#E7E7E7;stroke-width:3.0;"/></g><!--SRC=[KypCIyufJKbLqDFJBqxEqCqipjShpSq10000]--></g></svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

+1
View File
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

+17 -3
View File
@@ -32,6 +32,7 @@ extensions = [
"sphinx_tabs.tabs",
"sphinx_copybutton",
"sphinxext.opengraph",
"sphinx_rtd_dark_mode",
]
# Add any paths that contain templates here, relative to this directory.
@@ -49,7 +50,7 @@ source_suffix = ".rst"
master_doc = "index"
# This is overriden by readthedocs with the version tag anyway
version = "12.0"
version = "12.2"
# To avoid repetition in <title> we set this to an empty string.
release = ""
@@ -291,12 +292,25 @@ def setup(app):
app.add_css_file("css/custom.css")
# taken from https://github.com/sphinx-doc/sphinx/blob/82dad44e5bd3776ecb6fd8ded656bc8151d0e63d/sphinx/util/requests.py#L42
user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20100101 Firefox/25.0"
user_agent = (
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0"
)
linkcheck_ignore = [
# Odd SSL error
r"https://www.dripdepot.com",
# New GitHub UI delays comment load, so anchor fails
r"https://github.com/.*#issuecomment",
# Random 500 Internal Server Error
r"https://jwt.io",
]
# sphinx-tabs configuration
sphinx_tabs_disable_tab_closing = True
# sphinx_rtd_dark_mode configuration
default_dark_mode = False
# sphinxext-opengraph configuration
ogp_image = "_images/logo.png"
-100
View File
@@ -1,100 +0,0 @@
let
# Commit of the Nixpkgs repository that we want to use.
nixpkgsVersion = {
date = "2023-03-25";
rev = "dbf5322e93bcc6cfc52268367a8ad21c09d76fea";
tarballHash = "0lwk4v9dkvd28xpqch0b0jrac4xl9lwm6snrnzx8k5lby72kmkng";
};
# Nix files that describe the Nixpkgs repository. We evaluate the expression
# using `import` below.
pkgs = import
(fetchTarball {
url = "https://github.com/nixos/nixpkgs/archive/${nixpkgsVersion.rev}.tar.gz";
sha256 = nixpkgsVersion.tarballHash;
})
{ };
python = pkgs.python3.withPackages (ps: [ ps.sphinx ps.sphinx_rtd_theme ps.livereload ps.sphinx-tabs ps.sphinx-copybutton ps.sphinxext-opengraph ]);
in
rec {
inherit pkgs;
build =
pkgs.writeShellScriptBin "postgrest-docs-build"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
# clean previous build, otherwise some errors might be supressed
rm -rf _build
${python}/bin/sphinx-build --color -W -b html -a -n . _build
'';
serve =
pkgs.writeShellScriptBin "postgrest-docs-serve"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
# livereload_docs.py needs to find "sphinx-build"
PATH=${python}/bin:$PATH
${python}/bin/python livereload_docs.py
'';
spellcheck =
pkgs.writeShellScriptBin "postgrest-docs-spellcheck"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
FILES=$(find . -type f -iname '*.rst' | tr '\n' ' ')
cat $FILES \
| grep -v '^\(\.\.\| \)' \
| sed 's/`.*`//g' \
| ${pkgs.aspell}/bin/aspell -d ${pkgs.aspellDicts.en}/lib/aspell/en_US -p ./postgrest.dict list \
| sort -f \
| tee misspellings
test ! -s misspellings
'';
# dictcheck detects obsolete entries in postgrest.dict, that are not used anymore
dictcheck =
pkgs.writeShellScriptBin "postgrest-docs-dictcheck"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
FILES=$(find . -type f -iname '*.rst' | tr '\n' ' ')
cat postgrest.dict \
| tail -n+2 \
| tr '\n' '\0' \
| xargs -0 -n 1 -i \
sh -c "grep \"{}\" $FILES > /dev/null || echo \"{}\"" \
| tee unuseddict
test ! -s unuseddict
'';
linkcheck =
pkgs.writeShellScriptBin "postgrest-docs-linkcheck"
''
set -euo pipefail
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/docs"
${python}/bin/sphinx-build --color -b linkcheck . _build
'';
check =
pkgs.writeShellScriptBin "postgrest-docs-check"
''
set -euo pipefail
${build}/bin/postgrest-docs-build
${dictcheck}/bin/postgrest-docs-dictcheck
${linkcheck}/bin/postgrest-docs-linkcheck
${spellcheck}/bin/postgrest-docs-spellcheck
'';
}
+11 -10
View File
@@ -8,9 +8,6 @@ Community Tutorials
* `PostgREST + Auth0: Create REST API in mintutes, and add social login using Auth0 <https://samkhawase.com/blog/postgrest/>`_ - A step-by-step tutorial to show how to dockerize and integrate Auth0 to PostgREST service.
* `PostgREST + PostGIS API tutorial in 5 minutes <https://gis-ops.com/postgrest-postgis-api-tutorial-geospatial-api-in-5-minutes/>`_ -
In this tutorial, GIS • OPS shows how to perform PostGIS calculations through PostgREST :ref:`s_procs` interface.
* `"CodeLess" backend using postgres, postgrest and oauth2 authentication with keycloak <https://www.mathieupassenaud.fr/codeless_backend/>`_ -
A step-by-step tutorial for using PostgREST with KeyCloak(hosted on a managed service).
@@ -20,7 +17,9 @@ Community Tutorials
* `Build data-driven applications with Workers and PostgreSQL <https://developers.cloudflare.com/workers/tutorials/postgres/>`_ - A tutorial on how to integrate with PostgREST and PostgreSQL using Cloudflare Workers.
.. * `A poor man's API <https://blog.frankel.ch/poor-man-api>`_ - Shows how to integrate PostgREST with Apache APISIX as an alternative to Nginx.
* `A poor man's API <https://blog.frankel.ch/poor-man-api>`_ - Shows how to integrate PostgREST with Apache APISIX as an alternative to Nginx.
.. * `Accessing a PostgreSQL database in Godot 4 via PostgREST <https://peterkingsbury.com/2022/08/16/godot-postgresql-postgrest/>`_
.. _templates:
@@ -35,6 +34,7 @@ Templates
Example Apps
------------
* `archtika <https://github.com/archtika/archtika>`_ - selfhosted CMS
* `delibrium-postgrest <https://gitlab.com/delibrium/delibrium-postgrest/>`_ - example school API and front-end in Vue.js
* `ETH-transactions-storage <https://github.com/Adamant-im/ETH-transactions-storage>`_ - indexer for Ethereum to get transaction list by ETH address
* `general <https://github.com/PierreRochard/general>`_ - example auth back-end
@@ -49,17 +49,18 @@ DevOps
* `cloudgov-demo-postgrest <https://github.com/GSA/cloudgov-demo-postgrest>`_ - demo for a federally-compliant REST API on cloud.gov
* `cloudstark/helm-charts <https://github.com/cloudstark/helm-charts/tree/master/postgrest>`_ - helm chart to deploy PostgREST to a Kubernetes cluster via a Deployment and Service
* `jbkarle/postgrest <https://github.com/jbkarle/postgrest>`_ - helm chart with a demo database for development and test purposes
* `Limezest/postgrest-cloud-run <https://github.com/Limezest/postgrest-cloud-run>`_ - expose a PostgreSQL database on Cloud SQL using Cloud Run
* `cyril-sabourault/postgrest-cloud-run <https://github.com/cyril-sabourault/postgrest-cloud-run>`_ - expose a PostgreSQL database on Cloud SQL using Cloud Run
* `eyberg/postgrest <https://repo.ops.city/v2/packages/eyberg/postgrest/10.1.1/x86_64/show>`_ - run PostgREST as a Nanos unikernel
* `jbkarle/postgrest <https://github.com/jbkarle/postgrest>`_ - helm chart with a demo database for development and test purposes
.. _eco_external_notification:
External Notification
---------------------
These are PostgreSQL bridges that propagate LISTEN/NOTIFY to external queues for further processing. This allows stored procedures to initiate actions outside the database such as sending emails.
These are PostgreSQL bridges that propagate LISTEN/NOTIFY to external queues for further processing. This allows functions to initiate actions outside the database such as sending emails.
* `pg-notify-stdout <https://github.com/mkleczek/pg-notify-stdout>`_ - writes notifications to standard output (use in shell scripts etc.)
* `pg-notify-webhook <https://github.com/vbalasu/pg-notify-webhook>`_ - trigger webhooks from PostgreSQL's LISTEN/NOTIFY
* `pgsql-listen-exchange <https://github.com/gmr/pgsql-listen-exchange>`_ - RabbitMQ
* `postgres-websockets <https://github.com/diogob/postgres-websockets>`_ - expose web sockets for PostgreSQL's LISTEN/NOTIFY
@@ -82,12 +83,12 @@ Client-Side Libraries
---------------------
* `postgrest-csharp <https://github.com/supabase-community/postgrest-csharp>`_ - C#
* `postgrest-dart <https://github.com/supabase-community/postgrest-dart>`_ - Dart
* `postgrest-ex <https://github.com/J0/postgrest-ex>`_ - Elixir
* `postgrest-dart <https://github.com/supabase/postgrest-dart>`_ - Dart
* `postgrest-ex <https://github.com/supabase-community/postgrest-ex>`_ - Elixir
* `postgrest-go <https://github.com/supabase-community/postgrest-go>`_ - Go
* `postgrest-js <https://github.com/supabase/postgrest-js>`_ - TypeScript/JavaScript
* `postgrest-kt <https://github.com/supabase-community/postgrest-kt>`_ - Kotlin
* `postgrest-py <https://github.com/supabase-community/postgrest-py>`_ - Python
* `postgrest-py <https://github.com/supabase/postgrest-py>`_ - Python
* `postgrest-rs <https://github.com/supabase-community/postgrest-rs>`_ - Rust
* `postgrest-swift <https://github.com/supabase-community/postgrest-swift>`_ - Swift
* `redux-postgrest <https://github.com/andytango/redux-postgrest>`_ - TypeScript/JS, client integrated with (React) Redux.
+95
View File
@@ -0,0 +1,95 @@
Architecture
############
This page describes the architecture of PostgREST.
Bird's Eye View
===============
You can click on the components to navigate to their respective documentation.
.. container:: img-dark
.. See https://github.com/sphinx-doc/sphinx/issues/2240#issuecomment-187366626
.. raw:: html
<object width="100%" data="../_static/arch-dark.svg" type="image/svg+xml"></object>
.. container:: img-light
.. raw:: html
<object width="100%" data="../_static/arch.svg" type="image/svg+xml"></object>
Code Map
========
This section talks briefly about various important modules.
Main
----
The starting point of the program is `Main.hs <https://github.com/PostgREST/postgrest/blob/main/main/Main.hs>`_.
CLI
---
Main then calls `CLI.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/CLI.hs>`_, which is in charge of :ref:`cli`.
App
---
`App.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/App.hs>`_ is then in charge of composing the different modules.
Auth
----
`Auth.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/Auth.hs>`_ is in charge of :ref:`authn`.
Api Request
-----------
`ApiRequest.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/ApiRequest.hs>`_ is in charge of parsing the URL query string (following PostgREST syntax), the request headers, and the request body.
A request might be rejected at this level if it's invalid. For example when providing an unknown media type to PostgREST or using an unknown HTTP method.
Plan
----
Using the Schema Cache, `Plan.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/Plan.hs>`_ fills in out-of-band SQL details (like an ``ON CONFLICT (pk)`` clause) required to complete the user request.
A request might be rejected at this level if it's invalid. For example when doing resource embedding on a nonexistent resource.
Query
-----
`Query.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/Query.hs>`_ generates the SQL queries (parametrized and prepared) required to satisfy the user request.
Only at this stage a connection from the pool might be used.
Schema Cache
------------
`SchemaCache.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/SchemaCache.hs>`_ is in charge of :ref:`schema_cache`.
Config
------
`Config.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/Config.hs>`_ is in charge of :ref:`configuration`.
Admin
-----
`Admin.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/Admin.hs>`_ is in charge of the :ref:`admin_server`.
HTTP
----
The HTTP server is provided by `Warp <https://aosabook.org/en/posa/warp.html>`_.
Listener
--------
`Listener.hs <https://github.com/PostgREST/postgrest/blob/main/src/PostgREST/Listener.hs>`_ is in charge of the :ref:`listener`.
+4 -4
View File
@@ -15,7 +15,7 @@ Roles for Each Web User
PostgREST can accommodate either viewpoint. If you treat a role as a single user then the :ref:`jwt_impersonation` does most of what you need. When an authenticated user makes a request PostgREST will switch into the database role for that user, which in addition to restricting queries, is available to SQL through the :code:`current_user` variable.
You can use row-level security to flexibly restrict visibility and access for the current user. Here is an `example <https://www.2ndquadrant.com/en/blog/application-users-vs-row-level-security/>`_ from Tomas Vondra, a chat table storing messages sent between users. Users can insert rows into it to send messages to other users, and query it to see messages sent to them by other users.
You can use row-level security to flexibly restrict visibility and access for the current user. Here is an `example <https://www.enterprisedb.com:443/blog/application-users-vs-row-level-security>`_ from Tomas Vondra, a chat table storing messages sent between users. Users can insert rows into it to send messages to other users, and query it to see messages sent to them by other users.
.. code-block:: postgres
@@ -156,7 +156,7 @@ You can also grant execute on all functions in a schema to a higher privileged r
Security definer
----------------
A function is executed with the privileges of the user who calls it. This means that the user has to have all permissions to do the operations the procedure performs.
A function is executed with the privileges of the user who calls it. This means that the user has to have all permissions to do the operations the function performs.
If the function accesses private database objects, your :ref:`API roles <roles>` won't be able to successfully execute the function.
Another option is to define the function with the :code:`SECURITY DEFINER` option. Then only one permission check will take place, the permission to call the function, and the operations in the function will have the authority of the user who owns the function itself.
@@ -166,7 +166,7 @@ Another option is to define the function with the :code:`SECURITY DEFINER` optio
-- login as a user wich has privileges on the private schemas
-- create a sample function
create or replace function login(email text, pass text) returns jwt_token as $$
create or replace function login(email text, pass text, out token text) as $$
begin
-- access to a private schema called 'auth'
select auth.user_role(email, pass) into _role;
@@ -180,7 +180,7 @@ Note the ``SECURITY DEFINER`` keywords at the end of the function. See `PostgreS
Views
=====
Views are invoked with the privileges of the view owner, much like stored procedures with the ``SECURITY DEFINER`` option. When created by a SUPERUSER role, all `row-level security <https://www.postgresql.org/docs/current/ddl-rowsecurity.html>`_ policies will be bypassed.
Views are invoked with the privileges of the view owner, much like functions with the ``SECURITY DEFINER`` option. When created by a SUPERUSER role, all `row-level security <https://www.postgresql.org/docs/current/ddl-rowsecurity.html>`_ policies will be bypassed.
If you're on PostgreSQL >= 15, this behavior can be changed by specifying the ``security_invoker`` option.
+17 -14
View File
@@ -3,7 +3,7 @@
Installation
############
The release page has `pre-compiled binaries for macOS, Windows, Linux and FreeBSD <https://github.com/PostgREST/postgrest/releases/latest>`_ .
The release page has `pre-compiled binaries for macOS, Windows, Linux and FreeBSD <https://github.com/PostgREST/postgrest/releases/latest>`_.
The Linux binary is a static executable that can be run on any Linux distribution.
You can also use your OS package manager.
@@ -21,6 +21,12 @@ Supported PostgreSQL versions
PostgREST works with all PostgreSQL versions starting from 9.6.
.. note::
Support for PostgreSQL versions 9.6, 10 and 11 is deprecated. From this on version onwards, PostgREST will only support non-end-of-life PostgreSQL versions.
See https://www.postgresql.org/support/versioning/.
Running PostgREST
=================
@@ -163,14 +169,15 @@ If you want to have a visual overview of your API in your browser you can add sw
.. code-block:: yaml
swagger:
image: swaggerapi/swagger-ui
ports:
- "8080:8080"
expose:
- "8080"
environment:
API_URL: http://localhost:3000/
# in services:
swagger:
image: swaggerapi/swagger-ui
ports:
- "8080:8080"
expose:
- "8080"
environment:
API_URL: http://localhost:3000/
With this you can see the swagger-ui in your browser on port 8080.
@@ -181,13 +188,9 @@ Building from Source
When a pre-built binary does not exist for your system you can build the project from source.
.. note::
We discourage building and using PostgREST on **Alpine Linux** because of a reported GHC memory leak on that platform.
You can build PostgREST from source with `Stack <https://github.com/commercialhaskell/stack>`_. It will install any necessary Haskell dependencies on your system.
* `Install Stack <https://docs.haskellstack.org/en/stable/README/#how-to-install-stack>`_ for your platform
* `Install Stack <https://docs.haskellstack.org/en/stable/#how-to-install-stack>`_ for your platform
* Install Library Dependencies
===================== =======================================
+5 -12
View File
@@ -42,7 +42,7 @@ The first step is to create an Nginx configuration file that proxies requests to
HTTPS
-----
PostgREST aims to do one thing well: add an HTTP interface to a PostgreSQL database. To keep the code small and focused we do not implement HTTPS. Use a reverse proxy such as NGINX to add this, `here's how <https://nginx.org/en/docs/http/configuring_https_servers.html>`_. Note that some Platforms as a Service like Heroku also add SSL automatically in their load balancer.
PostgREST aims to do one thing well: add an HTTP interface to a PostgreSQL database. To keep the code small and focused we do not implement HTTPS. Use a reverse proxy such as NGINX to add this, `here's how <https://nginx.org/en/docs/http/configuring_https_servers.html>`_.
Rate Limiting
-------------
@@ -55,7 +55,7 @@ Nginx supports "leaky bucket" rate limiting (see `official docs <https://nginx.o
This creates a shared memory zone called "login" to store a log of IP addresses that access the rate limited urls. The space reserved, 10 MB (:code:`10m`) will give us enough space to store a history of 160k requests. We have chosen to allow only allow one request per second (:code:`1r/s`).
Next we apply the zone to certain routes, like a hypothetical stored procedure called :code:`login`.
Next we apply the zone to certain routes, like a hypothetical function called :code:`login`.
.. code-block:: nginx
@@ -73,17 +73,10 @@ Alternate URL Structure
As discussed in :ref:`singular_plural`, there are no special URL forms for singular resources in PostgREST, only operators for filtering. Thus there are no URLs like :code:`/people/1`. It would be specified instead as
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?id=eq.1 HTTP/1.1
Accept: application/vnd.pgrst.object+json
.. code-tab:: bash Curl
curl "http://localhost:3000/people?id=eq.1" \
-H "Accept: application/vnd.pgrst.object+json"
curl "http://localhost:3000/people?id=eq.1" \
-H "Accept: application/vnd.pgrst.object+json"
This allows compound primary keys and makes the intent for singular response independent of a URL convention.
+17 -7
View File
@@ -1,15 +1,25 @@
.. note::
This page is a work in progress.
.. _schema_isolation:
Schema Isolation
================
A PostgREST instance exposes all the tables, views, and stored procedures of a single `PostgreSQL schema <https://www.postgresql.org/docs/current/ddl-schemas.html>`_ (a namespace of database objects). This means private data or implementation details can go inside different private schemas and be invisible to HTTP clients.
A PostgREST instance exposes all the tables, views, and functions of a single `PostgreSQL schema <https://www.postgresql.org/docs/current/ddl-schemas.html>`_ (a namespace of database objects). This means private data or implementation details can go inside different private schemas and be invisible to HTTP clients.
It is recommended that you don't expose tables on your API schema. Instead expose views and stored procedures which insulate the internal details from the outside world.
It is recommended that you don't expose tables on your API schema. Instead expose views and functions which insulate the internal details from the outside world.
This allows you to change the internals of your schema and maintain backwards compatibility. It also keeps your code easier to refactor, and provides a natural way to do API versioning.
.. image:: ../_static/db.png
.. container:: svg-container-md
.. container:: img-dark
.. See https://github.com/sphinx-doc/sphinx/issues/2240#issuecomment-187366626
.. raw:: html
<object width="100%" data="../_static/sch-iso-dark.svg" type="image/svg+xml"></object>
.. container:: img-light
.. raw:: html
<object width="100%" data="../_static/sch-iso.svg" type="image/svg+xml"></object>
+1 -1
View File
@@ -191,7 +191,7 @@ References
For more information concerning PostgREST, cf.
- :ref:`s_proc_single_unnamed`
- :ref:`function_single_unnamed`
- :ref:`custom_media`. See :ref:`any_handler`, if you need to support an ``application/soap+xml`` media type or if you want to respond with XML without sending a media type.
- :ref:`Nginx reverse proxy <nginx>`
+112 -107
View File
@@ -38,7 +38,8 @@ and return a raw HTML document file.
Creating an HTML Response
-------------------------
Let's create a function that returns a basic HTML file, using `Tailwind CSS <https://v2.tailwindcss.com/>`_ for styling.
Let's create a function that returns a basic HTML file, using `Pico CSS <https://picocss.com>`_ for styling and
`Ionicons <https://ionic.io/ionicons>`_ to show some icons later.
.. code-block:: postgres
@@ -50,15 +51,20 @@ Let's create a function that returns a basic HTML file, using `Tailwind CSS <htt
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PostgREST + HTMX To-Do List</title>
<!-- Tailwind for CSS styling -->
<link href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<!-- Pico CSS for CSS styling -->
<link href="https://cdn.jsdelivr.net/npm/@picocss/pico@next/css/pico.min.css" rel="stylesheet" />
</head>
<body class="bg-gray-900">
<div class="flex justify-center">
<div class="max-w-lg mt-5 p-6 bg-gray-800 border border-gray-800 rounded-lg shadow-xl">
<h5 class="mb-3 text-2xl font-bold tracking-tight text-white">PostgREST + HTMX To-Do List</h5>
</div>
</div>
<body>
<main class="container">
<article>
<h5 style="text-align: center;">
PostgREST + HTMX To-Do List
</h5>
</article>
</main>
<!-- Script for Ionicons icons -->
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
</body>
</html>
$html$;
@@ -84,24 +90,22 @@ For that, we'll also need a function to help us sanitize the HTML content that m
create or replace function api.html_todo(api.todos) returns text as $$
select format($html$
<li class="py-3">
<span class="ml-2 %2$s">
<div>
<%2$s>
%3$s
</span>
</li>
</%2$s>
</div>
$html$,
$1.id,
case when $1.done then 'line-through text-gray-400' else '' end,
case when $1.done then 's' else 'span' end,
api.sanitize_html($1.task)
);
$$ language sql stable;
create or replace function api.html_all_todos() returns text as $$
select coalesce(
'<ul id="todo-list" role="list" class="divide-y divide-gray-700 text-gray-100">'
|| string_agg(api.html_todo(t), '' order by t.id) ||
'</ul>',
'<p class="text-gray-100">There is nothing else to do.</p>'
string_agg(api.html_todo(t), '<hr/>' order by t.id),
'<p><em>There is nothing else to do.</em></p>'
)
from api.todos t;
$$ language sql;
@@ -126,39 +130,44 @@ Next, let's add an endpoint to register a to-do in the database and modify the `
$$ language sql;
create or replace function api.index() returns "text/html" as $$
select $html$
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PostgREST + HTMX To-Do List</title>
<!-- Tailwind for CSS styling -->
<link href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<!-- htmx for AJAX requests -->
<script src="https://unpkg.com/htmx.org"></script>
</head>
<body class="bg-gray-900"
hx-headers='{"Accept": "text/html"}'>
<div class="flex justify-center">
<div class="max-w-lg mt-5 p-6 bg-gray-800 border border-gray-800 rounded-lg shadow-xl">
<h5 class="mb-3 text-2xl font-bold tracking-tight text-white">PostgREST + HTMX To-Do List</h5>
<form hx-post="/rpc/add_todo"
hx-target="#todo-list-area"
hx-trigger="submit"
hx-on="htmx:afterRequest: this.reset()">
<input class="bg-gray-50 border text-sm rounded-lg block w-full p-2.5 mb-3 bg-gray-700 border-gray-600 placeholder-gray-400 text-white focus:ring-blue-500 focus:border-blue-500"
type="text" name="_task" placeholder="Add a todo...">
</form>
<div id="todo-list-area">
$html$
|| api.html_all_todos() ||
$html$
<div>
</div>
</div>
</body>
</html>
select $html$
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PostgREST + HTMX To-Do List</title>
<!-- Pico CSS for CSS styling -->
<link href="https://cdn.jsdelivr.net/npm/@picocss/pico@next/css/pico.min.css" rel="stylesheet"/>
<!-- htmx for AJAX requests -->
<script src="https://unpkg.com/htmx.org"></script>
</head>
<body>
<main class="container"
style="max-width: 600px"
hx-headers='{"Accept": "text/html"}'>
<article>
<h5 style="text-align: center;">
PostgREST + HTMX To-Do List
</h5>
<form hx-post="/rpc/add_todo"
hx-target="#todo-list-area"
hx-trigger="submit"
hx-on="htmx:afterRequest: this.reset()">
<input type="text" name="_task" placeholder="Add a todo...">
</form>
<div id="todo-list-area">
$html$
|| api.html_all_todos() ||
$html$
<div>
</article>
</main>
<!-- Script for Ionicons icons -->
<script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
</body>
</html>
$html$;
$$ language sql;
@@ -190,49 +199,46 @@ Now, let's modify ``api.html_todo`` and make it more functional.
.. code-block:: postgres
create or replace function api.html_todo(api.todos) returns text as $$
select format($html$
<li class="py-3">
<div class="flex justify-between items-center">
<div id="todo-edit-area-%1$s" class="pr-5">
<form id="edit-task-state-%1$s"
hx-post="/rpc/change_todo_state"
hx-vals='{"_id": %1$s, "_done": %4$s}'
hx-target="#todo-list-area"
hx-trigger="click">
<span class="ml-2 %2$s cursor-pointer">
%3$s
</span>
</form>
</div>
<div>
<button class="p-1.5 rounded-full hover:bg-gray-700 focus:ring-gray-800"
hx-get="/rpc/html_editable_task"
hx-vals='{"_id": "%1$s"}'
hx-target="#todo-edit-area-%1$s"
hx-trigger="click">
<svg class="w-4 h-4 text-blue-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 18">
<path d="M12.687 14.408a3.01 3.01 0 0 1-1.533.821l-3.566.713a3 3 0 0 1-3.53-3.53l.713-3.566a3.01 3.01 0 0 1 .821-1.533L10.905 2H2.167A2.169 2.169 0 0 0 0 4.167v11.666A2.169 2.169 0 0 0 2.167 18h11.666A2.169 2.169 0 0 0 16 15.833V11.1l-3.313 3.308Zm5.53-9.065.546-.546a2.518 2.518 0 0 0 0-3.56 2.576 2.576 0 0 0-3.559 0l-.547.547 3.56 3.56Z"/>
<path d="M13.243 3.2 7.359 9.081a.5.5 0 0 0-.136.256L6.51 12.9a.5.5 0 0 0 .59.59l3.566-.713a.5.5 0 0 0 .255-.136L16.8 6.757 13.243 3.2Z"/>
</svg>
</button>
<button class="p-1.5 rounded-full hover:bg-gray-700 focus:ring-gray-800"
hx-post="/rpc/delete_todo"
hx-vals='{"_id": %1$s}'
select format($html$
<div class="grid">
<div id="todo-edit-area-%1$s">
<form id="edit-task-state-%1$s"
hx-post="/rpc/change_todo_state"
hx-vals='{"_id": %1$s, "_done": %4$s}'
hx-target="#todo-list-area"
hx-trigger="click">
<svg class="w-4 h-4 text-red-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 5h16M7 8v8m4-8v8M7 1h4a1 1 0 0 1 1 1v3H6V2a1 1 0 0 1 1-1ZM3 5h12v13a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V5Z"/>
</svg>
</button>
<%2$s style="cursor: pointer">
%3$s
</%2$s>
</form>
</div>
<div style="text-align: right">
<button class="outline"
hx-get="/rpc/html_editable_task"
hx-vals='{"_id": "%1$s"}'
hx-target="#todo-edit-area-%1$s"
hx-trigger="click">
<span>
<ion-icon name="create"></ion-icon>
</span>
</button>
<button class="outline contrast"
hx-post="/rpc/delete_todo"
hx-vals='{"_id": %1$s}'
hx-target="#todo-list-area"
hx-trigger="click">
<span>
<ion-icon name="trash" style="color: #f87171"></ion-icon>
</span>
</button>
</div>
</div>
</div>
</li>
$html$,
$1.id,
case when $1.done then 'line-through text-gray-400' else '' end,
api.sanitize_html($1.task),
(not $1.done)::text
);
$html$,
$1.id,
case when $1.done then 's' else 'span' end,
api.sanitize_html($1.task),
(not $1.done)::text
);
$$ language sql stable;
Let's deconstruct the new htmx features added:
@@ -267,22 +273,21 @@ That's why we create the ``api.html_editable_task`` function as an endpoint:
.. code-block:: postgres
create or replace function api.html_editable_task(_id int) returns "text/html" as $$
select format ($html$
<form id="edit-task-%1$s"
hx-post="/rpc/change_todo_task"
hx-headers='{"Accept": "text/html"}'
hx-vals='{"_id": %1$s}'
hx-target="#todo-list-area"
hx-trigger="submit,focusout">
<input class="bg-gray-50 border text-sm rounded-lg block w-full p-2.5 bg-gray-700 border-gray-600 text-white focus:ring-blue-500 focus:border-blue-500"
id="task-%1$s" type="text" name="_task" value="%2$s" autofocus>
</form>
$html$,
id,
api.sanitize_html(task)
)
from api.todos
where id = _id;
select format ($html$
<form id="edit-task-%1$s"
hx-post="/rpc/change_todo_task"
hx-headers='{"Accept": "text/html"}'
hx-vals='{"_id": %1$s}'
hx-target="#todo-list-area"
hx-trigger="submit,focusout">
<input id="task-%1$s" type="text" name="_task" value="%2$s" autofocus>
</form>
$html$,
id,
api.sanitize_html(task)
)
from api.todos
where id = _id;
$$ language sql;
In this example, this will return an input field that allows us to edit the corresponding to-do task.
+4 -2
View File
@@ -81,12 +81,14 @@ First, in addition to the minimal example, we need to store the media types and
.. code-block:: postgres
alter table files
add column type text,
add column type text generated always as (byteamagic_mime(substr(blob, 0, 4100))) stored,
add column name text;
This uses the :code:`byteamagic_mime()` function from the `pg_byteamagic extension <https://github.com/nmandery/pg_byteamagic>`_ to automatically generate the type in the :code:`files` table. To guess the type of a file, it's generally enough to look at the beginning of the file, which is more efficient.
Next, we set modify the function to set the content type and filename.
We use this opportunity to configure some basic, client-side caching.
For production, you probably want to configure additional caches, e.g. on the :ref:`reverse proxy <admin>`.
For production, you probably want to configure additional caches, e.g. on the :ref:`reverse proxy <nginx>`.
.. code-block:: postgres
@@ -31,7 +31,7 @@ As in :ref:`sql_user_management`, we create a :code:`basic_auth` schema:
-- We put things inside the basic_auth schema to hide
-- them from public view. Certain public procs/views will
-- refer to helpers and tables inside.
CREATE SCHEMA IF NOT EXISTS basic_auth;
CREATE SCHEMA basic_auth;
As in :ref:`sql_user_management`, we create the :code:`pgcrypto` and :code:`pgjwt` extensions. Here we prefer to put the extensions in its own schemas:
@@ -40,7 +40,7 @@ As in :ref:`sql_user_management`, we create the :code:`pgcrypto` and :code:`pgjw
CREATE SCHEMA ext_pgcrypto;
ALTER SCHEMA ext_pgcrypto OWNER TO postgres;
CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA ext_pgcrypto;
CREATE EXTENSION pgcrypto WITH SCHEMA ext_pgcrypto;
Concerning the `pgjwt extension <https://github.com/michelp/pgjwt>`_, please cf. to :ref:`client_auth`.
@@ -49,12 +49,12 @@ Concerning the `pgjwt extension <https://github.com/michelp/pgjwt>`_, please cf.
CREATE SCHEMA ext_pgjwt;
ALTER SCHEMA ext_pgjwt OWNER TO postgres;
CREATE EXTENSION IF NOT EXISTS pgjwt WITH SCHEMA ext_pgjwt;
CREATE EXTENSION pgjwt WITH SCHEMA ext_pgjwt;
In order to be able to work with postgres' SCRAM-SHA-256 password hashes, we also need the PBKDF2 key derivation function. Luckily there is `a PL/pgSQL implementation on stackoverflow <https://stackoverflow.com/q/47162200/2337147>`_:
In order to be able to work with postgres' SCRAM-SHA-256 password hashes, we also need the PBKDF2 key derivation function. Luckily there is `a PL/pgSQL implementation on stackoverflow <https://stackoverflow.com/a/72805848>`_:
.. code-block:: plpgsql
.. code-block:: postgres
CREATE FUNCTION basic_auth.pbkdf2(salt bytea, pw text, count integer, desired_length integer, algorithm text) RETURNS bytea
LANGUAGE plpgsql IMMUTABLE
@@ -117,10 +117,10 @@ In order to be able to work with postgres' SCRAM-SHA-256 password hashes, we als
ALTER FUNCTION basic_auth.pbkdf2(salt bytea, pw text, count integer, desired_length integer, algorithm text) OWNER TO postgres;
Analogous to :ref:`sql_user_management` creates the function :code:`basic_auth.user_role`, we create a helper function to check the user's password, here with another name and signature (since we want the username, not an email address).
Analogous to how :ref:`sql_user_management` creates the function :code:`basic_auth.user_role`, we create a helper function to check the user's password, here with another name and signature (since we want the username, not an email address).
But contrary to :ref:`sql_user_management`, this function does not use a dedicated :code:`users` table with passwords, but instead utilizes the built-in table `pg_catalog.pg_authid <https://www.postgresql.org/docs/current/catalog-pg-authid.html>`_:
.. code-block:: plpgsql
.. code-block:: postgres
CREATE FUNCTION basic_auth.check_user_pass(username text, password text) RETURNS name
LANGUAGE sql
@@ -160,22 +160,17 @@ Logins
As described in :ref:`client_auth`, we'll create a JWT token inside our login function. Note that you'll need to adjust the secret key which is hard-coded in this example to a secure (at least thirty-two character) secret of your choosing.
.. code-block:: plpgsql
CREATE TYPE basic_auth.jwt_token AS (
token text
);
.. code-block:: postgres
-- if you are not using psql, you need to replace :DBNAME with the current database's name.
ALTER DATABASE :DBNAME SET "app.jwt_secret" to 'reallyreallyreallyreallyverysafe';
CREATE FUNCTION public.login(username text, password text) RETURNS basic_auth.jwt_token
CREATE FUNCTION public.login(username text, password text, OUT token text)
LANGUAGE plpgsql security definer
AS $$
DECLARE
_role name;
result basic_auth.jwt_token;
BEGIN
-- check email and password
SELECT basic_auth.check_user_pass(username, password) INTO _role;
@@ -190,8 +185,7 @@ As described in :ref:`client_auth`, we'll create a JWT token inside our login fu
SELECT login.username as role,
extract(epoch FROM now())::integer + 60*60 AS exp
) r
INTO result;
RETURN result;
INTO token;
END;
$$;
@@ -259,19 +253,11 @@ Test at the REST level
~~~~~~~~~~~~~~~~~~~~~~
An API request to call this function would look like:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/login HTTP/1.1
{ "username": "foo", "password": "bar" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "username": "foo", "password": "bar" }'
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "username": "foo", "password": "bar" }'
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of :code:`reallyreallyreallyreallyverysafe` as specified in the SQL code above. You'll want to change this secret in your app!)
@@ -296,31 +282,18 @@ Let's add a table, intended for the :code:`foo` user:
Now try to get the table's contents with:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /foobar HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/foobar"
curl "http://localhost:3000/foobar"
This should fail --- of course, we haven't specified the user, thus PostgREST falls back to the :code:`anon` user and denies access.
Add an :code:`Authorization` header. Please use the token value from the login function call above instead of the one provided below.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /foobar HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY
.. code-tab:: bash Curl
curl "http://localhost:3000/foobar" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY"
curl "http://localhost:3000/foobar" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZm9vIiwiZXhwIjoxNjY4MTkyMjAyfQ.zzdHCBjfkqDQLQ8D7CHO3cIALF6KBCsfPTWgwhCiHCY"
This will fail again --- we get :code:`Permission denied to set role`. We forgot to allow the authenticator role to switch into this user by executing:
+18 -40
View File
@@ -17,9 +17,8 @@ First we'll need a table to keep track of our users:
-- We put things inside the basic_auth schema to hide
-- them from public view. Certain public procs/views will
-- refer to helpers and tables inside.
create schema if not exists basic_auth;
create table if not exists
create table
basic_auth.users (
email text primary key check ( email ~* '^.+@.+\..+$' ),
pass text not null check (length(pass) < 512),
@@ -28,9 +27,9 @@ First we'll need a table to keep track of our users:
We would like the role to be a foreign key to actual database roles, however PostgreSQL does not support these constraints against the :code:`pg_roles` table. We'll use a trigger to manually enforce it.
.. code-block:: plpgsql
.. code-block:: postgres
create or replace function
create function
basic_auth.check_role_exists() returns trigger as $$
begin
if not exists (select 1 from pg_roles as r where r.rolname = new.role) then
@@ -42,7 +41,6 @@ We would like the role to be a foreign key to actual database roles, however Pos
end
$$ language plpgsql;
drop trigger if exists ensure_user_role_exists on basic_auth.users;
create constraint trigger ensure_user_role_exists
after insert or update on basic_auth.users
for each row
@@ -50,11 +48,11 @@ We would like the role to be a foreign key to actual database roles, however Pos
Next we'll use the pgcrypto extension and a trigger to keep passwords safe in the :code:`users` table.
.. code-block:: plpgsql
.. code-block:: postgres
create extension if not exists pgcrypto;
create extension pgcrypto;
create or replace function
create function
basic_auth.encrypt_pass() returns trigger as $$
begin
if tg_op = 'INSERT' or new.pass <> old.pass then
@@ -64,7 +62,6 @@ Next we'll use the pgcrypto extension and a trigger to keep passwords safe in th
end
$$ language plpgsql;
drop trigger if exists encrypt_pass on basic_auth.users;
create trigger encrypt_pass
before insert or update on basic_auth.users
for each row
@@ -72,9 +69,9 @@ Next we'll use the pgcrypto extension and a trigger to keep passwords safe in th
With the table in place we can make a helper to check a password against the encrypted column. It returns the database role for a user if the email and password are correct.
.. code-block:: plpgsql
.. code-block:: postgres
create or replace function
create function
basic_auth.user_role(email text, pass text) returns name
language plpgsql
as $$
@@ -118,15 +115,11 @@ JWT from SQL
You can create JWT tokens in SQL using the `pgjwt extension <https://github.com/michelp/pgjwt>`_. It's simple and requires only pgcrypto. If you're on an environment like Amazon RDS which doesn't support installing new extensions, you can still manually run the `SQL inside pgjwt <https://github.com/michelp/pgjwt/blob/master/pgjwt--0.1.1.sql>`_ (you'll need to replace ``@extschema@`` with another schema or just delete it) which creates the functions you will need.
Next write a stored procedure that returns the token. The one below returns a token with a hard-coded role, which expires five minutes after it was issued. Note this function has a hard-coded secret as well.
Next write a function that returns the token. The one below returns a token with a hard-coded role, which expires five minutes after it was issued. Note this function has a hard-coded secret as well.
.. code-block:: postgres
CREATE TYPE jwt_token AS (
token text
);
CREATE FUNCTION jwt_test() RETURNS public.jwt_token AS $$
CREATE FUNCTION jwt_test(OUT token text) AS $$
SELECT public.sign(
row_to_json(r), 'reallyreallyreallyreallyverysafe'
) AS token
@@ -141,7 +134,7 @@ PostgREST exposes this function to clients via a POST request to ``/rpc/jwt_test
.. note::
To avoid hard-coding the secret in stored procedures, save it as a property of the database.
To avoid hard-coding the secret in functions, save it as a property of the database.
.. code-block:: postgres
@@ -161,17 +154,11 @@ As described in `JWT from SQL`_, we'll create a JWT inside our login function. N
.. code-block:: postgres
-- add type
CREATE TYPE basic_auth.jwt_token AS (
token text
);
-- login should be on your exposed schema
create or replace function
login(email text, pass text) returns basic_auth.jwt_token as $$
create function
login(email text, pass text, out token text) as $$
declare
_role name;
result basic_auth.jwt_token;
begin
-- check email and password
select basic_auth.user_role(email, pass) into _role;
@@ -186,8 +173,7 @@ As described in `JWT from SQL`_, we'll create a JWT inside our login function. N
select _role as role, login.email as email,
extract(epoch from now())::integer + 60*60 as exp
) r
into result;
return result;
into token;
end;
$$ language plpgsql security definer;
@@ -199,19 +185,11 @@ the anonymous user :code:`anon` doesn't need permission to read the :code:`basic
An API request to call this function would look like:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/login HTTP/1.1
{ "email": "foo@bar.com", "pass": "foobar" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "email": "foo@bar.com", "pass": "foobar" }'
curl "http://localhost:3000/rpc/login" \
-X POST -H "Content-Type: application/json" \
-d '{ "email": "foo@bar.com", "pass": "foobar" }'
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of :code:`reallyreallyreallyreallyverysafe` as specified in the SQL code above. You'll want to change this secret in your app!)
@@ -5,133 +5,13 @@ Working with PostgreSQL data types
:author: `Laurence Isla <https://github.com/laurenceisla>`_
PostgREST makes use of PostgreSQL string representations to work with data types. Thanks to this, you can use special values, such as ``now`` for timestamps, ``yes`` for booleans or time values including the time zones. This page describes how you can take advantage of these string representations to perform operations on different PostgreSQL data types.
PostgREST makes use of PostgreSQL string representations to work with data types. Thanks to this, you can use special values, such as ``now`` for timestamps, ``yes`` for booleans or time values including the time zones. This page describes how you can take advantage of these string representations and some alternatives to perform operations on different PostgreSQL data types.
.. contents::
:local:
:depth: 1
Timestamps
----------
You can use the **time zone** to filter or send data if needed.
.. code-block:: postgres
create table reports (
id int primary key
, due_date timestamptz
);
Suppose you are located in Sydney and want create a report with the date in the local time zone. Your request should look like this:
.. tabs::
.. code-tab:: http
POST /reports HTTP/1.1
Content-Type: application/json
[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },
{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]
.. code-tab:: bash Curl
curl "http://localhost:3000/reports" \
-X POST -H "Content-Type: application/json" \
-d '[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]'
Someone located in Cairo can retrieve the data using their local time, too:
.. tabs::
.. code-tab:: http
GET /reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo"
.. code-block:: json
[
{
"id": 1,
"due_date": "2022-02-23T19:10:15-05:00"
}
]
The response has the date in the time zone configured by the server: ``UTC -05:00`` (see :ref:`prefer_timezone`).
You can use other comparative filters and also all the `PostgreSQL special date/time input values <https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-DATETIME-SPECIAL-TABLE>`_ as illustrated in this example:
.. tabs::
.. code-tab:: http
GET /reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch)) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch))"
.. code-block:: json
[
{
"id": 2,
"due_date": "2022-02-27T06:00:00-05:00"
}
]
JSON
----
To work with a ``json`` type column, you can handle the value as a JSON object.
.. code-block:: postgres
create table products (
id int primary key,
name text unique,
extra_info json
);
You can insert a new product using a JSON object for the ``extra_info`` column:
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
{
"id": 1,
"name": "Canned fish",
"extra_info": {
"expiry_date": "2025-12-31",
"exportable": true
}
}
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "Canned fish",
"extra_info": {
"expiry_date": "2025-12-31",
"exportable": true
}
}
EOF
To query and filter the data see :ref:`json_columns` for a complete reference.
.. NOTE: Titles are ordered alphabetically. New entries should respect this order.
Arrays
------
@@ -149,61 +29,33 @@ To handle `array types <https://www.postgresql.org/docs/current/arrays.html>`_ y
You can insert a new value using string representation.
.. tabs::
.. code-tab:: http
POST /movies HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": "{family,comedy,not streamable}",
"performance_times": "{12:40,15:00,20:00}"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": "{family,comedy,not streamable}",
"performance_times": "{12:40,15:00,20:00}"
}
EOF
EOF
Or you could send the same data using JSON array format:
.. tabs::
.. code-tab:: http
POST /movies HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": ["family", "comedy", "not streamable"],
"performance_times": ["12:40", "15:00", "20:00"]
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"title": "Paddington",
"tags": ["family", "comedy", "not streamable"],
"performance_times": ["12:40", "15:00", "20:00"]
}
EOF
EOF
To query the data you can use arrow operators. See :ref:`composite_array_columns`.
@@ -220,38 +72,21 @@ Similarly to one-dimensional arrays, both the string representation and JSON arr
You can now update the item using JSON array format:
.. tabs::
.. code-tab:: http
PATCH /movies?id=eq.1 HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/movies?id=eq.1" \
-X PATCH -H "Content-Type: application/json" \
-d @- << EOF
{
"cinema_floor_auditorium": [ [ [1,2], [6,7] ], [ [3,5], [8,9] ] ]
}
.. code-tab:: bash Curl
curl "http://localhost:3000/movies?id=eq.1" \
-X PATCH -H "Content-Type: application/json" \
-d @- << EOF
{
"cinema_floor_auditorium": [ [ [1,2], [6,7] ], [ [3,5], [8,9] ] ]
}
EOF
EOF
Then, for example, to query the auditoriums that are located in the first cinema (position 0 in the array) and on the second floor (position 1 in the next inner array), we can use the arrow operators this way:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1"
curl "http://localhost:3000/movies?select=title,auditorium:cinema_floor_auditorium->0->1&id=eq.1"
.. code-block:: json
@@ -262,211 +97,6 @@ Then, for example, to query the auditoriums that are located in the first cinema
}
]
Composite Types
---------------
With PostgREST, you have two options to handle `composite type columns <https://www.postgresql.org/docs/current/rowtypes.html>`_.
.. code-block:: postgres
create type dimension as (
length decimal(6,2),
width decimal (6,2),
height decimal (6,2),
unit text
);
create table products (
id int primary key,
size dimension
);
insert into products (id, size)
values (1, '(5.0,5.0,10.0,"cm")');
On one hand you can insert values using string representation.
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
EOF
Or you could insert the same data in JSON format.
.. tabs::
.. code-tab:: http
POST /products HTTP/1.1
Content-Type: application/json
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
}
.. code-tab:: bash Curl
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
}
EOF
You can also query the data using arrow operators. See :ref:`composite_array_columns`.
Ranges
------
PostgREST allows you to handle `ranges <https://www.postgresql.org/docs/current/rangetypes.html>`_.
.. code-block:: postgres
create table events (
id int primary key,
name text unique,
duration tsrange
);
To insert a new event, specify the ``duration`` value as a string representation of the ``tsrange`` type:
.. tabs::
.. code-tab:: http
POST /events HTTP/1.1
Content-Type: application/json
{
"id": 1,
"name": "New Year's Party",
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
}
.. code-tab:: bash Curl
curl "http://localhost:3000/events" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "New Year's Party",
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
}
EOF
You can use range :ref:`operators <operators>` to filter the data. But, in this case, requesting a filter like ``events?duration=cs.2023-01-01`` will return an error, because PostgreSQL needs an explicit cast from string to timestamp. A workaround is to use a range starting and ending in the same date:
.. tabs::
.. code-tab:: http
GET /events?duration=cs.[2023-01-01,2023-01-01] HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/events?duration=cs.\[2023-01-01,2023-01-01\]"
.. code-block:: json
[
{
"id": 1,
"name": "New Year's Party",
"duration": "[\"2022-12-31 11:00:00\",\"2023-01-01 06:00:00\"]"
}
]
.. _casting_range_to_json:
Casting a Range to a JSON Object
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As you may have noticed, the ``tsrange`` value is returned as a string literal. To return it as a JSON value, first you need to create a function that will do the conversion from a ``tsrange`` type:
.. code-block:: postgres
create or replace function tsrange_to_json(tsrange) returns json as $$
select json_build_object(
'lower', lower($1)
, 'upper', upper($1)
, 'lower_inc', lower_inc($1)
, 'upper_inc', upper_inc($1)
);
$$ language sql;
Then, create the cast using this function:
.. code-block:: postgres
create cast (tsrange as json) with function tsrange_to_json(tsrange) as assignment;
Finally, do the request :ref:`casting the range column <casting_columns>`:
.. tabs::
.. code-tab:: http
GET /events?select=id,name,duration::json HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/events?select=id,name,duration::json"
.. code-block:: json
[
{
"id": 1,
"name": "New Year's Party",
"duration": {
"lower": "2022-12-31T11:00:00",
"upper": "2023-01-01T06:00:00",
"lower_inc": true,
"upper_inc": true
}
}
]
.. note::
If you don't want to modify casts for built-in types, an option would be to `create a custom type <https://www.postgresql.org/docs/current/sql-createtype.html>`_
for your own ``tsrange`` and add its own cast.
.. code-block:: postgres
create type mytsrange as range (subtype = timestamp, subtype_diff = tsrange_subdiff);
-- define column types and casting function analogously to the above example
-- ...
create cast (mytsrange as json) with function mytsrange_to_json(mytsrange) as assignment;
Bytea
-----
@@ -491,20 +121,11 @@ Let's download the PostgREST logo for our test.
Now, to send the file ``postgrest-logo.png`` we need to set the ``Content-Type: application/octet-stream`` header in the request:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/upload_binary HTTP/1.1
Content-Type: application/octet-stream
postgrest-logo.png
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@postgrest-logo.png"
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@postgrest-logo.png"
To get the image from the database, use :ref:`custom_media` like so:
@@ -516,17 +137,10 @@ To get the image from the database, use :ref:`custom_media` like so:
select file from files where id = $1;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /get_image?id=1 HTTP/1.1
Accept: image/png
.. code-tab:: bash Curl
curl "http://localhost:3000/get_image?id=1" \
-H "Accept: image/png"
curl "http://localhost:3000/get_image?id=1" \
-H "Accept: image/png"
See :ref:`providing_img` for a step-by-step example on how to handle images in HTML.
@@ -534,6 +148,104 @@ See :ref:`providing_img` for a step-by-step example on how to handle images in H
Be careful when saving binaries in the database, having a separate storage service for these is preferable in most cases. See `Storing Binary files in the Database <https://wiki.postgresql.org/wiki/BinaryFilesInDB>`_.
Composite Types
---------------
With PostgREST, you have two options to handle `composite type columns <https://www.postgresql.org/docs/current/rowtypes.html>`_.
.. code-block:: postgres
create type dimension as (
length decimal(6,2),
width decimal (6,2),
height decimal (6,2),
unit text
);
create table products (
id int primary key,
size dimension
);
insert into products (id, size)
values (1, '(5.0,5.0,10.0,"cm")');
On one hand you can insert values using string representation.
.. code-block:: bash
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{ "id": 2, "size": "(0.7,0.5,1.8,\"m\")" }
EOF
Or you could insert the same data in JSON format.
.. code-block:: bash
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 2,
"size": {
"length": 0.7,
"width": 0.5,
"height": 1.8,
"unit": "m"
}
}
EOF
You can also query the data using arrow operators. See :ref:`composite_array_columns`.
Enums
-----
You can handle `Enumerated Types <https://www.postgresql.org/docs/current/datatype-enum.html>`_ using string representations:
.. code-block:: postgres
create type letter_size as enum ('s','m','l','xl');
create table products (
id int primary key generated always as identity,
name text,
size letter_size
);
To insert or update the value use a string:
.. code-block:: bash
curl -X POST "http://localhost:3000/products" \
-H "Content-Type: application/json" \
-d @- << EOF
{ "name": "t-shirt", "size": "l" }
EOF
You can then query and filter the enum using the compatible :ref:`operators <operators>`.
For example, to get all the products larger than `m` and ordering them by their size:
.. code-block:: bash
curl "http://localhost:3000/products?select=name,size&size=gt.m&order=size"
.. code-block:: json
[
{
"name": "t-shirt",
"size": "l"
},
{
"name": "hoodie",
"size": "xl"
}
]
hstore
------
@@ -551,53 +263,67 @@ You can work with data types belonging to additional supplied modules such as `h
The ``name`` column will have the name of the country in different formats. You can insert values using the string representation for that data type:
.. tabs::
.. code-tab:: http
POST /countries HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/countries" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "common => Egypt, official => \"Arab Republic of Egypt\", native => مصر" },
{ "id": 2, "name": "common => Germany, official => \"Federal Republic of Germany\", native => Deutschland" }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/countries" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "common => Egypt, official => \"Arab Republic of Egypt\", native => مصر" },
{ "id": 2, "name": "common => Germany, official => \"Federal Republic of Germany\", native => Deutschland" }
]
EOF
EOF
Notice that the use of ``"`` in the value of the ``name`` column needs to be escaped using a backslash ``\``.
You can also query and filter the value of a ``hstore`` column using the arrow operators, as you would do for a :ref:`JSON column<json_columns>`. For example, if you want to get the native name of Egypt:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /countries?select=name->>native&name->>common=like.Egypt HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/countries?select=name->>native&name->>common=like.Egypt"
curl "http://localhost:3000/countries?select=name->>native&name->>common=like.Egypt"
.. code-block:: json
[{ "native": "مصر" }]
JSON
----
To work with a ``json`` type column, you can handle the value as a JSON object.
.. code-block:: postgres
create table products (
id int primary key,
name text unique,
extra_info json
);
You can insert a new product using a JSON object for the ``extra_info`` column:
.. code-block:: bash
curl "http://localhost:3000/products" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "Canned fish",
"extra_info": {
"expiry_date": "2025-12-31",
"exportable": true
}
}
EOF
To query and filter the data see :ref:`json_columns` for a complete reference.
.. _ww_postgis:
PostGIS
-------
You can use the string representation for `PostGIS <https://postgis.net/>`_ data types such as ``geometry`` or ``geography`` (you need to `install PostGIS <https://postgis.net/install/>`_ first).
You can use the string representation for `PostGIS <https://postgis.net/>`_ data types such as ``geometry`` or ``geography`` (you need to `install PostGIS <https://postgis.net/documentation/getting_started/>`_ first).
.. code-block:: postgres
@@ -612,42 +338,23 @@ You can use the string representation for `PostGIS <https://postgis.net/>`_ data
To add areas in polygon format, you can use string representation:
.. tabs::
.. code-tab:: http
POST /coverage HTTP/1.1
Content-Type: application/json
.. code-block:: bash
curl "http://localhost:3000/coverage" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "small", "area": "SRID=4326;POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))" },
{ "id": 2, "name": "big", "area": "SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))" }
]
.. code-tab:: bash Curl
curl "http://localhost:3000/coverage" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
[
{ "id": 1, "name": "small", "area": "SRID=4326;POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))" },
{ "id": 2, "name": "big", "area": "SRID=4326;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))" }
]
EOF
EOF
Now, when you request the information, PostgREST will automatically cast the ``area`` column into a ``Polygon`` geometry type. Although this is useful, you may need the whole output to be in `GeoJSON <https://geojson.org/>`_ format out of the box, which can be done by including the ``Accept: application/geo+json`` in the request. This will work for PostGIS versions 3.0.0 and up and will return the output as a `FeatureCollection Object <https://www.rfc-editor.org/rfc/rfc7946#section-3.3>`_:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /coverage HTTP/1.1
Accept: application/geo+json
.. code-tab:: bash Curl
curl "http://localhost:3000/coverage" \
-H "Accept: application/geo+json"
curl "http://localhost:3000/coverage" \
-H "Accept: application/geo+json"
.. code-block:: json
@@ -711,15 +418,9 @@ In the case that you are using older PostGIS versions, then creating a function
Now this query will return the same results:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/coverage_geo_collection HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/coverage_geo_collection"
curl "http://localhost:3000/rpc/coverage_geo_collection"
.. code-block:: json
@@ -754,3 +455,157 @@ Now this query will return the same results:
}
]
}
Ranges
------
PostgREST allows you to handle `ranges <https://www.postgresql.org/docs/current/rangetypes.html>`_.
.. code-block:: postgres
create table events (
id int primary key,
name text unique,
duration tsrange
);
To insert a new event, specify the ``duration`` value as a string representation of the ``tsrange`` type:
.. code-block:: bash
curl "http://localhost:3000/events" \
-X POST -H "Content-Type: application/json" \
-d @- << EOF
{
"id": 1,
"name": "New Year's Party",
"duration": "['2022-12-31 11:00','2023-01-01 06:00']"
}
EOF
You can use range :ref:`operators <operators>` to filter the data. But, in this case, requesting a filter like ``events?duration=cs.2023-01-01`` will return an error, because PostgreSQL needs an explicit cast from string to timestamp. A workaround is to use a range starting and ending in the same date:
.. code-block:: bash
curl "http://localhost:3000/events?duration=cs.\[2023-01-01,2023-01-01\]"
.. code-block:: json
[
{
"id": 1,
"name": "New Year's Party",
"duration": "[\"2022-12-31 11:00:00\",\"2023-01-01 06:00:00\"]"
}
]
.. _casting_range_to_json:
Casting a Range to a JSON Object
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As you may have noticed, the ``tsrange`` value is returned as a string literal. To return it as a JSON value, first you need to create a function that will do the conversion from a ``tsrange`` type:
.. code-block:: postgres
create or replace function tsrange_to_json(tsrange) returns json as $$
select json_build_object(
'lower', lower($1)
, 'upper', upper($1)
, 'lower_inc', lower_inc($1)
, 'upper_inc', upper_inc($1)
);
$$ language sql;
Then, create the cast using this function:
.. code-block:: postgres
create cast (tsrange as json) with function tsrange_to_json(tsrange) as assignment;
Finally, do the request :ref:`casting the range column <casting_columns>`:
.. code-block:: bash
curl "http://localhost:3000/events?select=id,name,duration::json"
.. code-block:: json
[
{
"id": 1,
"name": "New Year's Party",
"duration": {
"lower": "2022-12-31T11:00:00",
"upper": "2023-01-01T06:00:00",
"lower_inc": true,
"upper_inc": true
}
}
]
.. note::
If you don't want to modify casts for built-in types, an option would be to `create a custom type <https://www.postgresql.org/docs/current/sql-createtype.html>`_
for your own ``tsrange`` and add its own cast.
.. code-block:: postgres
create type mytsrange as range (subtype = timestamp, subtype_diff = tsrange_subdiff);
-- define column types and casting function analogously to the above example
-- ...
create cast (mytsrange as json) with function mytsrange_to_json(mytsrange) as assignment;
Timestamps
----------
You can use the **time zone** to filter or send data if needed.
.. code-block:: postgres
create table reports (
id int primary key
, due_date timestamptz
);
Suppose you are located in Sydney and want create a report with the date in the local time zone. Your request should look like this:
.. code-block:: bash
curl "http://localhost:3000/reports" \
-X POST -H "Content-Type: application/json" \
-d '[{ "id": 1, "due_date": "2022-02-24 11:10:15 Australia/Sydney" },{ "id": 2, "due_date": "2022-02-27 22:00:00 Australia/Sydney" }]'
Someone located in Cairo can retrieve the data using their local time, too:
.. code-block:: bash
curl "http://localhost:3000/reports?due_date=eq.2022-02-24+02:10:15+Africa/Cairo"
.. code-block:: json
[
{
"id": 1,
"due_date": "2022-02-23T19:10:15-05:00"
}
]
The response has the date in the time zone configured by the server: ``UTC -05:00`` (see :ref:`prefer_timezone`).
You can use other comparative filters and also all the `PostgreSQL special date/time input values <https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-DATETIME-SPECIAL-TABLE>`_ as illustrated in this example:
.. code-block:: bash
curl "http://localhost:3000/reports?or=(and(due_date.gte.today,due_date.lte.tomorrow),and(due_date.gt.-infinity,due_date.lte.epoch))"
.. code-block:: json
[
{
"id": 2,
"due_date": "2022-02-27T06:00:00-05:00"
}
]
+46 -31
View File
@@ -5,7 +5,7 @@ PostgREST Documentation
.. container:: image-container
.. figure:: _static/logo.png
.. figure:: ../static/postgrest.png
.. image:: https://img.shields.io/github/stars/postgrest/postgrest.svg?style=social
:target: https://github.com/PostgREST/postgrest
@@ -16,15 +16,9 @@ PostgREST Documentation
.. image:: https://img.shields.io/docker/pulls/postgrest/postgrest.svg
:target: https://hub.docker.com/r/postgrest/postgrest/
.. image:: https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg
:target: https://gitter.im/begriffs/postgrest
.. image:: https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854
:target: https://www.patreon.com/postgrest
.. image:: https://img.shields.io/badge/Donate-PayPal-green.svg
:target: https://www.paypal.com/paypalme/postgrest
|
PostgREST is a standalone web server that turns your PostgreSQL database directly into a RESTful API. The structural constraints and permissions in the database determine the API endpoints and operations.
@@ -34,38 +28,59 @@ Sponsors
.. container:: image-container
.. image:: _static/cybertec-new.png
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
:width: 13em
.. container:: img-dark
.. image:: _static/gnuhost.png
:target: https://gnuhost.eu/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. image:: ../static/cybertec-dark.svg
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
.. image:: _static/neon.jpg
:target: https://neon.tech/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. container:: img-light
.. image:: ../static/cybertec.svg
:target: https://www.cybertec-postgresql.com/en/?utm_source=postgrest.org&utm_medium=referral&utm_campaign=postgrest
.. image:: ../static/gnuhost.png
:target: https://euronodes.com/?utm_source=sponsor&utm_campaign=postgrest
.. container:: img-dark
.. image:: ../static/neon-dark.jpg
:target: https://neon.tech/?utm_source=sponsor&utm_campaign=postgrest
.. container:: img-light
.. image:: ../static/neon.jpg
:target: https://neon.tech/?utm_source=sponsor&utm_campaign=postgrest
|
.. image:: _static/code-build.webp
:target: https://code.build/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. container:: img-dark
.. image:: _static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
:width: 13em
.. image:: ../static/code-build-dark.png
:target: https://code.build/?utm_source=sponsor&utm_campaign=postgrest
.. image:: _static/tembo.png
.. container:: img-light
.. image:: ../static/code-build.png
:target: https://code.build/?utm_source=sponsor&utm_campaign=postgrest
.. container:: img-dark
.. image:: ../static/supabase-dark.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
.. container:: img-light
.. image:: ../static/supabase.png
:target: https://supabase.com/?utm_source=postgrest%20backers&utm_medium=open%20source%20partner&utm_campaign=postgrest%20backers%20github&utm_term=homepage
.. image:: ../static/tembo.png
:target: https://tembo.io/?utm_source=sponsor&utm_campaign=postgrest
:width: 13em
.. The static/empty.png(created with `convert -size 320x95 xc:#fcfcfc empty.png`) is an ugly workaround
to create space and center the logos. It's not easy to layout with restructuredText.
.. .. image:: _static/empty.png
:target: #sponsors
:width: 13em
|
@@ -92,7 +107,7 @@ PostgREST has a focused scope. It works well with other tools like Nginx. This f
Getting Support
----------------
The project has a friendly and growing community. For discussions, use the Github `discussions page <https://github.com/PostgREST/postgrest/discussions>`_ or join our `chat room <https://gitter.im/begriffs/postgrest>`_. You can also report or search for bugs/features on the Github `issues <https://github.com/PostgREST/postgrest/issues>`_ page.
The project has a friendly and growing community. For discussions, use the Github `discussions page <https://github.com/PostgREST/postgrest/discussions>`_. You can also report or search for bugs/features on the Github `issues <https://github.com/PostgREST/postgrest/issues>`_ page.
Release Notes
-------------
@@ -126,11 +141,13 @@ Technical references for PostgREST's functionality.
references/auth.rst
references/api.rst
references/cli.rst
references/transactions.rst
references/connection_pool.rst
references/schema_cache.rst
references/errors.rst
references/configuration.rst
references/observability.rst
references/*
Explanations
@@ -195,13 +212,11 @@ Here are some companies that use PostgREST in production.
* `Datrium <https://www.datrium.com>`_
* `Drip Depot <https://www.dripdepot.com>`_
* `Image-charts <https://www.image-charts.com>`_
* `Moat <https://www.moat.com>`_
* `Moat <https://www.oracle.com/advertising/>`_
* `Netwo <https://www.netwo.io>`_
* `Nimbus <https://www.nimbusforwork.com>`_
* `Nimbus <https://www.nimbusfacility.com/sg/home>`_
- See how Nimbus uses PostgREST in `Paul Copplestone's blog post <https://paul.copplest.one/blog/nimbus-tech-2019-04.html>`_.
* `OpenBooking <https://www.openbooking.ch>`_
* `Redsmin <https://www.redsmin.com>`_
* `Sompani <https://www.sompani.com>`_
* `OpenBooking <https://openbooking.ch>`_
* `Supabase <https://supabase.com>`_
.. Failing links
+1 -1
View File
@@ -1,6 +1,6 @@
Greenplum
#########
`Greenplum <https://greenplum.org/>`_ has been reported to work by adding ``LOGIN`` to the :ref:`anonymous and user roles <roles>`.
`Greenplum <https://blogs.vmware.com/tanzu/tanzu-greenplum/>`_ has been reported to work by adding ``LOGIN`` to the :ref:`anonymous and user roles <roles>`.
For more details, see https://github.com/PostgREST/postgrest/issues/2021.
-122
View File
@@ -1,122 +0,0 @@
.. _deploy_heroku:
Heroku
======
1. Log into Heroku using the `Heroku CLI <https://devcenter.heroku.com/articles/heroku-cli>`_:
.. code-block:: bash
# If you have multiple Heroku accounts, use flag '--interactive' to switch between them
heroku login --interactive
2. Create a new Heroku app using the PostgREST buildpack:
.. code-block:: bash
mkdir ${YOUR_APP_NAME}
cd ${YOUR_APP_NAME}
git init .
heroku apps:create ${YOUR_APP_NAME} --buildpack https://github.com/PostgREST/postgrest-heroku.git
heroku git:remote -a ${YOUR_APP_NAME}
3. Create a new Heroku PostgreSQL add-on attached to the app and keep notes of the assigned add-on name (e.g. :code:`postgresql-curly-58902`) referred later as ${HEROKU_PG_DB_NAME}
.. code-block:: bash
heroku addons:create heroku-postgresql:standard-0 -a ${YOUR_APP_NAME}
# wait until the add-on is available
heroku pg:wait -a ${YOUR_APP_NAME}
4. Create the necessary user roles according to the
`PostgREST documentation <https://postgrest.org/en/stable/auth.html>`_:
.. code-block:: bash
heroku pg:credentials:create --name api_user -a ${YOUR_APP_NAME}
# use the following command to ensure the new credential state is active before attaching it
heroku pg:credentials -a ${YOUR_APP_NAME}
heroku addons:attach ${HEROKU_PG_DB_NAME} --credential api_user -a ${YOUR_APP_NAME}
5. Connect to the PostgreSQL database and create some sample data:
.. code-block:: bash
heroku psql -a ${YOUR_APP_NAME}
.. code-block:: postgres
# from the psql command prompt execute the following commands:
create schema api;
create table api.todos (
id serial primary key,
done boolean not null default false,
task text not null,
due timestamptz
);
insert into api.todos (task) values
('finish tutorial 0'), ('pat self on back');
grant usage on schema api to api_user;
grant select on api.todos to api_user;
6. Create the :code:`Procfile`:
.. code-block:: bash
web: PGRST_SERVER_HOST=0.0.0.0 PGRST_SERVER_PORT=${PORT} PGRST_DB_URI=${PGRST_DB_URI:-${DATABASE_URL}} ./postgrest-${POSTGREST_VER}
..
Set the following environment variables on Heroku:
.. code-block:: bash
heroku config:set POSTGREST_VER=10.0.0
heroku config:set PGRST_DB_SCHEMA=api
heroku config:set PGRST_DB_ANON_ROLE=api_user
..
PGRST_DB_URI can be set if an external database is used or if it's different from the default Heroku DATABASE_URL. This latter is used if nothing is provided.
POSTGREST_VER is mandatory to select and build the required PostgREST release.
See https://postgrest.org/en/stable/configuration.html#environment-variables for the full list of environment variables.
7. Build and deploy your app:
.. code-block:: bash
git add Procfile
git commit -m "PostgREST on Heroku"
git push heroku master
..
Your Heroku app should be live at :code:`${YOUR_APP_NAME}.herokuapp.com`
8. Test your app
From a terminal display the application logs:
.. code-block:: bash
heroku logs -t
..
From a different terminal retrieve with curl the records previously created:
.. code-block:: bash
curl https://${YOUR_APP_NAME}.herokuapp.com/todos
..
and test that any attempt to modify the table via a read-only user is not allowed:
.. code-block:: bash
curl https://${YOUR_APP_NAME}.herokuapp.com/todos -X POST \
-H "Content-Type: application/json" \
-d '{"task": "do bad thing"}'
-20
View File
@@ -9,23 +9,3 @@ JWT from Auth0
An external service like `Auth0 <https://auth0.com/>`_ can do the hard work transforming OAuth from Github, Twitter, Google etc into a JWT suitable for PostgREST. Auth0 can also handle email signup and password reset flows.
To use Auth0, create `an application <https://auth0.com/docs/get-started/applications>`_ for your app and `an API <https://auth0.com/docs/get-started/apis>`_ for your PostgREST server. Auth0 supports both HS256 and RS256 scheme for the issued tokens for APIs. For simplicity, you may first try HS256 scheme while creating your API on Auth0. Your application should use your PostgREST API's `API identifier <https://auth0.com/docs/get-started/apis/api-settings>`_ by setting it with the `audience parameter <https://auth0.com/docs/secure/tokens/access-tokens/get-access-tokens#control-access-token-audience>`_ during the authorization request. This will ensure that Auth0 will issue an access token for your PostgREST API. For PostgREST to verify the access token, you will need to set ``jwt-secret`` on PostgREST config file with your API's signing secret.
.. note::
Our code requires a database role in the JWT. To add it you need to save the database role in Auth0 `app metadata <https://auth0.com/docs/manage-users/user-accounts/metadata/manage-metadata-rules>`_. Then, you will need to write `a rule <https://auth0.com/docs/customize/rules>`_ that will extract the role from the user's app_metadata and set it as a `custom claim <https://auth0.com/docs/get-started/apis/scopes/sample-use-cases-scopes-and-claims#add-custom-claims-to-a-token>`_ in the access token. Note that, you may use Auth0's `core authorization feature <https://auth0.com/docs/manage-users/access-control/rbac>`_ for more complex use cases. Metadata solution is mentioned here for simplicity.
.. code:: javascript
function (user, context, callback) {
// Follow the documentations at
// https://postgrest.org/en/latest/configuration.html#db-role-claim-key
// to set a custom role claim on PostgREST
// and use it as custom claim attribute in this rule
const myRoleClaim = 'https://myapp.com/role';
user.app_metadata = user.app_metadata || {};
context.accessToken[myRoleClaim] = user.app_metadata.role;
callback(null, user, context);
}
+4 -16
View File
@@ -8,27 +8,15 @@ Block Full-Table Operations
If the :ref:`active role <user_impersonation>` can delete table rows then the DELETE verb is allowed for clients. Here's an API request to delete old rows from a hypothetical logs table:
.. tabs::
.. code-block:: bash
.. code-tab:: http
DELETE /logs?time=lt.1991-08-06 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/logs?time=lt.1991-08-06" -X DELETE
curl "http://localhost:3000/logs?time=lt.1991-08-06" -X DELETE
Note that it's very easy to delete the **entire table** by omitting the query parameter!
.. tabs::
.. code-block:: bash
.. code-tab:: http
DELETE /logs HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/logs" -X DELETE
curl "http://localhost:3000/logs" -X DELETE
This can happen accidentally such as by switching a request from a GET to a DELETE. To protect against accidental operations use the `pg-safeupdate <https://github.com/eradman/pg-safeupdate>`_ PostgreSQL extension. It raises an error if UPDATE or DELETE are executed without specifying conditions. To install it you can use the `PGXN <https://pgxn.org/>`_ network:
+1 -1
View File
@@ -1,7 +1,7 @@
systemd
=======
For Linux distributions that use **systemd** (Ubuntu, Debian, Archlinux) you can create a daemon in the following way.
For Linux distributions that use **systemd** (Ubuntu, Debian, Arch Linux) you can create a daemon in the following way.
First, create postgrest configuration in ``/etc/postgrest/config``
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env python
from livereload import Server, shell
from subprocess import call
## Build docs at startup
call(["sphinx-build", "-b", "html", "-a", "-n", ".", "_build"])
server = Server()
server.watch("**/*.rst", shell("sphinx-build -b html -a -n . _build"))
# For custom port and host
# server.serve(root='_build/', host='192.168.1.2')
server.serve(root="_build/")
+8 -9
View File
@@ -1,22 +1,21 @@
personal_ws-1.1 en 0 utf-8
api
API's
APIs
APISIX
Archlinux
aud
Auth
auth
authenticator
backoff
balancer
booleans
buildpack
BOM
Bytea
Cardano
casted
cd
centric
CLI
CMS
coercible
conf
Cloudflare
@@ -30,6 +29,8 @@ DDL
DOM
DevOps
dockerize
enum
Enums
eq
ETH
Ethereum
@@ -38,7 +39,6 @@ filename
FreeBSD
fts
GeoJSON
GHC
Github
Google
grantor
@@ -47,7 +47,6 @@ Greenplum
gte
GUC
Haskell
Heroku
HMAC
htmx
Htmx
@@ -95,10 +94,12 @@ npm
nxl
nxr
OAuth
Observability
OpenAPI
openapi
ORM
ov
parametrized
passphrase
PBKDF
PgBouncer
@@ -145,17 +146,15 @@ SHA
signup
SIGUSR
sl
spreaded
Spreaded
SQL
sql
SQLSTATE
sr
SSL
stateful
stdout
supervisees
SvelteKit
syslog
systemd
todo
todos
+93
View File
@@ -0,0 +1,93 @@
.. _admin_server:
Admin Server
############
PostgREST provides an admin server that can be enabled by setting :ref:`admin-server-port`.
.. _health_check:
Health Check
============
You can enable a health check to verify if PostgREST is available for client requests. Also to check the status of its internal state.
Two endpoints ``live`` and ``ready`` will then be available.
.. important::
If you have a machine with multiple network interfaces and multiple PostgREST instances in the same port, you need to specify a unique :ref:`hostname <server-host>`
in the configuration of each PostgREST instance for the health check to work correctly. Don't use the special values(``!4``, ``*``, etc) in this case because the health check
could report a false positive.
Live
----
The ``live`` endpoint verifies if PostgREST is running on its configured port. A request will return ``200 OK`` if PostgREST is alive or ``500`` otherwise.
For instance, to verify if PostgREST is running while the ``admin-server-port`` is set to ``3001``:
.. code-block:: bash
curl -I "http://localhost:3001/live"
.. code-block:: http
HTTP/1.1 200 OK
Ready
-----
Additionally to the ``live`` check, the ``ready`` endpoint checks the state of the :ref:`connection_pool` and the :ref:`schema_cache`. A request will return ``200 OK`` if both are good or ``503`` if not.
.. code-block:: bash
curl -I "http://localhost:3001/ready"
.. code-block:: http
HTTP/1.1 200 OK
PostgREST will try to recover from the ``503`` state with :ref:`automatic_recovery`.
Metrics
=======
Provides :ref:`metrics`.
Runtime Configuration
=====================
Provides a ``config`` endpoint that returns the runtime :ref:`configuration`.
.. code-block:: bash
curl "http://localhost:3001/config"
.. code-block::
db-aggregates-enabled = false
db-anon-role = "web_anon"
db-channel = "pgrst"
db-channel-enabled = false
...
Runtime Schema Cache
====================
Provides the ``schema_cache`` endpoint that prints the runtime :ref:`schema_cache`.
.. code-block:: bash
curl "http://localhost:3001/schema_cache"
.. code-block:: json
{
"dbMediaHandlers": ["..."],
"dbRelationships": ["..."],
"dbRepresentations": ["..."],
"dbRoutines": ["..."],
"dbTables": ["..."],
"dbTimezones": ["..."]
}
+29 -29
View File
@@ -3,14 +3,14 @@
API
###
PostgREST exposes three database objects of a schema as resources: tables, views and stored procedures.
PostgREST exposes three database objects of a schema as resources: tables, views and functions.
.. toctree::
:glob:
:maxdepth: 1
api/tables_views.rst
api/stored_procedures.rst
api/functions.rst
api/schemas.rst
api/computed_fields.rst
api/domain_representations.rst
@@ -30,22 +30,22 @@ PostgREST exposes three database objects of a schema as resources: tables, views
const redirects = {
// Tables and Views
'#horizontal-filtering-rows': 'api/tables_views.html#horizontal-filtering-rows',
'#horizontal-filtering-rows': 'api/tables_views.html#horizontal-filtering',
'#operators': 'api/tables_views.html#operators',
'#logical-operators': 'api/tables_views.html#logical-operators',
'#pattern-matching': 'api/tables_views.html#pattern-matching',
'#full-text-search': 'api/tables_views.html#full-text-search',
'#vertical-filtering-columns': 'api/tables_views.html#vertical-filtering-columns',
'#vertical-filtering-columns': 'api/tables_views.html#vertical-filtering',
'#renaming-columns': 'api/tables_views.html#renaming-columns',
'#casting-columns': 'api/tables_views.html#casting-columns',
'#json-columns': 'api/tables_views.html#json-columns',
'#composite-array-columns': 'api/tables_views.html#composite-array-columns',
'#computed-virtual-columns': 'api/computed_fields.html#computed-fields',
'#computed-virtual-columns': 'api/computed_fields.html',
'#ordering': 'api/tables_views.html#ordering',
'#limits-and-pagination': 'api/tables_views.html#limits-and-pagination',
'#exact-count': 'api/tables_views.html#exact-count',
'#planned-count': 'api/tables_views.html#planned-count',
'#estimated-count': 'api/tables_views.html#estimated-count',
'#limits-and-pagination': 'api/pagination_count.html',
'#exact-count': 'api/pagination_count.html#exact-count',
'#planned-count': 'api/pagination_count.html#planned-count',
'#estimated-count': 'api/pagination_count.html#estimated-count',
'#updates': 'api/tables_views.html#update',
'#insertions': 'api/tables_views.html#insert',
'#bulk-insert': 'api/tables_views.html#bulk-insert',
@@ -55,15 +55,15 @@ PostgREST exposes three database objects of a schema as resources: tables, views
'#put': 'api/tables_views.html#put',
'#deletions': 'api/tables_views.html#delete',
'#limited-updates-deletions': 'api/tables_views.html#limited-update-delete',
// Stored procedures
'#stored-procedures': 'api/stored_procedures.html#stored-procedures',
'#calling-functions-with-a-single-json-parameter': 'api/stored_procedures.html#functions-with-a-single-json-parameter',
'#calling-functions-with-a-single-unnamed-parameter': 'api/stored_procedures.html#functions-with-a-single-unnamed-parameter',
'#calling-functions-with-array-parameters': 'api/stored_procedures.html#functions-with-array-parameters',
'#calling-variadic-functions': 'api/stored_procedures.html#variadic-functions',
'#scalar-functions': 'api/stored_procedures.html#scalar-functions',
'#function-filters': 'api/stored_procedures.html#table-valued-functions',
'#overloaded-functions': 'api/stored_procedures.html#overloaded-functions',
// Functions
'#stored-procedures': 'api/functions.html',
'#calling-functions-with-a-single-json-parameter': 'api/functions.html#functions-with-a-single-json-parameter',
'#calling-functions-with-a-single-unnamed-parameter': 'api/functions.html#functions-with-a-single-unnamed-parameter',
'#calling-functions-with-array-parameters': 'api/functions.html#functions-with-array-parameters',
'#calling-variadic-functions': 'api/functions.html#variadic-functions',
'#scalar-functions': 'api/functions.html#scalar-functions',
'#function-filters': 'api/functions.html#table-valued-functions',
'#overloaded-functions': 'api/functions.html#overloaded-functions',
// Schemas
'#switching-schemas': 'api/schemas.html',
// Resource Embedding
@@ -76,21 +76,21 @@ PostgREST exposes three database objects of a schema as resources: tables, views
'#nested-embedding': 'api/resource_embedding.html#nested-embedding',
'#embedded-filters': 'api/resource_embedding.html#embedded-filters',
'#embedding-with-top-level-filtering': 'api/resource_embedding.html#top-level-filtering',
'#embedding-partitioned-tables': 'api/resource_embedding.html#embedding-partitioned-tables',
'#embedding-views': 'api/resource_embedding.html#embedding-views',
'#embedding-chains-of-views': 'api/resource_embedding.html#embedding-chains-of-views',
'#embedding-on-stored-procedures': 'api/resource_embedding.html#embedding-on-stored-procedures',
'#embedding-after-insertions-updates-deletions': 'api/resource_embedding.html#embedding-after-insertions-updates-deletions',
'#embedding-disambiguation': 'api/resource_embedding.html#embedding-disambiguation',
'#target-disambiguation': 'api/resource_embedding.html#target-disambiguation',
'#hint-disambiguation': 'api/resource_embedding.html#hint-disambiguation',
'#embedding-partitioned-tables': 'api/resource_embedding.html#foreign-key-joins-on-partitioned-tables',
'#embedding-views': 'api/resource_embedding.html#foreign-key-joins-on-views',
'#embedding-chains-of-views': 'api/resource_embedding.html#foreign-key-joins-on-chains-of-views',
'#embedding-on-stored-procedures': 'api/resource_embedding.html#foreign-key-joins-on-table-valued-functions',
'#embedding-after-insertions-updates-deletions': 'api/resource_embedding.html#foreign-key-joins-on-writes',
'#embedding-disambiguation': 'api/resource_embedding.html#foreign-key-joins-on-multiple-foreign-key-relationships',
'#target-disambiguation': 'api/resource_embedding.html#foreign-key-joins-on-multiple-foreign-key-relationships',
'#hint-disambiguation': 'api/resource_embedding.html#foreign-key-joins-on-multiple-foreign-key-relationships',
"#embedding-through-join-tables": "api/resource_embedding.html#many-to-many-relationships",
// OpenAPI
'#openapi-support': 'api/openapi.html',
// Resource Representation
'#response-format': 'api/resource_representation.html#response-format',
'#singular-or-plural': 'api/resource_representation.html#singular-or-plural',
'#response-formats-for-scalar-responses': 'api/resource_representation.html#scalar-function-response-format',
'#response-formats-for-scalar-responses': 'api/functions.html#scalar-functions',
// CORS
'#cors': 'api/cors.html',
// OPTIONS
@@ -109,9 +109,9 @@ PostgREST exposes three database objects of a schema as resources: tables, views
'#setting-response-headers': 'transactions.html#response-headers',
'#setting-headers-via-pre-request': 'transactions.html#setting-headers-via-pre-request',
'#setting-response-status-code': 'transactions.html#response-status-code',
'#raise-errors-with-http-status-codes': 'transactions.html#raise-errors-with-http-status-codes',
'#raise-errors-with-http-status-codes': 'errors.html#raise-errors-with-http-status-codes',
// Admin
'#execution-plan': 'admin.html#execution-plan',
'#execution-plan': 'observability.html#execution-plan',
// Deprecated
'#bulk-call': '../releases/v11.0.1.html#breaking-changes',
};
+79 -168
View File
@@ -3,26 +3,20 @@
Aggregate Functions
###################
Aggregate functions allow you to summarize data by performing calculations across groups of rows. For instance, if you have an ``orders`` table that has an ``amount`` column, you could use an aggregate function to get the sum of the ``amount`` column, either for all rows, or for each group of rows that share specific values, for instance all rows that share the same ``order_date``.
PostgREST supports the following aggregate functions: ``avg()``, ``count()``, ``max()``, ``min()``, and ``sum()``.
Please refer to the `section on aggregate functions in the PostgreSQL documentation <https://www.postgresql.org/docs/current/functions-aggregate.html>`_ for a detailed explanation of these functions.
.. note::
Aggregate functions are *disabled* by default in PostgREST, as without appropriate safeguards, aggregate functions can create performance problems. See :ref:`db-aggregates-enabled` for further details.
Aggregate functions are *disabled* by default in PostgREST, because they can create performance problems without appropriate safeguards.
See :ref:`db-aggregates-enabled` for further details.
PostgREST supports the following aggregate functions: ``avg()``, ``count()``, ``max()``, ``min()``, and ``sum()``. Please refer to the `section on aggregate functions in the PostgreSQL documentation <https://www.postgresql.org/docs/current/functions-aggregate.html>`_ for a detailed explanation of these functions.
To use an aggregate function, append it to a column in the ``select`` parameter, like so:
To use an aggregate function, you append the function to a value in the ``select`` parameter, like so:
.. code-block:: bash
.. tabs::
curl "http://localhost:3000/orders?select=amount.sum()"
.. code-tab:: http
GET /orders?select=amount.sum() HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.sum()"
With the above query, PostgREST will return a single row with a single column named ``sum`` that contains the sum of all the values in the ``amount`` column:
This will return a ``sum`` of all the values of the ``amount`` column in a single row:
.. code-block:: json
@@ -32,21 +26,29 @@ With the above query, PostgREST will return a single row with a single column na
}
]
You can use multiple aggregate functions by just adding more columns with aggregate functions to the ``select`` parameter.
You can ``select`` multiple aggregate functions at the same time (you may need to :ref:`rename them <renaming_columns>` to disambiguate).
To group by other columns, you simply add those columns to the ``select`` parameter. For instance:
.. code-block:: bash
.. tabs::
curl "http://localhost:3000/orders?select=total_amount:amount.sum(),avg_amount:amount.avg(),total_quantity:quantity.sum()"
.. code-tab:: http
.. note::
Aggregate functions work alongside other PostgREST features, like :ref:`h_filter`, :ref:`json_columns`, and :ref:`ordering`.
However they are not compatible with :ref:`domain_reps` for the moment.
Additionally, PostgreSQL's ``HAVING`` clause and ordering by aggregated columns are not yet supported.
GET /orders?select=amount.sum(),amount.avg(),order_date HTTP/1.1
Automatic ``GROUP BY``
======================
.. code-tab:: bash Curl
In SQL, a ``GROUP BY`` clause is required to aggregate the selected columns.
However, PostgREST handles grouping automatically if the columns are already present in the ``select`` parameter.
For instance:
curl "http://localhost:3000/orders?select=amount.sum(),amount.avg(),order_date"
.. code-block:: bash
This will return a row for each unique value in the ``order_date`` column, with the sum and average of the ``amount`` column for all rows that share the same ``order_date``:
curl "http://localhost:3000/orders?select=amount.sum(),amount.avg(),order_date"
This will get the sum and average of the amounts grouped by each unique value in the ``order_date`` column:
.. code-block:: json
@@ -63,78 +65,54 @@ This will return a row for each unique value in the ``order_date`` column, with
}
]
.. note::
Aggregate functions work alongside other PostgREST features, like :ref:`h_filter`, :ref:`json_columns`, and :ref:`ordering`. Please note at this time aggregate functions are not compatible with :ref:`domain_reps`. Additionally, PostgreSQL's ``HAVING`` clause and ordering by aggregated columns are not yet supported.
The Case of ``count()``
===========================
The ``count()`` Aggregate
=========================
.. note::
Before the addition of aggregate functions, it was possible to count by adding ``count`` (without parentheses) to the ``select`` parameter. While this is still supported, it may be deprecated in the future, and thus use of this legacy feature is **not recommended.** Please use ``count()`` (with parentheses) instead.
Before the addition of aggregate functions, it was possible to count by adding ``count`` (without parentheses) to the ``select`` parameter.
While this is still supported, it may be deprecated in the future, and thus use of this legacy feature is **not recommended**.
Please use ``count()`` (with parentheses) instead.
``count()`` is a special case because it can be used with or without an aggregated column. For example:
``count()`` is treated specially, as it can be used without an associated column. Take for example the following query:
.. code-block:: bash
.. tabs::
.. code-tab:: http
GET /orders?select=count(),order_date HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=count(),order_date"
This would return a row for each unique value in the ``order_date`` column, with the count of all rows that share the same ``order_date``:
curl "http://localhost:3000/orders?select=count(),observation_count:observation.count(),order_date"
.. code-block:: json
[
{
"count": 4,
"observation_count": 2,
"order_date": "2023-01-01"
},
{
"count": 2,
"observation_count": 1,
"order_date": "2023-01-02"
}
]
When ``count()`` is used with an associated column, its behaviour is slightly different: It will return the count of all values that are not ``NULL``. This is due to how PostgreSQL itself implements the ``count()`` function.
Renaming and Casting
====================
Renaming Aggregates
-------------------
Just like with other columns, you can rename aggregated columns too. See :ref:`renaming_columns` for details.
Renaming columns is especially helpful in the context of aggregate functions, as by default a column with an aggregate function applied will take on the name of the applied aggregate function. You may want to provide a more semantically meaningful name or prevent collisions when using multiple aggregate functions of the same type.
Note that there is a difference between the result of ``count()`` and ``observation.count()``.
The former counts the whole row, while the latter counts the non ``NULL`` values of the ``observation`` column (both grouped by ``order_date``).
This is due to how PostgreSQL itself implements the ``count()`` function.
Casting Aggregates
------------------
==================
When applying an aggregate function to a column, you are able to cast both the value of the input to the aggregate function *and* the value of the output from the aggregate function. In both cases, the syntax works as described in :ref:`casting_columns`, with the only difference being the placement of the cast.
It is :ref:`possible to cast <casting_columns>` the aggregated column or the aggregate itself, or both at the same time.
Casting the Value of the Input
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Casting the Aggregated Column
-----------------------------
For instance, imagine that the ``orders`` table has a JSON column, ``order_details``, and this column contains a JSON object that has a key, ``tax_amount``. Let's say you want to get the sum of the tax amount for every order. You can use the ``->`` or ``->>`` operators to extract the value with this key (see :ref:`json_columns`), but these operators will return values of the types JSON and ``text`` respectively, and neither of these types can be used with ``sum()``.
For example, let's say that ``orders`` has an ``order_details`` :ref:`JSON column <json_columns>` with a ``tax_amount`` key.
We cannot sum ``tax_amount`` directly because using ``->`` or ``->>`` will return the data in ``json`` or ``text`` format.
So we need to cast it to a compatible type (e.g. ``numeric``) right before the aggregate function:
Therefore, you will need to first cast the input value to a type that is compatible with ``sum()`` (e.g. ``numeric``). Casting the input value is done in exactly the same way as casting any other value:
.. code-block:: bash
.. tabs::
.. code-tab:: http
GET /orders?select=order_details->tax_amount::numeric.sum() HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=order_details->tax_amount::numeric.sum()"
With this, you will receive the sum of the casted ``tax_amount`` value:
curl "http://localhost:3000/orders?select=order_details->tax_amount::numeric.sum()"
.. code-block:: json
@@ -144,22 +122,14 @@ With this, you will receive the sum of the casted ``tax_amount`` value:
}
]
Casting the Value of the Output
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Casting the Aggregate
---------------------
Now let's return to an example involving the ``amount`` column of the ``orders`` table. Imagine that we want to get the rounded average of the ``amount`` column. One way to do this is to use the ``avg()`` aggregate function and then to cast the output value of the function to ``int``. To cast the value of the output of the function, we simply place the cast *after* the aggregate function:
For instance, if we wanted to round the average of the ``amount`` column, we could do so by casting ``avg()`` to an ``int``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /orders?select=amount.avg()::int HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.avg()::int"
You will then receive the rounded average as the result:
curl "http://localhost:3000/orders?select=amount.avg()::int"
.. code-block:: json
@@ -169,32 +139,21 @@ You will then receive the rounded average as the result:
}
]
Of course, you can use both input and output casts at the same time, if you so desire.
Aggregates and Resource Embedding
=================================
You can group an aggregate function by an :ref:`embedded resource <resource_embedding>` and also use the aggregates inside them.
Using Aggregate Functions with Resource Embedding
=================================================
Grouping by an Embedded Resource
--------------------------------
Aggregate functions can be used in conjunction with :ref:`resource_embedding`. You can use embedded resources as grouping columns, use aggregate functions within the context of an embedded resource, or use columns from a spreaded resource as grouping columns or as inputs to aggregate functions.
Similar to grouping by columns, aggregate functions can also be grouped by embedded resources.
For example, let's say that the ``orders`` table is related to a ``customers`` table.
To get the sum of the ``amount`` column grouped by the ``name`` column from the ``customers`` table, we would do the following:
Using Embedded Resources as Grouping Columns
--------------------------------------------
.. code-block:: bash
Using an embedded resource as a grouping column allows you to use data from an association to group the results of an aggregation.
For example, imagine that the ``orders`` table from the examples above is related to a ``customers`` table. If you want to get the sum of the ``amount`` column grouped by the ``name`` column from the ``customers`` table, you can include the customer name, using the standard :ref:`resource_embedding` syntax, and perform a sum on the ``amount`` column.
.. tabs::
.. code-tab:: http
GET /orders?select=amount.sum(),customers(name) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.sum(),customers(name)"
You will then get the summed amount, along with the embedded customer resource:
curl "http://localhost:3000/orders?select=amount.sum(),customers(name)"
.. code-block:: json
@@ -213,25 +172,20 @@ You will then get the summed amount, along with the embedded customer resource:
}
]
.. note::
The previous example uses a has-one association to demonstrate this functionality, but you may also use has-many associations as grouping columns, although there are few obvious use cases for this.
The previous example uses a "to-one" relationship, but this can be done on "to-many" relationships as well (although there are few obvious use cases).
Using Aggregate Functions Within the Context of an Embedded Resource
--------------------------------------------------------------------
This also works in a similar way for :ref:`spread embedded resources <spread_embed>`.
For example, ``select=amount.sum(),...customers(name)`` would sum the ``amount`` grouped by the ``name`` column.
When embedding a resource, you can apply aggregate functions to columns from the associated resource to perform aggregations within the context of an embedded resource.
Using Aggregates Inside Embedded Resources
------------------------------------------
Continuing with the example relationship between ``orders`` and ``customers`` from the previous section, imagine that you want to fetch the ``name``, ``city``, and ``state`` for each customer, along with the sum of amount of the customer's orders, grouped by the order date. This can be done in the following way:
Using the relationship from the previous example, let's take all the ``customers`` and embed their ``orders``.
If we also want to get the total ``amount`` grouped by the ``order_date`` of the ``orders``, we would do the following:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /customers?select=name,city,state,orders(amount.sum(),order_date) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/customers?select=name,city,state,orders(amount.sum(),order_date)"
curl "http://localhost:3000/customers?select=name,city,state,orders(amount.sum(),order_date)"
.. code-block:: json
@@ -268,63 +222,20 @@ Continuing with the example relationship between ``orders`` and ``customers`` fr
}
]
In this example, the ``amount`` column is summed and grouped by the ``order_date`` *within* the context of the embedded resource. That is, the ``name``, ``city``, and ``state`` from the ``customers`` table have no bearing on the aggregation performed in the context of the ``orders`` association; instead, each aggregation can be seen as being performed independently on just the orders belonging to a particular customer, using only the data from the embedded resource for both grouping and aggregation.
Note that the aggregate is done within the embedded resource ``orders``.
It is not affected by any of the columns from the top-level relationship ``customers``.
Using Columns from a Spreaded Resource
--------------------------------------
Using Aggregates in Spreads
~~~~~~~~~~~~~~~~~~~~~~~~~~~
When you :ref:`spread an embedded resource <spread_embed>`, the columns from the spreaded resource are treated as if they were columns of the top-level resource, both when using them as grouping columns and when applying aggregate functions to them.
All the aggregates inside a :ref:`spread embedded resource <spread_embed>` will be hoisted to the top-level relationship.
In other words, it will behave as if the aggregate was done in the top-level relationship itself. For example:
Grouping with Columns from a Spreaded Resource
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
For instance, assume you want to sum the ``amount`` column from the ``orders`` table, using the ``city`` and ``state`` columns from the ``customers`` table as grouping columns. To achieve this, you may select these two columns from the ``customers`` table and spread them; they will then be used as grouping columns:
curl "http://localhost:3000/orders?select=order_date,...customers(subscription_date.max(),subscription_date.min())
.. tabs::
.. code-tab:: http
GET /orders?select=amount.sum(),...customers(city,state) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=amount.sum(),...customers(city,state)
The result will be the same as if ``city`` and ``state`` were columns from the ``orders`` table:
.. code-block:: json
[
{
"sum": 2000.29,
"city": "New York",
"state": "NY"
},
{
"sum": 9241.21,
"city": "Los Angeles",
"state": "CA"
}
]
Aggregate Functions with Columns from a Spreaded Resource
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now imagine that the ``customers`` table has a ``joined_date`` column that represents the date that the customer joined. You want to get both the most recent and the oldest ``joined_date`` for customers that placed an order on every distinct order date. This can be expressed as follows:
.. tabs::
.. code-tab:: http
GET /orders?select=order_date,...customers(joined_date.max(),joined_date.min()) HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/orders?select=order_date,...customers(joined_date.max(),joined_date.min())
As columns from a spreaded resource are treated as if they were columns from the top-level resource, the ``max()`` and ``min()`` are applied *within* the context of the top-level, rather than within the context of the embedded resource, as in the previous section.
The result will be the same as if the aggregations were applied to columns from the top-level:
This will take the ``max`` and ``min`` subscription date of every customer and group it by the ``order_date`` column:
.. code-block:: json
+7 -25
View File
@@ -30,15 +30,9 @@ Horizontal Filtering on Computed Fields
CREATE INDEX people_full_name_idx ON people
USING GIN (to_tsvector('english', full_name(people)));
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?full_name=fts.Beckett HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?full_name=fts.Beckett"
curl "http://localhost:3000/people?full_name=fts.Beckett"
.. code-block:: json
@@ -51,15 +45,9 @@ Vertical Filtering on Computed Fields
Computed fields won't appear on the response by default but you can use :ref:`v_filter` to include them:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?select=full_name,job HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?select=full_name,job"
curl "http://localhost:3000/people?select=full_name,job"
.. code-block:: json
@@ -72,19 +60,13 @@ Ordering on Computed Fields
:ref:`ordering` on computed fields is also possible:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?order=full_name.desc HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?order=full_name.desc"
curl "http://localhost:3000/people?order=full_name.desc"
.. important::
Computed columns must be created in the :ref:`exposed schema <db-schemas>` or in a schema in the :ref:`extra search path <db-extra-search-path>` to be used in this way. When placing the computed column in the :ref:`exposed schema <db-schemas>` you can use an **unnamed** parameter, as in the example above, to prevent it from being exposed as an :ref:`RPC <s_procs>` under ``/rpc``.
Computed fields must be created in the :ref:`exposed schema <db-schemas>` or in a schema in the :ref:`extra search path <db-extra-search-path>` to be used in this way. When placing the computed field in the :ref:`exposed schema <db-schemas>` you can use an **unnamed** parameter, as in the example above, to prevent it from being exposed as an :ref:`RPC <functions>` under ``/rpc``.
.. note::
+6 -16
View File
@@ -10,22 +10,13 @@ It also handles `preflight requests <https://developer.mozilla.org/en-US/docs/Gl
A ``POST`` preflight request would look like this:
.. tabs::
.. code-block:: bash
.. code-tab:: http
OPTIONS /items HTTP/1.1
Origin: http://example.com
Access-Control-Allow-Method: POST
Access-Control-Allow-Headers: Content-Type
.. code-tab:: bash Curl
curl -i "http://localhost:3000/items" \
-X OPTIONS \
-H "Origin: http://example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type"
curl -i "http://localhost:3000/items" \
-X OPTIONS \
-H "Origin: http://example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type"
.. code-block:: http
@@ -47,4 +38,3 @@ With the following config setting, PostgREST will accept CORS requests from doma
.. code-block::
server-cors-allowed-origins="http://example.com, http://example2.com"
+13 -37
View File
@@ -58,17 +58,10 @@ Then create a CAST to tell PostgREST to convert it automatically whenever a JSON
With this you can obtain the data in the shortened format.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /profiles HTTP/1.1
Accept: application/json
.. code-tab:: bash Curl
curl "http://localhost:3000/profiles" \
-H "Accept: application/json"
curl "http://localhost:3000/profiles" \
-H "Accept: application/json"
.. code-block:: json
@@ -102,17 +95,10 @@ PostgREST considers the URL query string to be, in the most generic sense, ``tex
Now you can filter as usual.
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /profiles?id=eq.hGxP/ZLOTeeNEY4pkp9OxA== HTTP/1.1
Accept: application/json
.. code-tab:: bash Curl
curl "http://localhost:3000/profiles?id=eq.ZLOTeeNEY4pkp9OxA==" \
-H "Accept: application/json"
curl "http://localhost:3000/profiles?id=eq.ZLOTeeNEY4pkp9OxA==" \
-H "Accept: application/json"
.. code-block:: json
@@ -139,26 +125,16 @@ To accept the shortened format in a JSON request body, for example when creating
Now we can :ref:`insert` (or :ref:`update`) as usual.
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/profiles" \
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d @- <<JSON
POST /profiles HTTP/1.1
Content-Type: application/json
Prefer: return=representation
{"id":"zH7HbFJUTfy/GZpwuirpuQ==","name":"Jane Doe"}
{"id":"zH7HbFJUTfy/GZpwuirpuQ==","name":"Jane Doe"}
.. code-tab:: bash Curl
curl "http://localhost:3000/profiles" \
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d @- <<JSON
{"id":"zH7HbFJUTfy/GZpwuirpuQ==","name":"Jane Doe"}
JSON
JSON
The response:
@@ -1,21 +1,25 @@
.. _s_procs:
.. _functions:
Stored Procedures
=================
Functions as RPC
================
*"A single resource can be the equivalent of a database stored procedure, with the power to abstract state changes over any number of storage items"* -- `Roy T. Fielding <http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven#comment-743>`_
*"A single resource can be the equivalent of a database function, with the power to abstract state changes over any number of storage items"* -- `Roy T. Fielding <https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven#comment-743>`_
Procedures can perform any operations allowed by PostgreSQL (read data, modify data, :ref:`raise errors <raise_error>`, and even DDL operations). Every stored procedure in the :ref:`exposed schema <schemas>` and accessible by the :ref:`active database role <roles>` is executable under the :code:`/rpc` prefix.
Functions can perform any operation allowed by PostgreSQL (read data, modify data, :ref:`raise errors <raise_error>`, and even DDL operations). Every function in the :ref:`exposed schema <schemas>` and accessible by the :ref:`active database role <roles>` is executable under the :code:`/rpc` prefix.
If they return table types, Stored Procedures can:
If they return table types, functions can:
- Use all the same :ref:`read filters as Tables and Views <read>` (horizontal/vertical filtering, counts, limits, etc.).
- Use :ref:`Resource Embedding <s_proc_embed>`, if the returned table type has relationships to other tables.
- Use :ref:`Resource Embedding <function_embed>`, if the returned table type has relationships to other tables.
.. note::
Why the ``/rpc`` prefix? PostgreSQL allows a table or view to have the same name as a function. The prefix allows us to avoid routes collisions.
.. warning::
`Stored Procedures <https://www.postgresql.org/docs/current/xproc.html>`_ are not supported.
Calling with POST
-----------------
@@ -23,7 +27,7 @@ To supply arguments in an API call, include a JSON object in the request payload
For instance, assume we have created this function in the database.
.. code-block:: plpgsql
.. code-block:: postgres
CREATE FUNCTION add_them(a integer, b integer)
RETURNS integer AS $$
@@ -36,19 +40,11 @@ For instance, assume we have created this function in the database.
The client can call it by posting an object like
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/add_them HTTP/1.1
{ "a": 1, "b": 2 }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/add_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "a": 1, "b": 2 }'
curl "http://localhost:3000/rpc/add_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "a": 1, "b": 2 }'
.. code-block:: json
@@ -67,80 +63,65 @@ Calling with GET
If the function doesn't modify the database, it will also run under the GET method (see :ref:`access_mode`).
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/add_them?a=1&b=2 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
The function parameter names match the JSON object keys in the POST case, for the GET case they match the query parameters ``?a=1&b=2``.
.. _s_proc_single_json:
.. _function_single_json:
Functions with a single JSON parameter
--------------------------------------
Functions with an array of JSON objects
----------------------------------------------
You can also call a function that takes a single parameter of type JSON by sending the header :code:`Prefer: params=single-object` with your request. That way the JSON request body will be used as the single argument.
If you want to pass multiple JSON objects to a Postgres function (an array of objects), you can create a function with a parameter of type ``json`` or ``jsonb``.
.. code-block:: plpgsql
Within the curl request, this JSON must be embedded in an object where they key matches the same name as the function's ``json`` or ``jsonb`` parameter.
This will allow you to loop over the array of JSON objects within the Postgres function.
CREATE FUNCTION mult_them(param json) RETURNS int AS $$
SELECT (param->>'x')::int * (param->>'y')::int
$$ LANGUAGE SQL;
This practice may allow you to reduce the number of ``curl`` requests required to accomplish a task.
.. tabs::
For instance, assume we have created this function in the database.
.. code-tab:: http
.. code-block:: postgres
POST /rpc/mult_them HTTP/1.1
Prefer: params=single-object
CREATE FUNCTION update_data(p_json jsonb)
RETURNS void AS $$
DECLARE
json_item json;
BEGIN
FOR json_item IN SELECT jsonb_array_elements(p_json) LOOP
UPDATE data_table SET data_text_column = (json_item->>'data_text')::text
WHERE data_int_column = (json_item->>'data_int')::integer;
END LOOP;
END;
$$ LANGUAGE SQL IMMUTABLE;
{ "x": 4, "y": 2 }
A ``curl`` request using the POST method would look like the following:
.. code-tab:: bash Curl
.. code-block:: bash
curl "http://localhost:3000/rpc/mult_them" \
-X POST -H "Content-Type: application/json" \
-H "Prefer: params=single-object" \
-d '{ "x": 4, "y": 2 }'
curl "http://localhost:3000/rpc/update_data" \
-X POST -H "Content-Type: application/json" \
-d '{ "p_json": [ { "data_text": "one", "data_int": "1" }, { "data_text": "two", "data_int": "2" } ] }'
.. code-block:: json
Functions with a single unnamed JSON parameter
----------------------------------------------
8
If you want the JSON request body to be sent as a single argument, you can create a function with a single unnamed ``json`` or ``jsonb`` parameter.
For this the ``Content-Type: application/json`` header must be included in the request.
.. _s_proc_single_unnamed:
Functions with a single unnamed parameter
-----------------------------------------
You can make a POST request to a function with a single unnamed parameter to send raw ``json/jsonb``, ``bytea``, ``text`` or ``xml`` data.
To send raw JSON, the function must have a single unnamed ``json`` or ``jsonb`` parameter and the header ``Content-Type: application/json`` must be included in the request.
.. code-block:: plpgsql
.. code-block:: postgres
CREATE FUNCTION mult_them(json) RETURNS int AS $$
SELECT ($1->>'x')::int * ($1->>'y')::int
$$ LANGUAGE SQL;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/mult_them HTTP/1.1
Content-Type: application/json
{ "x": 4, "y": 2 }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/mult_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "x": 4, "y": 2 }'
curl "http://localhost:3000/rpc/mult_them" \
-X POST -H "Content-Type: application/json" \
-d '{ "x": 4, "y": 2 }'
.. code-block:: json
@@ -148,13 +129,24 @@ To send raw JSON, the function must have a single unnamed ``json`` or ``jsonb``
.. note::
If an overloaded function has a single ``json`` or ``jsonb`` unnamed parameter, PostgREST will call this function as a fallback provided that no other overloaded function is found with the parameters sent in the POST request.
If an overloaded function has a single ``json`` or ``jsonb`` unnamed parameter, PostgREST will call this function as a fallback provided that no other overloaded function is found with the parameters sent in the POST request.
.. warning::
Sending the JSON request body as a single argument is also possible with :ref:`Prefer: params=single-object <prefer_params>` but this method is **deprecated**.
.. _function_single_unnamed:
Functions with a single unnamed parameter
-----------------------------------------
You can make a POST request to a function with a single unnamed parameter to send raw ``bytea``, ``text`` or ``xml`` data.
To send raw XML, the parameter type must be ``xml`` and the header ``Content-Type: text/xml`` must be included in the request.
To send raw binary, the parameter type must be ``bytea`` and the header ``Content-Type: application/octet-stream`` must be included in the request.
.. code-block:: plpgsql
.. code-block:: postgres
CREATE TABLE files(blob bytea);
@@ -162,20 +154,11 @@ To send raw binary, the parameter type must be ``bytea`` and the header ``Conten
INSERT INTO files(blob) VALUES ($1);
$$ LANGUAGE SQL;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/upload_binary HTTP/1.1
Content-Type: application/octet-stream
file_name.ext
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@file_name.ext"
curl "http://localhost:3000/rpc/upload_binary" \
-X POST -H "Content-Type: application/octet-stream" \
--data-binary "@file_name.ext"
.. code-block:: http
@@ -185,7 +168,7 @@ To send raw binary, the parameter type must be ``bytea`` and the header ``Conten
To send raw text, the parameter type must be ``text`` and the header ``Content-Type: text/plain`` must be included in the request.
.. _s_procs_array:
.. _functions_array:
Functions with array parameters
-------------------------------
@@ -198,20 +181,11 @@ You can call a function that takes an array parameter:
SELECT array_agg(n + 1) FROM unnest($1) AS n;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
Content-Type: application/json
{"arr": [1,2,3,4]}
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"arr": [1,2,3,4]}'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"arr": [1,2,3,4]}'
.. code-block:: json
@@ -220,37 +194,23 @@ You can call a function that takes an array parameter:
For calling the function with GET, you can pass the array as an `array literal <https://www.postgresql.org/docs/current/arrays.html#ARRAYS-INPUT>`_,
as in ``{1,2,3,4}``. Note that the curly brackets have to be urlencoded(``{`` is ``%7B`` and ``}`` is ``%7D``).
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/plus_one?arr=%7B1,2,3,4%7D' HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one?arr=%7B1,2,3,4%7D'"
curl "http://localhost:3000/rpc/plus_one?arr=%7B1,2,3,4%7D'"
.. note::
For versions prior to PostgreSQL 10, to pass a PostgreSQL native array on a POST payload, you need to quote it and use an array literal:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
{ "arr": "{1,2,3,4}" }
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{ "arr": "{1,2,3,4}" }'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{ "arr": "{1,2,3,4}" }'
In these versions we recommend using function parameters of type JSON to accept arrays from the client.
.. _s_procs_variadic:
.. _functions_variadic:
Variadic functions
------------------
@@ -263,20 +223,11 @@ You can call a variadic function by passing a JSON array in a POST request:
SELECT array_agg(n + 1) FROM unnest($1) AS n;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
Content-Type: application/json
{"v": [1,2,3,4]}
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"v": [1,2,3,4]}'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/json" \
-d '{"v": [1,2,3,4]}'
.. code-block:: json
@@ -284,63 +235,36 @@ You can call a variadic function by passing a JSON array in a POST request:
In a GET request, you can repeat the same parameter name:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/plus_one?v=1&v=2&v=3&v=4 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one?v=1&v=2&v=3&v=4"
curl "http://localhost:3000/rpc/plus_one?v=1&v=2&v=3&v=4"
Repeating also works in POST requests with ``Content-Type: application/x-www-form-urlencoded``:
.. tabs::
.. code-block:: bash
.. code-tab:: http
POST /rpc/plus_one HTTP/1.1
Content-Type: application/x-www-form-urlencoded
v=1&v=2&v=3&v=4
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d 'v=1&v=2&v=3&v=4'
curl "http://localhost:3000/rpc/plus_one" \
-X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d 'v=1&v=2&v=3&v=4'
.. _table_functions:
Table-Valued Functions
----------------------
A function that returns a table type can be filtered using the same filters as :ref:`tables and views <tables_views>`. They can also use :ref:`Resource Embedding <s_proc_embed>`.
A function that returns a table type can be filtered using the same filters as :ref:`tables and views <tables_views>`. They can also use :ref:`Resource Embedding <function_embed>`.
.. code-block:: postgres
CREATE FUNCTION best_films_2017() RETURNS SETOF films ..
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/rpc/best_films_2017?select=title,director:directors(*)"
GET /rpc/best_films_2017?select=title,director:directors(*) HTTP/1.1
.. code-block:: bash
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/best_films_2017?select=title,director:directors(*)"
.. tabs::
.. code-tab:: http
GET /rpc/best_films_2017?rating=gt.8&order=title.desc HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/best_films_2017?rating=gt.8&order=title.desc"
curl "http://localhost:3000/rpc/best_films_2017?rating=gt.8&order=title.desc"
.. _function_inlining:
@@ -361,19 +285,12 @@ For example, for the following function:
Let's get its :ref:`explain_plan` when calling it with filters applied:
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/rpc/getallprojects?id=eq.1" \
-H "Accept: application/vnd.pgrst.plan"
GET /rpc/getallprojects?id=eq.1 HTTP/1.1
Accept: application/vnd.pgrst.plan
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/getallprojects?id=eq.1" \
-H "Accept: application/vnd.pgrst.plan"
.. code-block:: psql
.. code-block:: postgres
Aggregate (cost=8.18..8.20 rows=1 width=112)
-> Index Scan using projects_pkey on projects (cost=0.15..8.17 rows=1 width=40)
@@ -388,29 +305,17 @@ Scalar functions
PostgREST will detect if the function is scalar or table-valued and will shape the response format accordingly:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/add_them?a=1&b=2 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
curl "http://localhost:3000/rpc/add_them?a=1&b=2"
.. code-block:: json
3
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/best_films_2017 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/best_films_2017"
curl "http://localhost:3000/rpc/best_films_2017"
.. code-block:: json
@@ -435,15 +340,9 @@ Functions that return ``record`` or ``SETOF record`` are supported:
select * from projects;
$$ language sql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /rpc/projects_setof_record HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/projects_setof_record"
curl "http://localhost:3000/rpc/projects_setof_record"
.. code-block:: json
@@ -466,25 +365,13 @@ You can call overloaded functions with different number of arguments.
CREATE FUNCTION rental_duration(customer_id integer, from_date date) ..
.. tabs::
.. code-block:: bash
.. code-tab:: http
curl "http://localhost:3000/rpc/rental_duration?customer_id=232"
GET /rpc/rental_duration?customer_id=232 HTTP/1.1
.. code-block:: bash
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/rental_duration?customer_id=232"
.. tabs::
.. code-tab:: http
GET /rpc/rental_duration?customer_id=232&from_date=2018-07-01 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/rpc/rental_duration?customer_id=232&from_date=2018-07-01"
curl "http://localhost:3000/rpc/rental_duration?customer_id=232&from_date=2018-07-01"
.. important::
+26 -20
View File
@@ -11,7 +11,7 @@ Media types are expressed as type aliases using `domains <https://www.postgresql
CREATE DOMAIN "application/json" AS json;
Using these domains, :ref:`functions <s_procs>` can become handlers and `user-defined aggregates <https://www.postgresql.org/docs/current/xaggr.html>`_ can serve as handlers for :ref:`tables_views` and :ref:`table_functions`.
Using these domains, :ref:`functions <functions>` can become handlers and `user-defined aggregates <https://www.postgresql.org/docs/current/xaggr.html>`_ can serve as handlers for :ref:`tables_views` and :ref:`table_functions`.
.. important::
@@ -95,16 +95,18 @@ Now we'll use it on a new aggregate defined for the ``lines`` table.
, sfunc = twkb_handler_transition
);
Make a quick test on SQL to see it working.
.. note::
.. code-block:: psql
You can test see this aggregate working with:
SELECT twkb_agg(l) from lines l;
.. code-block:: psql
twkb_agg
---------------------------------------------------------------
\xa20002c09a0cc09a0c80ea3080ea30a2000280b51880b51880ea3080ea30
(1 row)
SELECT twkb_agg(l) from lines l;
twkb_agg
---------------------------------------------------------------
\xa20002c09a0cc09a0c80ea3080ea30a2000280b51880b51880ea3080ea30
(1 row)
Now you can request the table endpoint with the ``twkb`` media type:
@@ -184,16 +186,20 @@ Now use the transition and final function as part of the new aggregate.
, finalfunc = bom_csv_final
);
.. code-block:: psql
.. note::
select bom_csv_agg(l) from lines l;
bom_csv_agg
-----------------------------------------------------------------------------------------------------
id,name,geom +
1,line-1,0102000020E610000002000000000000000000F03F000000000000F03F00000000000014400000000000001440+
2,line-2,0102000020E6100000020000000000000000000040000000000000004000000000000018400000000000001840+
You can test this with:
(1 row)
.. code-block:: psql
select bom_csv_agg(l) from lines l;
bom_csv_agg
-----------------------------------------------------------------------------------------------------
id,name,geom +
1,line-1,0102000020E610000002000000000000000000F03F000000000000F03F00000000000014400000000000001440+
2,line-2,0102000020E6100000020000000000000000000040000000000000004000000000000018400000000000001840+
(1 row)
And request it like:
@@ -215,11 +221,11 @@ And request it like:
The "Any" Handler
=================
For more flexibility, you can also define a catch-all handler by using a domain named ``*/*`` (any media type). This obeys to the following rules:
For more flexibility, you can also define a catch-all handler by using a domain named ``*/*`` (any media type). This handler obeys the following rules:
- Responds to all media types and even to requests that don't include an ``Accept`` header.
- Sets the ``Content-Type`` header to ``application/octet-stream`` by default, but this can be overridden inside the function with :ref:`guc_resp_hdrs`.
- This overrides all other handlers (:ref:`builtin <builtin_media>` or custom), so it's better to do it for an isolated function or view.
- It responds to all media types and even to requests that don't include an ``Accept`` header.
- It sets the ``Content-Type`` header to ``application/octet-stream`` by default, but this can be overridden inside the function with :ref:`guc_resp_hdrs`.
- It overrides all other handlers (:ref:`builtin <builtin_media>` or custom), so it's better to do it for an isolated function or view.
Let's define an any handler for a view that will always respond with ``XML`` output. It will accept ``text/xml``, ``application/xml``, ``*/*`` and reject other media types.
+5 -11
View File
@@ -11,7 +11,7 @@ PostgREST automatically serves a full `OpenAPI <https://www.openapis.org/>`_ des
For extra customization, the OpenAPI output contains a "description" field for every `SQL comment <https://www.postgresql.org/docs/current/sql-comment.html>`_ on any database object. For instance,
.. code-block:: sql
.. code-block:: postgres
COMMENT ON SCHEMA mammals IS
'A warm-blooded vertebrate animal of a class that is distinguished by the secretion of milk by females for the nourishment of the young';
@@ -26,7 +26,7 @@ These unsavory comments will appear in the generated JSON as the fields, ``info.
Also if you wish to generate a ``summary`` field you can do it by having a multiple line comment, the ``summary`` will be the first line and the ``description`` the lines that follow it:
.. code-block:: plpgsql
.. code-block:: postgres
COMMENT ON TABLE entities IS
$$Entities summary
@@ -37,7 +37,7 @@ Also if you wish to generate a ``summary`` field you can do it by having a multi
Similarly, you can override the API title by commenting the schema.
.. code-block:: plpgsql
.. code-block:: postgres
COMMENT ON SCHEMA api IS
$$FooBar API
@@ -81,15 +81,9 @@ You can override the whole default response with a function result. To do this,
end
$_$ language plpgsql;
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET / HTTP/1.1
.. code-tab:: bash Curl
curl http://localhost:3000
curl http://localhost:3000
.. code-block:: http
+2 -8
View File
@@ -7,15 +7,9 @@ You can verify which HTTP methods are allowed on endpoints for tables and views
For a table named ``people``, OPTIONS would show:
.. tabs::
.. code-block:: bash
.. code-tab:: http
OPTIONS /people HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people" -X OPTIONS -i
curl "http://localhost:3000/people" -X OPTIONS -i
.. code-block:: http
+20 -64
View File
@@ -23,15 +23,9 @@ Query Parameters
One way to request limits and offsets is by using query parameters. For example:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people?limit=15&offset=30 HTTP/1.1
.. code-tab:: bash Curl
curl "http://localhost:3000/people?limit=15&offset=30"
curl "http://localhost:3000/people?limit=15&offset=30"
This method is also useful for embedded resources, which we will cover in another section. The server always responds with range headers even if you use query parameters to limit the query.
@@ -41,19 +35,11 @@ Range Header
You can use headers to specify the range of rows desired.
This request gets the first twenty people:
.. tabs::
.. code-block:: bash
.. code-tab:: http
GET /people HTTP/1.1
Range-Unit: items
Range: 0-19
.. code-tab:: bash Curl
curl "http://localhost:3000/people" -i \
-H "Range-Unit: items" \
-H "Range: 0-19"
curl "http://localhost:3000/people" -i \
-H "Range-Unit: items" \
-H "Range: 0-19"
Note that the server may respond with fewer if unable to meet your request:
@@ -82,21 +68,12 @@ Exact Count
To get the exact count, use ``Prefer: count=exact``.
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /bigtable HTTP/1.1
Range-Unit: items
Range: 0-24
Prefer: count=exact
.. code-tab:: bash Curl
curl "http://localhost:3000/bigtable" -I \
-H "Range-Unit: items" \
-H "Range: 0-24" \
-H "Prefer: count=exact"
curl "http://localhost:3000/bigtable" -I \
-H "Range-Unit: items" \
-H "Range: 0-24" \
-H "Prefer: count=exact"
Note that the larger the table the slower this query runs in the database. The server will respond with the selected range and total
@@ -114,17 +91,10 @@ Planned Count
To avoid the shortcomings of :ref:`exact count <exact_count>`, PostgREST can leverage PostgreSQL statistics and get a fairly accurate and fast count.
To do this, specify the ``Prefer: count=planned`` header.
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /bigtable?limit=25 HTTP/1.1
Prefer: count=planned
.. code-tab:: bash Curl
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=planned"
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=planned"
.. code-block:: http
@@ -151,17 +121,10 @@ defined by :ref:`db-max-rows`.
Here's an example. Suppose we set ``db-max-rows=1000`` and ``smalltable`` has 321 rows, then we'll get the exact count:
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /smalltable?limit=25 HTTP/1.1
Prefer: count=estimated
.. code-tab:: bash Curl
curl "http://localhost:3000/smalltable?limit=25" -I \
-H "Prefer: count=estimated"
curl "http://localhost:3000/smalltable?limit=25" -I \
-H "Prefer: count=estimated"
.. code-block:: http
@@ -170,17 +133,10 @@ Here's an example. Suppose we set ``db-max-rows=1000`` and ``smalltable`` has 32
If we make a similar request on ``bigtable``, which has 3573458 rows, we would get the planned count:
.. tabs::
.. code-block:: bash
.. code-tab:: http
HEAD /bigtable?limit=25 HTTP/1.1
Prefer: count=estimated
.. code-tab:: bash Curl
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=estimated"
curl "http://localhost:3000/bigtable?limit=25" -I \
-H "Prefer: count=estimated"
.. code-block:: http

Some files were not shown because too many files have changed in this diff Show More