Full Code of PostgREST/postgrest for AI

main 12ef63370b0a cached
354 files
2.7 MB
715.4k tokens
853 symbols
1 requests
Download .txt
Showing preview only (2,855K chars total). Download the full file or copy to clipboard to get everything.
Repository: PostgREST/postgrest
Branch: main
Commit: 12ef63370b0a
Files: 354
Total size: 2.7 MB

Directory structure:
gitextract_dt40gs3b/

├── .cirrus.yml
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── actionlint.yml
│   ├── actions/
│   │   ├── artifact-from-cirrus/
│   │   │   └── action.yaml
│   │   ├── cache-on-main/
│   │   │   └── action.yaml
│   │   └── setup-nix/
│   │       └── action.yaml
│   ├── codecov.yml
│   ├── renovate.json
│   └── workflows/
│       ├── backport.yaml
│       ├── build.yaml
│       ├── check.yaml
│       ├── ci.yaml
│       ├── docs.yaml
│       ├── linkcheck.yaml
│       ├── release.yaml
│       └── test.yaml
├── .gitignore
├── .readthedocs.yaml
├── .stylish-haskell.yaml
├── BACKERS.md
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── Setup.hs
├── cabal.project
├── cabal.project.freeze
├── default.nix
├── docker-hub-readme.md
├── docs/
│   ├── .gitignore
│   ├── README.md
│   ├── _diagrams/
│   │   ├── README.md
│   │   ├── er/
│   │   │   ├── boxoffice.er
│   │   │   ├── employees.er
│   │   │   ├── film.er
│   │   │   ├── orders.er
│   │   │   ├── premieres.er
│   │   │   ├── presidents.er
│   │   │   └── users.er
│   │   └── uml/
│   │       ├── arch.uml
│   │       ├── dark/
│   │       │   ├── arch-dark.uml
│   │       │   └── sch-iso-dark.uml
│   │       └── sch-iso.uml
│   ├── _static/
│   │   └── css/
│   │       └── custom.css
│   ├── conf.py
│   ├── ecosystem.rst
│   ├── explanations/
│   │   ├── architecture.rst
│   │   ├── db_authz.rst
│   │   ├── external_auth.rst
│   │   ├── install.rst
│   │   ├── nginx.rst
│   │   └── schema_isolation.rst
│   ├── how-tos/
│   │   ├── create-soap-endpoint.rst
│   │   ├── providing-html-content-using-htmx.rst
│   │   ├── providing-images-for-img.rst
│   │   ├── sql-user-management-using-postgres-users-and-passwords.rst
│   │   ├── sql-user-management.rst
│   │   └── working-with-postgresql-data-types.rst
│   ├── index.rst
│   ├── integrations/
│   │   ├── pg-safeupdate.rst
│   │   └── systemd.rst
│   ├── postgrest.dict
│   ├── references/
│   │   ├── admin_server.rst
│   │   ├── api/
│   │   │   ├── aggregate_functions.rst
│   │   │   ├── computed_fields.rst
│   │   │   ├── cors.rst
│   │   │   ├── domain_representations.rst
│   │   │   ├── functions.rst
│   │   │   ├── media_type_handlers.rst
│   │   │   ├── openapi.rst
│   │   │   ├── options.rst
│   │   │   ├── pagination_count.rst
│   │   │   ├── preferences.rst
│   │   │   ├── resource_embedding.rst
│   │   │   ├── resource_representation.rst
│   │   │   ├── schemas.rst
│   │   │   ├── tables_views.rst
│   │   │   ├── url_grammar.rst
│   │   │   └── vary_header.rst
│   │   ├── api.rst
│   │   ├── auth.rst
│   │   ├── cli.rst
│   │   ├── configuration.rst
│   │   ├── connection_pool.rst
│   │   ├── errors.rst
│   │   ├── listener.rst
│   │   ├── observability.rst
│   │   ├── schema_cache.rst
│   │   └── transactions.rst
│   ├── requirements.txt
│   ├── shared/
│   │   └── installation.rst
│   └── tutorials/
│       ├── tut0.rst
│       └── tut1.rst
├── flake.nix
├── main/
│   └── Main.hs
├── nix/
│   ├── README.md
│   ├── UPGRADE.md
│   ├── hsie/
│   │   ├── Main.hs
│   │   ├── README.md
│   │   └── default.nix
│   ├── overlays/
│   │   ├── build-toolbox/
│   │   │   ├── build-toolbox.nix
│   │   │   └── default.nix
│   │   ├── checked-shell-script/
│   │   │   ├── checked-shell-script.nix
│   │   │   └── default.nix
│   │   ├── default.nix
│   │   ├── gitignore.nix
│   │   └── haskell-packages.nix
│   ├── static.nix
│   └── tools/
│       ├── cabalTools.nix
│       ├── devTools.nix
│       ├── docker/
│       │   ├── README.md
│       │   └── default.nix
│       ├── docs.nix
│       ├── gen_rsa_materials.py
│       ├── generate_targets.py
│       ├── gitTools.nix
│       ├── loadtest.nix
│       ├── merge_monitor_result.py
│       ├── monitor_pid.py
│       ├── nixpkgsTools.nix
│       ├── release.nix
│       ├── style.nix
│       ├── tests.nix
│       └── withTools.nix
├── postgrest.cabal
├── shell.nix
├── src/
│   └── PostgREST/
│       ├── Admin.hs
│       ├── ApiRequest/
│       │   ├── Payload.hs
│       │   ├── Preferences.hs
│       │   ├── QueryParams.hs
│       │   └── Types.hs
│       ├── ApiRequest.hs
│       ├── App.hs
│       ├── AppState.hs
│       ├── Auth/
│       │   ├── Jwt.hs
│       │   ├── JwtCache.hs
│       │   └── Types.hs
│       ├── Auth.hs
│       ├── CLI.hs
│       ├── Cache/
│       │   └── Sieve.hs
│       ├── Client.hs
│       ├── Config/
│       │   ├── Database.hs
│       │   ├── JSPath.hs
│       │   ├── PgVersion.hs
│       │   └── Proxy.hs
│       ├── Config.hs
│       ├── Cors.hs
│       ├── Error/
│       │   └── Types.hs
│       ├── Error.hs
│       ├── Listener.hs
│       ├── Logger.hs
│       ├── MainTx.hs
│       ├── MediaType.hs
│       ├── Metrics.hs
│       ├── Network.hs
│       ├── Observation.hs
│       ├── Plan/
│       │   ├── CallPlan.hs
│       │   ├── MutatePlan.hs
│       │   ├── Negotiate.hs
│       │   ├── ReadPlan.hs
│       │   └── Types.hs
│       ├── Plan.hs
│       ├── Query/
│       │   ├── PreQuery.hs
│       │   ├── QueryBuilder.hs
│       │   ├── SqlFragment.hs
│       │   └── Statements.hs
│       ├── Query.hs
│       ├── RangeQuery.hs
│       ├── Response/
│       │   ├── GucHeader.hs
│       │   ├── OpenAPI.hs
│       │   └── Performance.hs
│       ├── Response.hs
│       ├── SchemaCache/
│       │   ├── Identifiers.hs
│       │   ├── Relationship.hs
│       │   ├── Representations.hs
│       │   ├── Routine.hs
│       │   └── Table.hs
│       ├── SchemaCache.hs
│       ├── TimeIt.hs
│       ├── Unix.hs
│       └── Version.hs
├── stack.yaml
└── test/
    ├── coverage.overlay
    ├── doc/
    │   └── Main.hs
    ├── io/
    │   ├── __snapshots__/
    │   │   └── test_cli/
    │   │       ├── test_schema_cache_snapshot[dbMediaHandlers].yaml
    │   │       ├── test_schema_cache_snapshot[dbRelationships].yaml
    │   │       ├── test_schema_cache_snapshot[dbRepresentations].yaml
    │   │       ├── test_schema_cache_snapshot[dbRoutines].yaml
    │   │       ├── test_schema_cache_snapshot[dbTables].yaml
    │   │       └── test_schema_cache_snapshot[dbTimezones].yaml
    │   ├── config.py
    │   ├── configs/
    │   │   ├── aliases.config
    │   │   ├── boolean-numeric.config
    │   │   ├── boolean-string.config
    │   │   ├── defaults.config
    │   │   ├── expected/
    │   │   │   ├── aliases.config
    │   │   │   ├── boolean-numeric.config
    │   │   │   ├── boolean-string.config
    │   │   │   ├── defaults.config
    │   │   │   ├── jwt-role-claim-key1.config
    │   │   │   ├── jwt-role-claim-key2.config
    │   │   │   ├── jwt-role-claim-key3.config
    │   │   │   ├── jwt-role-claim-key4.config
    │   │   │   ├── jwt-role-claim-key5.config
    │   │   │   ├── no-defaults-with-db-other-authenticator.config
    │   │   │   ├── no-defaults-with-db.config
    │   │   │   ├── no-defaults.config
    │   │   │   ├── types.config
    │   │   │   └── utf-8.config
    │   │   ├── invalid.yaml
    │   │   ├── jwt-role-claim-key1.config
    │   │   ├── jwt-role-claim-key2.config
    │   │   ├── jwt-role-claim-key3.config
    │   │   ├── jwt-role-claim-key4.config
    │   │   ├── jwt-role-claim-key5.config
    │   │   ├── no-defaults-env.yaml
    │   │   ├── no-defaults.config
    │   │   ├── sigusr2-settings.config
    │   │   ├── types.config
    │   │   └── utf-8.config
    │   ├── conftest.py
    │   ├── fixtures/
    │   │   ├── big_schema.sql
    │   │   ├── database.sql
    │   │   ├── db_config.sql
    │   │   ├── fixtures.yaml
    │   │   ├── load.sql
    │   │   ├── privileges.sql
    │   │   ├── replica.sql
    │   │   ├── roles.sql
    │   │   └── schema.sql
    │   ├── postgrest.py
    │   ├── secrets/
    │   │   ├── ascii.b64
    │   │   ├── ascii.jwt
    │   │   ├── ascii.noeol
    │   │   ├── ascii.txt
    │   │   ├── binary.b64
    │   │   ├── binary.eol
    │   │   ├── binary.jwt
    │   │   ├── binary.noeol
    │   │   ├── utf8.b64
    │   │   ├── utf8.jwt
    │   │   ├── utf8.noeol
    │   │   ├── utf8.txt
    │   │   ├── word.b64
    │   │   ├── word.jwt
    │   │   ├── word.noeol
    │   │   └── word.txt
    │   ├── test_auth.py
    │   ├── test_big_schema.py
    │   ├── test_cli.py
    │   ├── test_io.py
    │   ├── test_replica.py
    │   ├── test_sanity.py
    │   └── util.py
    ├── load/
    │   ├── bulk.json
    │   ├── errors.http
    │   ├── errors.sql
    │   ├── fixtures.sql
    │   ├── patch.json
    │   ├── post.json
    │   ├── put.json
    │   ├── rpc.json
    │   └── targets.http
    ├── memory/
    │   └── memory-tests.sh
    ├── observability/
    │   ├── Main.hs
    │   ├── ObsHelper.hs
    │   ├── Observation/
    │   │   └── JwtCache.hs
    │   └── fixtures/
    │       ├── database.sql
    │       ├── load.sql
    │       ├── privileges.sql
    │       ├── roles.sql
    │       └── schema.sql
    ├── pgbench/
    │   ├── 1567/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── 1652/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── 2676/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── 2677/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── README.md
    │   └── fixtures.sql
    ├── spec/
    │   ├── Feature/
    │   │   ├── Auth/
    │   │   │   ├── AsymmetricJwtSpec.hs
    │   │   │   ├── AudienceJwtSecretSpec.hs
    │   │   │   ├── AuthSpec.hs
    │   │   │   ├── BinaryJwtSecretSpec.hs
    │   │   │   ├── NoAnonSpec.hs
    │   │   │   └── NoJwtSecretSpec.hs
    │   │   ├── ConcurrentSpec.hs
    │   │   ├── CorsSpec.hs
    │   │   ├── ExtraSearchPathSpec.hs
    │   │   ├── NoSuperuserSpec.hs
    │   │   ├── ObservabilitySpec.hs
    │   │   ├── OpenApi/
    │   │   │   ├── DisabledOpenApiSpec.hs
    │   │   │   ├── IgnorePrivOpenApiSpec.hs
    │   │   │   ├── OpenApiSpec.hs
    │   │   │   ├── ProxySpec.hs
    │   │   │   ├── RootSpec.hs
    │   │   │   └── SecurityOpenApiSpec.hs
    │   │   ├── OptionsSpec.hs
    │   │   ├── Query/
    │   │   │   ├── AggregateFunctionsSpec.hs
    │   │   │   ├── AndOrParamsSpec.hs
    │   │   │   ├── ComputedRelsSpec.hs
    │   │   │   ├── CustomMediaSpec.hs
    │   │   │   ├── DeleteSpec.hs
    │   │   │   ├── EmbedDisambiguationSpec.hs
    │   │   │   ├── EmbedInnerJoinSpec.hs
    │   │   │   ├── ErrorSpec.hs
    │   │   │   ├── InsertSpec.hs
    │   │   │   ├── JsonOperatorSpec.hs
    │   │   │   ├── MultipleSchemaSpec.hs
    │   │   │   ├── NullsStripSpec.hs
    │   │   │   ├── PgSafeUpdateSpec.hs
    │   │   │   ├── PlanSpec.hs
    │   │   │   ├── PostGISSpec.hs
    │   │   │   ├── PreferencesSpec.hs
    │   │   │   ├── QueryLimitedSpec.hs
    │   │   │   ├── QuerySpec.hs
    │   │   │   ├── RangeSpec.hs
    │   │   │   ├── RawOutputTypesSpec.hs
    │   │   │   ├── RelatedQueriesSpec.hs
    │   │   │   ├── RpcSpec.hs
    │   │   │   ├── ServerTimingSpec.hs
    │   │   │   ├── SingularSpec.hs
    │   │   │   ├── SpreadQueriesSpec.hs
    │   │   │   ├── UnicodeSpec.hs
    │   │   │   ├── UpdateSpec.hs
    │   │   │   └── UpsertSpec.hs
    │   │   ├── RollbackSpec.hs
    │   │   └── RpcPreRequestGucsSpec.hs
    │   ├── Main.hs
    │   ├── SpecHelper.hs
    │   └── fixtures/
    │       ├── 1.twkb
    │       ├── data.sql
    │       ├── database.sql
    │       ├── draft04.json
    │       ├── jsonschema.sql
    │       ├── jwt.sql
    │       ├── lines.csv
    │       ├── lines.twkb
    │       ├── load.sql
    │       ├── openapi.json
    │       ├── privileges.sql
    │       ├── roles.sql
    │       └── schema.sql
    └── weeder.toml

================================================
FILE CONTENTS
================================================

================================================
FILE: .cirrus.yml
================================================
freebsd_instance:
  image_family: freebsd-14-3

build_task:
  # Don't change this name without adjusting .github/workflows/build.yaml
  name: Build FreeBSD (Stack)
  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:
      - 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
    strip postgrest

  bin_artifacts:
    path: postgrest


================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .gitattributes
================================================
/CHANGELOG.md merge=union


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

patreon: postgrest


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a bug report to help us improve
type: Bug
title: ''
labels: ''
assignees: ''

---

<!--
Before reporting a bug:
If your database schema has changed while the PostgREST server is running,
send the server a SIGUSR1 signal or restart it (http://postgrest.org/en/stable/admin.html#schema-reloading) to ensure the schema cache is not stale. This sometimes fixes apparent bugs.
-->
### Environment

* PostgreSQL version: (if using docker, specify the image)
* PostgREST version: (if using docker, specify the image)
* Operating system:

### Description of issue

Describe the behavior you expected vs the actual behavior. Include:

- A minimal SQL definition.
- How you make the request to PostgREST (curl command preferred).
- The PostgREST response.


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an enhancement for this project
type: Feature
title: ''
labels: ''
assignees: ''

---

## Problem

A clear and concise description of what the problem is.

## Solution

A clear and concise description of what you want to happen.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
When submitting a new feature or fix:

- Add a new entry to the CHANGELOG - https://github.com/PostgREST/postgrest/blob/main/CHANGELOG.md#unreleased
- If relevant, update the docs
- Use a prefix for the PR title or commits, e.g. "fix: description of the fix".
  + `add`, Add a new feature
  + `amend`, To amend an unrealease commit
  + `change`, Breaking changes
  + `chore`, Maintenance, update sponsors, changelog, readme etc
  + `ci`, CI configuration files and scripts
  + `docs`, Documentation
  + `fix`, Bug fix
  + `nix`, Related to Nix
  + `perf`, Performance improvements
  + `refactor`, Refactoring code
  + `remove`, Remove a feature or fix
  + `test`, Adding tests
  + Other prefixes may be used if necessary
- If there's a breaking change, add `BREAKING CHANGE` and an explanation to your commit message
-->


================================================
FILE: .github/actionlint.yml
================================================
# 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


================================================
FILE: .github/actions/artifact-from-cirrus/action.yaml
================================================
name: Artifact from Cirrus

description: Waits for a specific Cirrus CI run to complete, then downloads the artifact and uploads it to the current workflow. This will silently succeed if Cirrus CI did not schedule a task within 2 minutes.

inputs:
  download:
    description: Name of Artifact to download from Cirrus CI
    required: true
  task:
    description: Name of Cirrus Task
    required: true
  token:
    description: GitHub Token
    required: true
  upload:
    description: Name of Artifact to upload on GitHub Actions
    required: true

runs:
  using: composite
  steps:
    - shell: bash
      run: echo "GH_TOKEN=${{ inputs.token }}" >> "$GITHUB_ENV"
    - name: Wait for Check Suite to be created
      id: check-suite
      env:
        # GITHUB_SHA does weird things for pull request, so we roll our own:
        COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
      shell: bash
      run: |
        get_check_runs_url() {
          gh api "repos/{owner}/{repo}/commits/${COMMIT}/check-suites" \
            | jq -r '.check_suites[] | select(.app.slug == "cirrus-ci") | .check_runs_url'
        }
        for _ in $(seq 1 12); do
          check_runs_url="$(get_check_runs_url)"
          if [ -z "$check_runs_url" ]; then
            echo "Cirrus CI task has not started, yet. Waiting..."
            sleep 10
          else
            echo "check_runs_url=$check_runs_url" >> "$GITHUB_OUTPUT"
            exit 0
          fi
        done
        >&2 echo "Cirrus CI check suite not found. Is Cirrus CI enabled for this repo?"
    - name: Find task by name
      id: find-task
      if: steps.check-suite.outputs.check_runs_url
      shell: bash
      run: |
        get_number_of_tasks() {
          gh api "${{ steps.check-suite.outputs.check_runs_url }}" \
            | jq -r '.check_runs | map(select(.name == "${{ inputs.task }}")) | length'
        }
        tasks="$(get_number_of_tasks)"
        case "$tasks" in
          0)
            echo "Task not found, assuming it's skipped intentionally..."
            exit 0
            ;;
          1)
            echo "task_found=1" >> "$GITHUB_OUTPUT"
            exit 0
            ;;
          *)
            >&2 echo "More than 1 task with the same name found. Don't know what to do..."
            exit 1
            ;;
        esac
    - name: Wait for Cirrus CI to complete task
      if: steps.find-task.outputs.task_found
      shell: bash
      run: |
        get_conclusion() {
          gh api "${{ steps.check-suite.outputs.check_runs_url }}" \
            | jq -r '.check_runs[] | select(.name == "${{ inputs.task }}" and .status == "completed") | .conclusion'
        }
        while true; do
          conclusion="$(get_conclusion)"
          if [ -z "$conclusion" ]; then
            echo "Cirrus CI task has not completed, yet. Waiting..."
            sleep 30
          else
            if [ "$conclusion" == "success" ]; then
              break
            else
              exit 1
            fi
          fi
        done
    - name: Download artifact from Cirrus CI
      if: steps.find-task.outputs.task_found
      id: download
      shell: bash
      run: |
        get_external_id() {
          gh api "${{ steps.check-suite.outputs.check_runs_url }}" \
            | jq -er '.check_runs[] | select(.name == "${{ inputs.task }}") | .external_id'
        }
        archive="$(mktemp)"
        artifacts="$(mktemp -d)"
        until curl --no-progress-meter --fail -o "${archive}" \
                "https://api.cirrus-ci.com/v1/artifact/task/$(get_external_id)/${{ inputs.download }}.zip"
        do
          # This happens when a tag is pushed on the same commit. In this case the
          # job is immediately marked as "completed" for us, so we end up here after a few
          # seconds - but the actual Cirrus CI task is still running and didn't produce its artifact, yet.
          echo "Artifact not found on Cirrus CI, yet. Waiting..."
          sleep 30
        done
        unzip "${archive}" -d "${artifacts}"
        echo "artifacts=${artifacts}" >> "$GITHUB_OUTPUT"
    - name: Save artifact to GitHub Actions
      if: steps.find-task.outputs.task_found
      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
      with:
        name: ${{ inputs.upload }}
        path: ${{ steps.download.outputs.artifacts }}
        if-no-files-found: error


================================================
FILE: .github/actions/cache-on-main/action.yaml
================================================
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@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
      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@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
      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 }}-


================================================
FILE: .github/actions/setup-nix/action.yaml
================================================
name: Setup Nix

description: Installs nix, sets up cachix and installs a subset of tooling.

inputs:
  authToken:
    description: Token to pass to cachix
  tools:
    description: Tools to install with nix-env -iA <tools>

runs:
  using: composite
  steps:
    - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 # v34
      with:
        nix_conf: |-
          always-allow-substitutes = true
          max-jobs = auto
    - uses: cachix/cachix-action@1eb2ef646ac0255473d23a5907ad7b04ce94065c # v17
      with:
        name: postgrest
        authToken: ${{ inputs.authToken }}
        skipPush: ${{ inputs.authToken == '' }}
    - if: ${{ inputs.tools }}
      run: nix-env -f default.nix -iA ${{ inputs.tools }}
      shell: bash


================================================
FILE: .github/codecov.yml
================================================
codecov:
  branch: main
  require_ci_to_pass: false

comment: false

coverage:
  status:
    project:
      default:
        target: auto
        threshold: 1%
        only_pulls: false
    patch:
      default:
        target: auto
        threshold: 1%
        only_pulls: true


================================================
FILE: .github/renovate.json
================================================
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "config:best-practices"
  ],
  "baseBranchPatterns": [
    "main",
    "/^v[0-9]+/"
  ],
  "rebaseWhen": "conflicted",
  "pip_requirements": {
    "enabled": false
  },
  "packageRules": [
    {
      "matchBaseBranches": [
        "/^v[0-9]+/"
      ],
      "matchManagers": [
        "haskell-cabal"
      ],
      "enabled": false
    },
    {
      "matchBaseBranches": [
        "/^v[0-9]+/"
      ],
      "groupName": "all dependencies"
    },
    {
      "matchManagers": [
        "haskell-cabal"
      ],
      "matchPackageNames": [
        "base",
        "bytestring",
        "containers",
        "directory",
        "mtl",
        "parsec",
        "process",
        "text"
      ],
      "groupName": "GHC dependencies"
    },
    {
      "matchManagers": [
        "haskell-cabal"
      ],
      "matchPackageNames": [
        "hasql",
        "hasql-dynamic-statements",
        "hasql-notifications",
        "hasql-transaction",
        "hasql-pool"
      ],
      "groupName": "hasql"
    },
    {
      "matchManagers": [
        "haskell-cabal"
      ],
      "matchPackageNames": [
        "fuzzyset"
      ],
      "allowedVersions": "<0.3"
    }
  ]
}


================================================
FILE: .github/workflows/backport.yaml
================================================
name: Backport

on:
  pull_request_target:
    types:
      - closed
      - labeled

jobs:
  backport:
    name: Backport
    runs-on: ubuntu-24.04
    # It triggers only when PR is already merged on either:
    #
    # - The merge event itself (action != labeled) or
    # - A label event with the right label (backport ...).
    #
    # The result will be that we can add the label before or after merge,
    # but the workflow will only run once the PR had been merged.
    if: >
      github.event.pull_request.merged &&
      (
        github.event.action != 'labeled' ||
        startsWith(github.event.label.name, 'backport')
      )
    steps:

      # This actions creates the github token using the postgrest app secrets
      - name: Create Github App Token
        id: app-token
        uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
        with:
          app-id: ${{ vars.POSTGREST_CI_APP_ID }}
          private-key: ${{ secrets.POSTGREST_CI_PRIVATE_KEY }}
          permission-contents: write
          permission-pull-requests: write
          permission-workflows: write # required when backporting CI changes

      # This is required for backport action to cherry-pick the PR
      - name: Fetch PR ref
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          token: ${{ steps.app-token.outputs.token }}

      # Backport action that creates the PR with given settings
      - name: Create backport PR
        uses: korthout/backport-action@4aaf0e03a94ff0a619c9a511b61aeb42adea5b02 # v4.2.0
        with:
          github_token: ${{ steps.app-token.outputs.token }}
          pull_description: 'Backport for #${pull_number}.'
          pull_title: '${target_branch}: ${pull_title}'


================================================
FILE: .github/workflows/build.yaml
================================================
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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 -A postgrestStatic.tests
      - name: Save built executable as artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: postgrest-docker-x86-64
          path: postgrest-docker.tar.gz
          if-no-files-found: error


  macos:
    name: Nix - MacOS
    runs-on: macos-15
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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 aarch64
            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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: haskell-actions/setup@f9150cb1d140e9a9271700670baa38991e6fa25c # v2.10.3
        with:
          # This must match the version in stack.yaml's resolver
          ghc-version: 9.6.7
          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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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.7', '9.8.4']
      fail-fast: false
    name: Cabal - Linux x86-64 - GHC ${{ matrix.ghc }}
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: haskell-actions/setup@f9150cb1d140e9a9271700670baa38991e6fa25c # v2.10.3
        with:
          ghc-version: ${{ matrix.ghc }}
      - name: Cache .cabal
        uses: ./.github/actions/cache-on-main
        with:
          path: |
            ~/.cabal/packages
            ~/.cabal/store
          prefix: cabal-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }}
          suffix: ${{ hashFiles('postgrest.cabal', 'cabal.project') }}
      - 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


================================================
FILE: .github/workflows/check.yaml
================================================
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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

  commit:
    if: github.event_name != 'push'  # we don't run this on a push, a failure on push disrupts the release workflow
    name: Commit
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 100  # fetch history (last 100 commits) instead of default shallow clone history, this is deemed enough for a PR history
      - name: Setup Nix Environment
        uses: ./.github/actions/setup-nix
        with:
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
          tools: gitTools.commitCheck.bin
      - name: Run commitlint (check locally with `nix-shell --run postgrest-commitlint`)
        run: |
          # Fetch target branch explicitly
          git fetch origin ${{ github.base_ref }}

          # Run commitlint
          postgrest-commitlint --from origin/${{ github.base_ref }} --to HEAD


================================================
FILE: .github/workflows/ci.yaml
================================================
name: CI

on:
  push:
    branches:
      - main
      - v[0-9]+

jobs:
  check:
    name: Check
    uses: ./.github/workflows/check.yaml
    secrets:
      CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}


  docs:
    name: Docs
    uses: ./.github/workflows/docs.yaml
    secrets:
      CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}


  test:
    name: Test
    uses: ./.github/workflows/test.yaml
    secrets:
      CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}


  build:
    name: Build
    uses: ./.github/workflows/build.yaml
    secrets:
      CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}


  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:
      - docs
      - test
      - build
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ssh-key: ${{ secrets.POSTGREST_SSH_KEY }}
      - name: Tag latest commit
        run: |
          cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"

          if [[ "$cabal_version" == *.* ]]; then
            git fetch --tags

            if [ -z "$(git tag --list "v$cabal_version")" ]; then
              git tag "v$cabal_version"
              git push origin "v$cabal_version"
            fi
          else
            git tag -f "devel"
            git push -f origin "devel"
          fi


================================================
FILE: .github/workflows/docs.yaml
================================================
name: Docs

on:
  workflow_call:
    secrets:
      CACHIX_AUTH_TOKEN:
        required: false
  pull_request:
    branches:
      - 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
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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: Spellcheck
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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


================================================
FILE: .github/workflows/linkcheck.yaml
================================================
name: Linkcheck

on:
  schedule:
    - cron: '1 2 * * 3'
  workflow_dispatch:

jobs:
  linkcheck:
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
    - name: Setup Nix Environment
      uses: ./.github/actions/setup-nix
      with:
        authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
        tools: docs.linkcheck.bin
    - run: postgrest-docs-linkcheck


================================================
FILE: .github/workflows/release.yaml
================================================
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Download all artifacts
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.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@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Download x86-64 Docker image
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          name: postgrest-docker-x86-64
      - name: Download aarch64 binary
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          name: postgrest-ubuntu-aarch64
      - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
      - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0
        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



================================================
FILE: .github/workflows/test.yaml
================================================
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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 cabalTools.update.bin

      - run: postgrest-cabal-update

      - name: Run coverage (IO tests and Spec tests against latest supported PostgreSQL)
        run: postgrest-coverage
      - name: Upload coverage to codecov
        uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3
        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: [13, 14, 15, 16, 17]
    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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Nix Environment
        uses: ./.github/actions/setup-nix
        with:
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
          tools: tests.testSpec.bin tests.testObservability.bin tests.testIO.bin tests.testBigSchema.bin withTools.pg-${{ matrix.pgVersion }}.bin cabalTools.update.bin

      - run: postgrest-cabal-update

      - name: Run spec tests
        if: always()
        run: postgrest-with-pg-${{ matrix.pgVersion }} postgrest-test-spec

      - name: Run observability tests
        if: always()
        run: postgrest-with-pg-${{ matrix.pgVersion }} postgrest-test-observability

      - name: Run IO tests
        if: always()
        run: postgrest-with-pg-${{ matrix.pgVersion }} postgrest-test-io -vv

      - name: Run IO tests on a big schema
        if: always()
        run: postgrest-with-pg-${{ matrix.pgVersion }} postgrest-test-big-schema -vv


  memory:
    name: Memory
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Nix Environment
        uses: ./.github/actions/setup-nix
        with:
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
          tools: tests.testMemory.bin cabalTools.update.bin

      - run: postgrest-cabal-update

      - name: Run memory tests
        run: postgrest-test-memory


  loadtest:
    strategy:
      matrix:
        kind: ['mixed', 'errors', 'jwt-hs', 'jwt-hs-cache', 'jwt-hs-cache-worst', 'jwt-rsa', 'jwt-rsa-cache', 'jwt-rsa-cache-worst']
    name: Loadtest
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.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 cabalTools.update.bin

      - run: postgrest-cabal-update

      - name: Run loadtest
        env:
          TARGET_BRANCH: ${{ github.base_ref || github.ref_name }}
        run: |
          if [ "$TARGET_BRANCH" = "main" ]; then
            latest_tag=$(git tag --sort=-creatordate --list "v*" | head -n1)
          else
            latest_tag=$(git tag --merged HEAD --sort=-creatordate "v*" | head -n1)
          fi
          postgrest-loadtest-against -k ${{ matrix.kind }} "$TARGET_BRANCH" "$latest_tag"
          postgrest-loadtest-report -g ${{ matrix.kind }} >> "$GITHUB_STEP_SUMMARY"

  flake:
    strategy:
      fail-fast: false
      matrix:
        runs-on:
          - macos-14 # aarch64-darwin
          - ubuntu-24.04 # x86_64-linux
          - ubuntu-24.04-arm # aarch64-linux
    name: Flake Check
    runs-on: ${{ matrix.runs-on }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
      - name: Setup Nix Environment
        uses: ./.github/actions/setup-nix
        with:
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
      - name: Run flake check
        run: |
          nix flake check


================================================
FILE: .gitignore
================================================
.DS_Store
db
dist
.cabal-sandbox
cabal.sandbox.config
hscope.out
codex.tags
.anvil
.stack-work*
tags
site
*~
*#*
.#*
*.swp
result*
dist-*
postgrest.hp
postgrest.prof
__pycache__
*.tix
coverage
.hpc
loadtest
.history
.docs-build
gen_targets.http
gen_jwk.json
gen_private.json


================================================
FILE: .readthedocs.yaml
================================================
version: 2
sphinx:
  configuration: docs/conf.py
python:
   install:
   - requirements: docs/requirements.txt
build:
  os: ubuntu-24.04
  tools:
    python: "3.11"


================================================
FILE: .stylish-haskell.yaml
================================================
# stylish-haskell configuration file
# ==================================

# The stylish-haskell tool is mainly configured by specifying steps. These steps
# are a list, so they have an order, and one specific step may appear more than
# once (if needed). Each file is processed by these steps in the given order.
steps:
  # Convert some ASCII sequences to their Unicode equivalents. This is disabled
  # by default.
  # - unicode_syntax:
  #     # In order to make this work, we also need to insert the UnicodeSyntax
  #     # language pragma. If this flag is set to true, we insert it when it's
  #     # not already present. You may want to disable it if you configure
  #     # language extensions using some other method than pragmas. Default:
  #     # true.
  #     add_language_pragma: true

  # Align the right hand side of some elements.  This is quite conservative
  # and only applies to statements where each element occupies a single
  # line.
  - simple_align:
      cases: true
      top_level_patterns: true
      records: true

  # Import cleanup
  - imports:
      # There are different ways we can align names and lists.
      #
      # - global: Align the import names and import list throughout the entire
      #   file.
      #
      # - file: Like global, but don't add padding when there are no qualified
      #   imports in the file.
      #
      # - group: Only align the imports per group (a group is formed by adjacent
      #   import lines).
      #
      # - none: Do not perform any alignment.
      #
      # Default: global.
      align: group

      # The following options affect only import list alignment.
      #
      # List align has following options:
      #
      # - after_alias: Import list is aligned with end of import including
      #   'as' and 'hiding' keywords.
      #
      #   > import qualified Data.List      as List (concat, foldl, foldr, head,
      #   >                                          init, last, length)
      #
      # - with_alias: Import list is aligned with start of alias or hiding.
      #
      #   > import qualified Data.List      as List (concat, foldl, foldr, head,
      #   >                                 init, last, length)
      #
      # - new_line: Import list starts always on new line.
      #
      #   > import qualified Data.List      as List
      #   >     (concat, foldl, foldr, head, init, last, length)
      #
      # Default: after_alias
      list_align: after_alias

      # Right-pad the module names to align imports in a group:
      #
      # - true: a little more readable
      #
      #   > import qualified Data.List       as List (concat, foldl, foldr,
      #   >                                           init, last, length)
      #   > import qualified Data.List.Extra as List (concat, foldl, foldr,
      #   >                                           init, last, length)
      #
      # - false: diff-safe
      #
      #   > import qualified Data.List as List (concat, foldl, foldr, init,
      #   >                                     last, length)
      #   > import qualified Data.List.Extra as List (concat, foldl, foldr,
      #   >                                           init, last, length)
      #
      # Default: true
      pad_module_names: true

      # Long list align style takes effect when import is too long. This is
      # determined by 'columns' setting.
      #
      # - inline: This option will put as much specs on same line as possible.
      #
      # - new_line: Import list will start on new line.
      #
      # - new_line_multiline: Import list will start on new line when it's
      #   short enough to fit to single line. Otherwise it'll be multiline.
      #
      # - multiline: One line per import list entry.
      #   Type with constructor list acts like single import.
      #
      #   > import qualified Data.Map as M
      #   >     ( empty
      #   >     , singleton
      #   >     , ...
      #   >     , delete
      #   >     )
      #
      # Default: inline
      long_list_align: inline

      # Align empty list (importing instances)
      #
      # Empty list align has following options
      #
      # - inherit: inherit list_align setting
      #
      # - right_after: () is right after the module name:
      #
      #   > import Vector.Instances ()
      #
      # Default: inherit
      empty_list_align: inherit

      # List padding determines indentation of import list on lines after import.
      # This option affects 'long_list_align'.
      #
      # - <integer>: constant value
      #
      # - module_name: align under start of module name.
      #   Useful for 'file' and 'group' align settings.
      list_padding: 4

      # Separate lists option affects formatting of import list for type
      # or class. The only difference is single space between type and list
      # of constructors, selectors and class functions.
      #
      # - true: There is single space between Foldable type and list of it's
      #   functions.
      #
      #   > import Data.Foldable (Foldable (fold, foldl, foldMap))
      #
      # - false: There is no space between Foldable type and list of it's
      #   functions.
      #
      #   > import Data.Foldable (Foldable(fold, foldl, foldMap))
      #
      # Default: true
      separate_lists: true

      # Space surround option affects formatting of import lists on a single
      # line. The only difference is single space after the initial
      # parenthesis and a single space before the terminal parenthesis.
      #
      # - true: There is single space associated with the enclosing
      #   parenthesis.
      #
      #   > import Data.Foo ( foo )
      #
      # - false: There is no space associated with the enclosing parenthesis
      #
      #   > import Data.Foo (foo)
      #
      # Default: false
      space_surround: false

  # Language pragmas
  - language_pragmas:
      # We can generate different styles of language pragma lists.
      #
      # - vertical: Vertical-spaced language pragmas, one per line.
      #
      # - compact: A more compact style.
      #
      # - compact_line: Similar to compact, but wrap each line with
      #   `{-#LANGUAGE #-}'.
      #
      # Default: vertical.
      style: vertical

      # Align affects alignment of closing pragma brackets.
      #
      # - true: Brackets are aligned in same column.
      #
      # - false: Brackets are not aligned together. There is only one space
      #   between actual import and closing bracket.
      #
      # Default: true
      align: true

      # stylish-haskell can detect redundancy of some language pragmas. If this
      # is set to true, it will remove those redundant pragmas. Default: true.
      remove_redundant: true

  # Replace tabs by spaces. This is disabled by default.
  # - tabs:
  #     # Number of spaces to use for each tab. Default: 8, as specified by the
  #     # Haskell report.
  #     spaces: 8

  # Remove trailing whitespace
  - trailing_whitespace: {}

# A common setting is the number of columns (parts of) code will be wrapped
# to. Different steps take this into account. Default: 80.
columns: 70

# By default, line endings are converted according to the OS. You can override
# preferred format here.
#
# - native: Native newline format. CRLF on Windows, LF on other OSes.
#
# - lf: Convert to LF ("\n").
#
# - crlf: Convert to CRLF ("\r\n").
#
# Default: native.
newline: native

# Sometimes, language extensions are specified in a cabal file or from the
# command line instead of using language pragmas in the file. stylish-haskell
# needs to be aware of these, so it can parse the file correctly.
#
# No language extensions are enabled by default.
language_extensions:
  - TemplateHaskell
  - QuasiQuotes
  - CPP


================================================
FILE: BACKERS.md
================================================
# Sponsors & Backers

PostgREST ongoing development is only possible thanks to our Sponsors and Backers, listed below. If you'd like to join them, you can do so by supporting the PostgREST organization on [Patreon](https://www.patreon.com/postgrest).

## Sponsors

<table align="center">
  <tbody>
    <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.svg">
        </a>
      </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="static/supabase.svg">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.euronodes.com/postgrest" target="_blank">
          <img width="296px" src="static/euronodes.svg">
        </a>
      </td>
    </tr>
    <tr></tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://neon.tech/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="296px" src="static/neon.jpg">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.bytebase.com/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="296px" src="static/bytebase.svg">
        </a>
      </td>
    </tr>
  </tbody>
</table>

## Lead Backers

- [Roboflow](https://github.com/roboflow)
- Evans Fernandes
- [Jan Sommer](https://github.com/nerfpops)
- [Franz Gusenbauer](https://www.igutech.at/)

## Backers

- Zac Miller
- Tsingson Qin
- Michel Pelletier
- Jay Hannah
- Robert Stolarz
- Nicholas DiBiase
- Christopher Reid
- Nathan Bouscal
- Daniel Rafaj
- David Fenko
- Remo Rechkemmer
- Severin Ibarluzea
- Tom Saleeba
- Pawel Tyll

## Former Backers

<table>
  <tbody>
    <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="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="static/retool.png">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.2ndquadrant.com/en/?utm_campaign=External%20Websites&utm_source=PostgREST&utm_medium=Logo" target="_blank">
          <img width="222px" src="static/2ndquadrant.png">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://oblivious.ai/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="222px" src="static/oblivious.jpg">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://code.build/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="222px" src="static/code-build.png">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://tembo.io/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="296px" src="static/tembo.png">
        </a>
      </td>
    </tr>
  </tbody>
</table>

- [Christiaan Westerbeek](https://devotis.nl)
- [Daniel Babiak](https://github.com/dbabiak)
- Kofi Gumbs


================================================
FILE: CHANGELOG.md
================================================
# Change Log

All notable changes to this project will be documented in this file. From version `14.0` onwards PostgREST follows a `MAJOR.PATCH` two-part versioning. Only even-numbered MAJOR versions will be released, reserving odd-numbered MAJOR versions for development.

## Unreleased

### Added

- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
- Add a `HINT` when the LISTEN channel stops working due to a PostgreSQL bug by @laurenceisla in #4581
- Add string slicing operator for `jwt-role-claim-key` by @taimoorzaeem in #4599
- Log host, port and pg version of listener database connection by @mkleczek in #4617 #4618
- Optimize requests with `Prefer: count=exact` that do not use ranges or `db-max-rows` by @laurenceisla in #3957
  + Removed unnecessary double count when building the `Content-Range`.
- Add config `client_error_verbosity` to customize error verbosity by @taimoorzaeem in #4088, #3980, #3824
- Add `Vary` header to responses by @develop7 in #4609

### Changed

- All responses now include a `Vary` header by @develop7 in #4609

- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
  + Now fails at startup. Prior to this, it failed with `PGRST205` on requests related to these schemas.

## [14.6] - 2026-03-06

### Fixed

- Fix leaking table and function names when calculating error hint by @taimoorzaeem in #4675

## [14.5] - 2026-02-12

### Fixed

- Don't hide async exceptions in logs by @stevechavez in #4646

## [14.4] - 2026-01-29

### Fixed

- Ensure Listener connections are released by @mkleczek in #4614
- Fix incorrectly filtering the returned representation for PATCH requests when using `or/and` filters by @laurenceisla in #3707
- Fix listener running with exception masked after first failure by @mkleczek in #4615

## [14.3] - 2026-01-03

### Fixed

- Fix performance and high memory usage of relation hint calculation by @mkleczek in #4462, #4463

## [14.2] - 2025-12-18

### Fixed

- Fix `hasSingleUnnamedParam` incorrectly matching functions with named parameters by @joelonsql in #4553
  + Functions with a single named parameter (e.g., `foo(data json)`) no longer incorrectly match the single-param fallback, returning a clean `PGRST202` error instead of a confusing PostgreSQL `42883` error.
- Fix misleading logs on unsupported PostgreSQL versions by @taimoorzaeem in #4519
- Fix regression where the `PGRST103` error response was truncated by @laurenceisla in #4455
  + Happened when an `offset` was greater than the rows requested and `Prefer: count=exact` was sent.
- Fix not returning `Content-Length` on empty HTTP `201` responses by @laurenceisla in #4518
- Fix inaccurate Server-Timing header durations by @steve-chavez in #4522
- Fix inaccurate "Schema cache queried" logs by @steve-chavez in #4522

## [14.1] - 2025-11-05

## Fixed

- Fix `db-pre-config` function failing when function names are pg reserved words by @taimoorzaeem in #4380
- Fix `server-host=!6` incorrectly binds to IPv4 address by @taimoorzaeem in #3202

## [14.0] - 2025-10-24

### Added

- Bounded JWT cache using the SIEVE algorithm by @mkleczek in #4084
  + It now uses a fixed size cache instead of arbitrary sized cache.
- Add `--ready` flag for postgrest healthcheck by @taimoorzaeem in #4239

### Fixed

- Fix not logging OpenAPI queries when `log-query=main-query` is enabled by @steve-chavez in #4226
- Fix not logging explain query when `log-query=main-query` is enabled by @steve-chavez in #4319
- Fix not logging transaction variables and db-pre-request function when `log-query=main-query` is enabled by @steve-chavez in #3934
- Fix not logging the JSON message to stderr on a `PGRST002` error by @laurenceisla in #4129
- Fix reloading the Schema Cache unnecessarily on a `PGRST002` error by @laurenceisla in #4367
- Fix schema cache loading taking a long time for large schemas by @mkleczek in #4360, #3704

### Changed

- Drop support for PostgreSQL EOL version 12 by @wolfgangwalther in #3865
- From now on PostgREST will follow a `MAJOR.PATCH` two-part versioning. Only even-numbered MAJOR versions will be released, reserving odd-numbered MAJOR versions for development.
- Replaced `jwt-cache-max-lifetime` config with `jwt-cache-max-entries` by @mkleczek in #4084
- `log-query` config now takes a boolean instead of a string value by @steve-chavez in #3934

## [13.0.8] - 2025-10-24

### Fixed

- Fix loading utf-8 config files with `ASCII` locale set by @taimoorzaeem in #4386

## [13.0.7] - 2025-09-14

### Added

- Improve the `PGRST106` error when the requested schema is invalid by @laurenceisla in #4089
  + It now shows the invalid schema in the `message` field.
  + The exposed schemas are now listed in the `hint` instead of the `message` field.
- Improve error details of `PGRST301` error by @taimoorzaeem in #4051

## [13.0.6] - 2025-08-30

### Fixed

- Fix logging the Haskell type instead of the listener error message directly by @laurenceisla in #3588
- Fix format of `IPv6` address logged at PostgREST startup by @taimoorzaeem in #4291
- Fix empty enum in `preferParams` OpenAPI parameter by @laurenceisla in #4292

## [13.0.5] - 2025-08-24

### Fixed

- Fix OpenAPI broken docs link by @taimoorzaeem in #4080
- Fix OpenAPI specification incorrectly exposing GET methods for volatile functions by @joelonsql in #4174
- Fix empty spread embeddings return unexpected SQL error by @taimoorzaeem in #3887
- Fix `/metrics` endpoint not responding with `Content-Type` header by @taimoorzaeem in #4271

## [13.0.4] - 2025-06-17

### Fixed

- Fix regression that makes full-text search not work on domain types based on `tsvector` by @laurenceisla in #4135
- Fix `jwt-aud` config not failing when set to an invalid URI by @taimoorzaeem in #4132

## [13.0.3] - 2025-06-16

- Fix `max-affected` preference not failing with RPC when `handling=strict` by @taimoorzaeem in #4100
- Fix a property definition's type in OpenAPI not showing the correct base type of a recursive domain by @laurenceisla in #4136

### Fixed

## [13.0.2] - 2025-06-02

### Fixed

- Fix regression that makes `ORDER BY` with nulls-order not work alongside limits by @laurenceisla in #4109

## [13.0.1] - 2025-06-01

### Fixed

- Fix jwt error returning HTTP status `400` for invalid role by @taimoorzaeem in #3601
- Fix `db-extra-search-path` cannot be set to nothing by @taimoorzaeem in #4074
  + It can now be disabled by setting it to empty string.
  + Schema Cache load error is now logged including `db-schemas` and `db-extra-search-path` config values.

## [13.0.0] - 2025-05-08

### Added

 - #3558, Add the `admin-server-host` config to set the host for the admin server - @develop7
 - #3607, Log to stderr when the JWT secret is less than 32 characters long - @laurenceisla
 - #2858, Performance improvements when calling RPCs via GET using indexes in more cases - @wolfgangwalther
 - #3560, Log resolved host in "Listening on ..." messages - @develop7
 - #3727, Log maximum pool size - @steve-chavez
 - #1536, Add string comparison feature for jwt-role-claim-key - @taimoorzaeem
 - #3747, Allow `not_null` value for the `is` operator - @taimoorzaeem
 - #2255, Apply `to_tsvector()` explicitly to the full-text search filtered column (excluding `tsvector` types) - @laurenceisla
 - #1578, Log the main SQL query to stderr at the current `log-level` when `log-query=main-query` - @laurenceisla
 - #3903, Log connection pool borrows on `log-level=debug` - @taimoorzaeem
 - #3041, Allow spreading one-to-many and many-to-many embedded resources - @laurenceisla
   + The selected columns in the embedded resources are aggregated into arrays
   + Aggregates are not supported
 - #2967, Add `Proxy-Status` header for better error response - @taimoorzaeem
 - #4016, Add `Content-Length` response header - @laurenceisla

### Fixed

 - #3693, Prevent spread embedding to allow aggregates when they are disabled - @laurenceisla
 - #3693, A nested spread embedding now correctly groups by the fields of its top parent relationship - @laurenceisla
 - #3693, Fix spread embedding errors when using the `count()` aggregate without a field - @laurenceisla
   + Fixed `"column reference <col> is ambiguous"` error when selecting `?select=...table(col,count())`
   + Fixed `"column <json_aggregate>.<alias> does not exist"` error when selecting `?select=...table(aias:count())`
 - #3727, Clarify "listening" logs - @steve-chavez
 - #3795, Clarify `Accept: vnd.pgrst.object` error message - @steve-chavez
 - #3697, #3602, Handle queries on non-existing table gracefully - @taimoorzaeem
 - #3600, #3926, Improve JWT errors - @taimoorzaeem
 - #3013, Fix `order=` with POST, PATCH, PUT and DELETE requests - @taimoorzaeem
 - #3965, Fix filter on unselected columns in a table-valued function - @taimoorzaeem
 - #4052, Fix schema cache load duplicate objects with different object type but same oid - @taimoorzaeem

### Changed

 - #2052, Dropped support for PostgreSQL 9.6 - @wolfgangwalther
 - #2052, Dropped support for PostgreSQL 10 - @wolfgangwalther
 - #2052, Dropped support for PostgreSQL 11 - @wolfgangwalther
 - #3508, PostgREST now fails to start when `server-port` and `admin-server-port` config options are the same - @develop7
 - #3607, PostgREST now fails to start when the JWT secret is less than 32 characters long - @laurenceisla
 - #3644, Fail schema cache lookup with invalid `db-schemas` or `db-extra-search-path` config - @wolfgangwalther
   - Previously, this would silently return 200 - OK on the root endpoint, but don't provide any usable endpoints.
   - Note: This also applies when deleting the `public` schema - both config options default to that.
 - #3757, Remove support for `Prefer: params=single-object` - @joelonsql
   + This preference was deprecated in favor of Functions with an array of JSON objects
 - #3013, Drop support for Limited updates/deletes
   + The feature was complicated and largely unused.
 - #3956, Drop `/config` endpoint of admin server - @steve-chavez
   + The endpoint was at risk of being left unprotected when exposing it.
   + The accompanying `admin-server-config-enabled` config was also dropped.
 - #3598, PostgREST now validates the `kid` parameter of the JWT - @wolfgangwalther
   + If the JWT contains a ``kid`` parameter, then PostgREST will look for the JSON Web Key in the `jwt-secret`.
   + If the JWT doesn't contain a `kid`, the behavior should be backwards compatible. PostgREST  will try each key in the `jwt-secret` one by one until it finds one that works.
 - #3697, #3602, Querying non-existent table now returns `PGRST205` error instead of empty json - @taimoorzaeem
 - #3600, #3926, Improve JWT errors - @taimoorzaeem
   + Return `PGRST301` error when `Bearer` in auth header is sent empty
   + Diagnostic error messages instead of exposed internals
   + Return new `PGRST303` error when jwt claims decoding fails
 - #3906, Return `PGRST125` and `PGRST126` errors instead of empty json - @taimoorzaeem

## [12.2.12] - 2025-05-01

### Fixed

- #3956, Fix exposing admin server `/config` by default - @steve-chavez
  + The above endpoint is now disabled unless the `admin-server-config-enabled` config is set to `true`

## [12.2.11] - 2025-04-22

### 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

 - #3149, Misleading "Starting PostgREST.." logs on schema cache reloading - @steve-chavez
 - #3205, Fix wrong subquery error returning a status of 400 Bad Request - @steve-chavez
 - #3224, Return status code 406 for non-accepted media type instead of code 415 - @wolfgangwalther
 - #3160, Fix using select= query parameter for custom media type handlers - @wolfgangwalther
 - #3361, Clarify PGRST204(column not found) error message - @steve-chavez
 - #3373, Remove rejected mediatype `application/vnd.pgrst.object+json` from response - @taimoorzaeem
 - #3418, Fix OpenAPI not tagging a FK column correctly on O2O relationships - @laurenceisla
 - #3256, Fix wrong http status for pg error `42P17 infinite recursion` - @taimoorzaeem

## [12.0.2] - 2023-12-20

### Fixed

  - #3124, Fix table's media type handlers not working for all schemas - @steve-chavez
  - #3126, Fix empty row on media type handler function - @steve-chavez

## [12.0.1] - 2023-12-12

### Fixed

 - #3054, Fix not allowing special characters in JSON keys - @laurenceisla
 - #2344, Replace JSON parser error with a clearer generic message - @develop7
 - #3100, Add missing in-database configuration option for `jwt-cache-max-lifetime` - @laurenceisla
 - #3089, The any media type handler now sets `Content-Type: application/octet-stream` by default instead of `Content-Type: application/json` - @steve-chavez

## [12.0.0] - 2023-12-01

### Added

 - #1614, Add `db-pool-automatic-recovery` configuration to disable connection retrying - @taimoorzaeem
 - #2492, Allow full response control when raising exceptions - @taimoorzaeem, @laurenceisla
 - #2771, #2983, #3062, #3055 Add `Server-Timing` response header - @taimoorzaeem, @develop7, @laurenceisla
 - #2698, Add config `jwt-cache-max-lifetime` and implement JWT caching - @taimoorzaeem
 - #2943, Add `handling=strict/lenient` for Prefer header - @taimoorzaeem
 - #2441, Add config `server-cors-allowed-origins` to specify CORS origins - @taimoorzaeem
 - #2825, SQL handlers for custom media types - @steve-chavez
   + Solves #1548, #2699, #2763, #2170, #1462, #1102, #1374, #2901
 - #2799, Add timezone in Prefer header - @taimoorzaeem
 - #3001, Add `statement_timeout` set on functions - @taimoorzaeem
 - #3045, Apply superuser settings on impersonated roles if they have PostgreSQL 15 `GRANT SET ON PARAMETER` privilege - @steve-chavez
 - #915, Add support for aggregate functions - @timabdulla
    + The aggregate functions SUM(), MAX(), MIN(), AVG(), and COUNT() are now supported.
    + It's disabled by default, you can enable it with `db-aggregates-enabled`.
 - #3057, Log all internal database errors to stderr - @laurenceisla

### Fixed

 - #3015, Fix unnecessary count() on RPC returning single - @steve-chavez
 - #1070, Fix HTTP status responses for upserts - @taimoorzaeem
   + `PUT` returns `201` instead of `200` when rows are inserted
   + `POST` with `Prefer: resolution=merge-duplicates` returns `200` instead of `201` when no rows are inserted
 - #3019, Transaction-Scoped Settings are now shown clearly in the Postgres logs - @laurenceisla
   + Shows `set_config('pgrst.setting_name', $1)` instead of `setconfig($1, $2)`
   + Does not apply to role settings and `app.settings.*`
 - #2420, Fix bogus message when listening on port 0 - @develop7
 - #3067, Fix Acquision Timeout errors logging to stderr when `log-level=crit` - @laurenceisla

### Changed

 - Removed [raw-media-types config](https://postgrest.org/en/v11.1/references/configuration.html#raw-media-types) - @steve-chavez
 - 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

### Fixed

 - #2824, Fix regression by reverting fix that returned 206 when first position = length in a `Range` header - @laurenceisla, @strengthless

## [11.2.1] - 2023-10-03

### Fixed

 - #2899, Fix `application/vnd.pgrst.array` not accepted as a valid mediatype - @taimoorzaeem
 - #2524, Fix schema cache and configuration reloading with `NOTIFY` not working on Windows - @diogob, @laurenceisla
 - #2915, Fix duplicate headers in response - @taimoorzaeem
 - #2824, Fix range request with first position same as length return status 206 - @taimoorzaeem
 - #2939, Fix wrong `Preference-Applied` with `Prefer: tx=commit` when transaction is rollbacked - @steve-chavez
 - #2939, Fix `count=exact` not being included in `Preference-Applied` - @steve-chavez
 - #2800, Fix not including to-one embed resources that had a `NULL` value in any of the selected fields when doing null filtering on them - @laurenceisla
 - #2846, Fix error when requesting `Prefer: count=<type>` and doing null filtering on embedded resources - @laurenceisla
 - #2959, Fix setting `default_transaction_isolation` unnecessarily - @steve-chavez
 - #2929, Fix arrow filtering on RPC returning dynamic TABLE with composite type - @steve-chavez
 - #2963, Fix RPCs not embedding correctly when using overloaded functions for computed relationships - @laurenceisla
 - #2970, Fix regression that rejects URI connection strings with certain unescaped characters in the password - @laurenceisla, @steve-chavez

## [11.2.0] - 2023-08-10

### Added

 - #2523, Data representations - @aljungberg
   + Allows for flexible API output formatting and input parsing on a per-column type basis using regular SQL functions configured in the database
   + Enables greater flexibility in the form and shape of your APIs, both for output and input, making PostgREST a more versatile general-purpose API server
   + Examples include base64 encode/decode your binary data (like a `bytea` column containing an image), choose whether to present a timestamp column as seconds since the Unix epoch or as an ISO 8601 string, or represent fixed precision decimals as strings, not doubles, to preserve precision
   + ...and accept the same in `POST/PUT/PATCH` by configuring the reverse transformation(s)
   + Other use-cases include custom representation of enums, arrays, nested objects, CSS hex colour strings, gzip compressed fields, metric to imperial conversions, and much more
   + Works when using the `select` parameter to select only a subset of columns, embedding through complex joins, renaming fields, with views and computed columns
   + Works when filtering on a formatted column without extra indexes by parsing to the canonical representation
   + Works for data `RETURNING` operations, such as requesting the full body in a POST/PUT/PATCH with `Prefer: return=representation`
   + Works for batch updates and inserts
   + Completely optional, define the functions in the database and they will be used automatically everywhere
   + Data representations preserve the ability to write to the original column and require no extra storage or complex triggers (compared to using `GENERATED ALWAYS` columns)
   + Note: data representations require Postgres 10 (Postgres 11 if using `IN` predicates); data representations are not implemented for RPC
 - #2647, Allow to verify the PostgREST version in SQL: `select distinct application_name from pg_stat_activity`. - @laurenceisla
 - #2856, Add the `--version` CLI option that prints the version information - @laurenceisla
 - #1655, Improve `details` field of the singular error response - @taimoorzaeem
 - #740, Add `Preference-Applied` in response for `Prefer: return=representation/headers-only/minimal` - @taimoorzaeem
 - #1601, Add optional `nulls=stripped` parameter for mediatypes `application/vnd.pgrst.array+json` and `application/vnd.pgrst.object+json` - @taimoorzaeem

### Fixed

 - #2821, Fix OPTIONS not accepting all available media types - @steve-chavez
 - #2834, Fix compilation on Ubuntu by being compatible with GHC 9.0.2 - @steve-chavez
 - #2840, Fix `Prefer: missing=default` with DOMAIN default values - @steve-chavez
 - #2849, Fix HEAD unnecessarily executing aggregates - @steve-chavez
 - #2594, Fix unused index on jsonb/jsonb arrow filter and order (``/bets?data->>contractId=eq.1`` and ``/bets?order=data->>contractId``) - @steve-chavez
 - #2861, Fix character and bit columns with fixed length not inserting/updating properly - @laurenceisla
   + Fixes the error "value too long for type character(1)" when the char length of the column was bigger than one.
 - #2862, Fix null filtering on embedded resource when using a column name equal to the relation name - @steve-chavez
 - #1586, Fix function parameters of type character and bit not ignoring length - @laurenceisla
   + Fixes the error "value too long for type character(1)" when the char length of the parameter was bigger than one.
 - #2881, Fix error when a function returns `RECORD` or `SET OF RECORD` - @laurenceisla
 - #2896, Fix applying superuser settings for impersonated role - @steve-chavez

### Deprecated

 - #2863, Deprecate resource embedding target disambiguation - @steve-chavez
   + The `/table?select=*,other!fk(*)` must be used to disambiguate
   + The server aids in choosing the `!fk` by sending a `hint` on the error whenever an ambiguous request happens.

## [11.1.0] - 2023-06-07

### Added

 - #2786, Limit idle postgresql connection lifetime - @robx
   + New option `db-pool-max-idletime` (default 30s).
   + This is equivalent to the old option `db-pool-timeout` of PostgREST 10.0.0.
   + A config alias for `db-pool-timeout` is included.
 - #2703, Add pre-config function - @steve-chavez
    + New config option `db-pre-config`(empty by default)
    + Allows using the in-database configuration without SUPERUSER
 - #2781, When `db-channel-enabled` is false, start automatic connection recovery on a new request when pool connections are closed with `pg_terminate_backend` - @steve-chavez
    + Mitigates the lack of LISTEN/NOTIFY for schema cache reloading on read replicas.

### Fixed

 - #2791, Fix dropping schema cache reload notifications  - @steve-chavez
 - #2801, Stop retrying connection when "no password supplied" - @steve-chavez

## [11.0.1] - 2023-04-27

### Fixed

 - #2762, Fixes "permission denied for schema" error during schema cache load - @steve-chavez
 - #2756, Fix bad error message on generated columns when using `Prefer: missing=default` - @steve-chavez
 - #1139, Allow a 30 second skew for JWT validation - @steve-chavez
   + It used to be 1 second, which was too strict

## [11.0.0] - 2023-04-16

### Added

 - #1414, Add related orders - @steve-chavez
   + On a many-to-one or one-to-one relationship, you can order a parent by a child column `/projects?select=*,clients(*)&order=clients(name).desc.nullsfirst`
 - #1233, #1907, #2566, Allow spreading embedded resources - @steve-chavez
   + On a many-to-one or one-to-one relationship, you can unnest a json object with `/projects?select=*,...clients(client_name:name)`
   + Allows including the join table columns when resource embedding
   + Allows disambiguating a recursive m2m embed
   + Allows disambiguating an embed that has a many-to-many relationship using two foreign keys on a junction
 - #2340, Allow embedding without selecting any column - @steve-chavez
 - #2563, Allow `is.null` or `not.is.null` on an embedded resource - @steve-chavez
   + Offers a more flexible replacement for `!inner`, e.g. `/projects?select=*,clients(*)&clients=not.is.null`
   + Allows doing an anti join, e.g. `/projects?select=*,clients(*)&clients=is.null`
   + Allows using or across related tables conditions
 - #1100, Customizable OpenAPI title - @AnthonyFisi
 - #2506, Add `server-trace-header` for tracing HTTP requests.  - @steve-chavez
   + When the client sends the request header specified in the config it will be included in the response headers.
 - #2694, Make `db-root-spec` stable. - @steve-chavez
   + This can be used to override the OpenAPI spec with a custom database function
 - #1567, On bulk inserts, missing values can get the column DEFAULT by using the `Prefer: missing=default` header - @steve-chavez
 - #2501, Allow filtering by`IS DISTINCT FROM` using the `isdistinct` operator, e.g. `/people?alias=isdistinct.foo`
 - #1569, Allow `any/all` modifiers on the `eq,like,ilike,gt,gte,lt,lte,match,imatch` operators, e.g. `/tbl?id=eq(any).{1,2,3}` - @steve-chavez
   - This converts the input into an array type
 - #2561, Configurable role settings - @steve-chavez
   - Database roles that are members of the connection role get their settings applied, e.g. doing
     `ALTER ROLE anon SET statement_timeout TO '5s'` will result in that `statement_timeout` getting applied for that role.
   - Works when switching roles when a JWT is sent
   - Settings can be reloaded with `NOTIFY pgrst, 'reload config'`.
 - #2468, Configurable transaction isolation level with `default_transaction_isolation` - @steve-chavez
   - Can be set per function `create function .. set default_transaction_isolation = 'repeatable read'`
   - Or per role `alter role .. set default_transaction_isolation = 'serializable'`

### Fixed

 - #2651, Add the missing `get` path item for RPCs to the OpenAPI output - @laurenceisla
 - #2648, Fix inaccurate error codes with new ones - @laurenceisla
   + `PGRST204`: Column is not found
   + `PGRST003`: Timed out when acquiring connection to db
 - #1652, Fix function call with arguments not inlining - @steve-chavez
 - #2705, Fix bug when using the `Range` header on `PATCH/DELETE` - @laurenceisla
   + Fix the`"message": "syntax error at or near \"RETURNING\""` error
   + Fix doing a limited update/delete when an `order` query parameter was present
 - #2742, Fix db settings and pg version queries not getting prepared  - @steve-chavez
 - #2618, Fix `PATCH` requests not recognizing embedded filters and using the top-level resource instead - @steve-chavez

### Changed

 - #2705, The `Range` header is now only considered on `GET` requests and is ignored for any other method - @laurenceisla
   + Other methods should use the `limit/offset` query parameters for sub-ranges
   + `PUT` requests no longer return an error when this header is present (using `limit/offset` still triggers the error)
 - #2733, Remove bulk RPC call with the `Prefer: params=multiple-objects` header. A function with a JSON array or object parameter should be used instead.

## [10.2.0] - 2023-04-12

### Added

 - #2663, Limit maximal postgresql connection lifetime - @robx
   + New option `db-pool-max-lifetime` (default 30m)
   + `db-pool-acquisition-timeout` is no longer optional and defaults to 10s
   + Fixes postgresql resource leak with long-lived connections (#2638)

### Fixed

 - #2667, Fix `db-pool-acquisition-timeout` not logging to stderr when the timeout is reached - @steve-chavez

## [10.1.2] - 2023-02-01

### Fixed

 - #2565, Fix bad M2M embedding on RPC - @steve-chavez
 - #2575, Replace misleading error message when no function is found with a hint containing functions/parameters names suggestions - @laurenceisla
 - #2582, Move explanation about "single parameters" from the `message` to the `details` in the error output - @laurenceisla
 - #2569, Replace misleading error message when no relationship is found with a hint containing parent/child names suggestions - @laurenceisla
 - #1405, Add the required OpenAPI items object when the parameter is an array - @laurenceisla
 - #2592, Add upsert headers for POST requests to the OpenAPI output - @laurenceisla
 - #2623, Fix FK pointing to VIEW instead of TABLE in OpenAPI output - @laurenceisla
 - #2622, Consider any PostgreSQL authentication failure as fatal and exit immediately - @michivi
 - #2620, Fix `NOTIFY pgrst` not reloading the db connections catalog cache - @steve-chavez

## [10.1.1] - 2022-11-08

### Fixed

 - #2548, Fix regression when embedding views with partial references to multi column FKs - @wolfgangwalther
 - #2558, Fix regression when requesting limit=0 and `db-max-row` is set - @laurenceisla
 - #2542, Return a clear error without hitting the database when trying to update or insert an unknown column with `?columns` - @aljungberg

## [10.1.0] - 2022-10-28

### Added

 - #2348, Add `db-pool-acquisition-timeout` configuration option, time in seconds to wait to acquire a connection. - @robx

### Fixed

 - #2261, #2349, #2467, Reduce allocations communication with PostgreSQL, particularly for request bodies. - @robx
 - #2401, #2444, Fix SIGUSR1 to fully flush connections pool. - @robx
 - #2428, Fix opening an empty transaction on failed resource embedding - @steve-chavez
 - #2455, Fix embedding the same table multiple times - @steve-chavez
 - #2518, Fix a regression when embedding views where base tables have a different column order for FK columns - @wolfgangwalther
 - #2458, Fix a regression with the location header when inserting into views with PKs from multiple tables - @wolfgangwalther
 - #2356, Fix a regression in openapi output with mode follow-privileges - @wolfgangwalther
 - #2283, Fix infinite recursion when loading schema cache with self-referencing view - @wolfgangwalther
 - #2343, Return status code 200 for PATCH requests which don't affect any rows - @wolfgangwalther
 - #2481, Treat computed relationships not marked SETOF as M2O/O2O relationship - @wolfgangwalther
 - #2534, Fix embedding a computed relationship with a normal relationship - @steve-chavez
 - #2362, Fix error message when [] is used inside select - @wolfgangwalther
 - #2475, Disallow !inner on computed columns - @wolfgangwalther
 - #2285, Ignore leading and trailing spaces in column names when parsing the query string - @wolfgangwalther
 - #2545, Fix UPSERT with PostgreSQL 15 - @wolfgangwalther
 - #2459, Fix embedding views with multiple references to the same base column - @wolfgangwalther

### Changed

 - #2444, Removed `db-pool-timeout` option, because this was removed upstream in hasql-pool. - @robx
 - #2343, PATCH requests that don't affect any rows no longer return 404 - @wolfgangwalther
 - #2537, Stricter parsing of query string. Instead of silently ignoring, the parser now throws on invalid syntax like json paths for embeddings, hints for regular columns, empty casts or fts languages, etc. - @wolfgangwalther

### Deprecated

 - #1385, Deprecate bulk-calls when including the `Prefer: params=multiple-objects` in the request. A function with a JSON array or object parameter should be used instead for a better performance.

## [10.0.0] - 2022-08-18

### Added

 - #1933, #2109, Add a minimal health check endpoint - @steve-chavez
   + For enabling this, the `admin-server-port` config must be set explicitly
   + A `<host>:<admin_server_port>/live` endpoint is available for checking if postgrest is running on its port/socket. 200 OK = alive, 503 = dead.
   + A `<host>:<admin_server_port>/ready` endpoint is available for checking a correct internal state(the database connection plus the schema cache). 200 OK = ready, 503 = not ready.
 - #1988, Add the current user to the request log on stdout - @DavidLindbom, @wolfgangwalther
 - #1823, Add the ability to run postgrest without any configuration. - @wolfgangwalther
   + #1991, Add the ability to run without `db-uri` using libpq's PG environment variables to connect. - @wolfgangwalther
   + #1769, Add the ability to run without `db-schemas`, defaulting to `db-schemas=public`. - @wolfgangwalther
   + #1689, Add the ability to run without `db-anon-role` disabling anonymous access. - @wolfgangwalther
 - #1543, Allow access to fields of composite types in select=, order= and filters through JSON operators -> and ->>. - @wolfgangwalther
 - #2075, Allow access to array items in ?select=, ?order= and filters through JSON operators -> and ->>. - @wolfgangwalther
 - #2156, #2211, Allow applying `limit/offset` to UPDATE/DELETE to only affect a subset of rows - @steve-chavez
   + It requires an explicit `order` on a unique column(s)
 - #1917, Add error codes with the `"PGRST"` prefix to the error response body to differentiate PostgREST errors from PostgreSQL errors - @laurenceisla
 - #1917, Normalize the error response body by always having the `detail` and `hint` error fields with a `null` value if they are empty - @laurenceisla
 - #2176, Errors raised with `SQLSTATE` now include the message and the code in the response body - @laurenceisla
 - #2236, Support POSIX regular expression operators for row filtering - @enote-kane
 - #2202, Allow returning XML from RPCs - @fjf2002
 - #2268, Allow returning XML from single-column queries - @fjf2002
 - #2300, RPC POST for function w/single unnamed XML param #2300 - @fjf2002
 - #1564, Allow geojson output by specifying the `Accept: application/geo+json` media type - @steve-chavez
   + Requires postgis >= 3.0
   + Works for GET, RPC, POST/PATCH/DELETE with `Prefer: return=representation`.
   + Resource embedding works and the embedded rows will go into the `properties` key
   + In case of multiple geometries in the same table, you can choose which one will go into the `geometry` key with the usual `?select` query parameter.
 - #1082, Add security definitions to the OpenAPI output - @laurenceisla
 - #2378, Support http OPTIONS method on RPC and root path - @steve-chavez
 - #2354, Allow getting the EXPLAIN plan of a request by using the `Accept: application/vnd.pgrst.plan` header - @steve-chavez
   + Only allowed if the `db-plan-enabled` config is set to true
   + Can generate the plan for different media types using the `for` parameter: `Accept: application/vnd.pgrst.plan; for="application/vnd.pgrst.object"`
   + Different options for the plan can be used with the `options` parameter: `Accept: application/vnd.pgrst.plan; options=analyze|verbose|settings|buffers|wal`
   + The plan can be obtained in text or json by using different media type suffixes: `Accept: application/vnd.pgrst.plan+text` and `Accept: application/vnd.pgrst.plan+json`.
 - #2144, Support computed relationships which allow extending and overriding relationships for resource embedding - @steve-chavez, @wolfgangwalther
 - #1984, Detect one-to-one relationships for resource embedding - @steve-chavez
   + Detected when there's a foreign key with a unique constraint or when a foreign key is also a primary key

### Fixed

 - #2058, Return 204 No Content without Content-Type for PUT - @wolfgangwalther
 - #2107, Clarify error for failed schema cache load. - @steve-chavez
   + From `Database connection lost. Retrying the connection` to `Could not query the database for the schema cache. Retrying.`
 - #1771, Fix silently ignoring filter on a non-existent embedded resource - @steve-chavez
 - #2152, Remove functions, which are uncallable because of unnamend arguments from schema cache and OpenAPI output. - @wolfgangwalther
 - #2145, Fix accessing json array fields with -> and ->> in ?select= and ?order=. - @wolfgangwalther
 - #2155, Ignore `max-rows` on POST, PATCH, PUT and DELETE - @steve-chavez
 - #2254, Fix inferring a foreign key column as a primary key column on views - @steve-chavez
 - #2070, Restrict generated many-to-many relationships - @steve-chavez
   + Only adds many-to-many relationships when: a table has FKs to two other tables and these FK columns are part of the table's PK columns.
 - #2278, Allow casting to types with underscores and numbers(e.g. `select=oid_array::_int4`) - @steve-chavez
 - #2277, #2238, #1643, Prevent views from breaking one-to-many/many-to-one embeds when using column or FK as target - @steve-chavez
    + When using a column or FK as target for embedding(`/tbl?select=*,col-or-fk(*)`), only tables are now detected and views are not.
    + You can still use a column or an inferred FK on a view to embed a table(`/view?select=*,col-or-fk(*)`)
 - #2317, Increase the `db-pool-timeout` to 1 hour to prevent frequent high connection latency - @steve-chavez
 - #2341, The search path now correctly identifies schemas with uppercase and special characters in their names (regression) - @laurenceisla
 - #2364, "404 Not Found" on nested routes and "405 Method Not Allowed" errors no longer start an empty database transaction - @steve-chavez
 - #2342, Fix inaccurate result count when an inner embed was selected after a normal embed in the query string - @laurenceisla
 - #2376, OPTIONS requests no longer start an empty database transaction - @steve-chavez
 - #2395, Allow using columns with dollar sign($) without double quoting in filters and `select` - @steve-chavez
 - #2410, Fix loop crash error on startup in Postgres 15 beta 3. Log: "UNION types \"char\" and text cannot be matched". - @yevon
 - #2397, Fix race conditions managing database connection helper - @robx
 - #2269, Allow `limit=0` in the request query to return an empty array - @gautam1168, @laurenceisla
 - #2401, Ensure database connections can't outlive SIGUSR1 - @robx

### Changed

 - #2001, Return 204 No Content without Content-Type for RPCs returning VOID - @wolfgangwalther
   + Previously, those RPCs would return "null" as a body with Content-Type: application/json.
 - #2156, `limit/offset` now limits the affected rows on UPDATE/DELETE  - @steve-chavez
   + Previously, `limit/offset` only limited the returned rows but not the actual updated rows
 - #2155, `max-rows` is no longer applied on POST/PATCH/PUT/DELETE returned rows - @steve-chavez
   + This was misleading because the affected rows were not really affected by `max-rows`, only the returned rows were limited
 - #2070, Restrict generated many-to-many relationships - @steve-chavez
   + A primary key that contains the foreign key columns is now needed for generating many-to-many relationships.
 - #2277, Views now are not detected when embedding using the column or FK as target (`/view?select=*,column(*)`) - @steve-chavez
   + This embedding form was easily made ambiguous whenever a new view was added.
   + You can use computed relationships to keep this embedding form working
 - #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

### Fixed

- #2165, Fix json/jsonb columns should not have type in OpenAPI spec - @clrnd
- #2020, Execute deferred constraint triggers when using `Prefer: tx=rollback` - @wolfgangwalther
- #2077, Fix `is` not working with upper or mixed case values like `NULL, TrUe, FaLsE` - @steve-chavez
- #2024, Fix schema cache loading when views with XMLTABLE and DEFAULT are present - @wolfgangwalther
- #1724, Fix wrong CORS header Authentication -> Authorization - @wolfgangwalther
- #2120, Fix reading database configuration properly when `=` is present in value - @wolfgangwalther
- #2135, Remove trigger functions from schema cache and OpenAPI output, because they can't be called directly anyway. - @wolfgangwalther
- #2101, Remove aggregates, procedures and window functions from the schema cache and OpenAPI output. - @wolfgangwalther
- #2153, Fix --dump-schema running with a wrong PG version. - @wolfgangwalther
- #2042, Keep working when EMFILE(Too many open files) is reached. - @steve-chavez
- #2147, Ignore `Content-Type` headers for `GET` requests when calling RPCs. - @laurenceisla
    + Previously, `GET` without parameters, but with `Content-Type: text/plain` or `Content-Type: application/octet-stream` would fail with `404 Not Found`, even if a function without arguments was available.
- #2239, Fix misleading disambiguation error where the content of the `relationship` key looks like valid syntax - @laurenceisla
- #2294, Disable parallel GC for better performance on higher core CPUs - @steve-chavez
- #1076, Fix using CPU while idle - @steve-chavez

## [9.0.0] - 2021-11-25

### Added

 - #1783, Include partitioned tables into the schema cache. Allows embedding, UPSERT, INSERT with Location response, OPTIONS request and OpenAPI support for partitioned tables - @laurenceisla
 - #1878, Add Retry-After hint header when in recovery mode - @gautam1168
 - #1735, Allow calling function with single unnamed param through RPC POST. - @steve-chavez
   + Enables calling a function with a single json parameter without using `Prefer: params=single-object`
   + Enables uploading bytea to a function with `Content-Type: application/octet-stream`
   + Enables uploading raw text to a function with `Content-Type: text/plain`
 - #1938, Allow escaping inside double quotes with a backslash, e.g. `?col=in.("Double\"Quote")`, `?col=in.("Back\\slash")` - @steve-chavez
 - #1075, Allow filtering top-level resource based on embedded resources filters. This is enabled by adding `!inner` to the embedded resource, e.g. `/projects?select=*,clients!inner(*)&clients.id=eq.12`- @steve-chavez, @Iced-Sun
 - #1857, Make GUC names for headers, cookies and jwt claims compatible with PostgreSQL v14 - @laurenceisla, @robertsosinski
   + Getting the value for a header GUC on PostgreSQL 14 is done using `current_setting('request.headers')::json->>'name-of-header'` and in a similar way for `request.cookies` and `request.jwt.claims`
   + PostgreSQL versions below 14 can opt in to the new JSON GUCs by setting the `db-use-legacy-gucs` config option to false (true by default)
 - #1988, Allow specifying `unknown` for the `is` operator - @steve-chavez
 - #2031, Improve error message for ambiguous embedding and add a relevant hint that includes unambiguous embedding suggestions - @laurenceisla

### Fixed

 - #1871, Fix OpenAPI missing default values for String types and identify Array types as "array" instead of "string" - @laurenceisla
 - #1930, Fix RPC return type handling for `RETURNS TABLE` with a single column. Regression of #1615. - @wolfgangwalther
 - #1938, Fix using single double quotes(`"`) and backslashes(`/`) as values on the "in" operator - @steve-chavez
 - #1992, Fix schema cache query failing with standard_conforming_strings = off - @wolfgangwalther

### Changed

 - #1949, Drop support for embedding hints used with '.'(`select=projects.client_id(*)`), '!' should be used instead(`select=projects!client_id(*)`) - @steve-chavez
 - #1783, Partitions (created using `PARTITION OF`) are no longer included in the schema cache. - @laurenceisla
 - #2038, Dropped support for PostgreSQL 9.5 - @wolfgangwalther

## [8.0.0] - 2021-07-25

### Added

 - #1525, Allow http status override through response.status guc - @steve-chavez
 - #1512, Allow schema cache reloading with NOTIFY - @steve-chavez
 - #1119, Allow config file reloading with SIGUSR2 - @steve-chavez
 - #1558, Allow 'Bearer' with and without capitalization as authentication schema - @wolfgangwalther
 - #1470, Allow calling RPC with variadic argument by passing repeated params - @wolfgangwalther
 - #1559, No downtime when reloading the schema cache with SIGUSR1 - @steve-chavez
 - #504, Add `log-level` config option. The admitted levels are: crit, error, warn and info - @steve-chavez
 - #1607, Enable embedding through multiple views recursively - @wolfgangwalther
 - #1598, Allow rollback of the transaction with Prefer tx=rollback - @wolfgangwalther
 - #1633, Enable prepared statements for GET filters. When behind a connection pooler, you can disable preparing with `db-prepared-statements=false`
   + This increases throughput by around 30% for simple GET queries(no embedding, with filters applied).
 - #1729, #1760, Get configuration parameters from the db and allow reloading config with NOTIFY  - @steve-chavez
 - #1824, Allow OPTIONS to generate certain HTTP methods for a DB view - @laurenceisla
 - #1872, Show timestamps in startup/worker logs - @steve-chavez
 - #1881, Add `openapi-mode` config option that allows ignoring roles privileges when showing the OpenAPI output - @steve-chavez
 - CLI options(for debugging):
   + #1678, Add --dump-config CLI option that prints loaded config and exits - @wolfgangwalther
   + #1691, Add --example CLI option to show example config file - @wolfgangwalther
   + #1697, #1723, Add --dump-schema CLI option for debugging purposes - @monacoremo, @wolfgangwalther
 - #1794, (Experimental) Add `request.spec` GUC for db-root-spec - @steve-chavez

### Fixed

 - #1592, Removed single column restriction to allow composite foreign keys in join tables - @goteguru
 - #1530, Fix how the PostgREST version is shown in the help text when the `.git` directory is not available - @monacoremo
 - #1094, Fix expired JWTs starting an empty transaction on the db - @steve-chavez
 - #1162, Fix location header for POST request with select= without PK - @wolfgangwalther
 - #1585, Fix error messages on connection failure for localized postgres on Windows - @wolfgangwalther
 - #1636, Fix `application/octet-stream` appending `charset=utf-8` - @steve-chavez
 - #1469, #1638 Fix overloading of functions with unnamed arguments - @wolfgangwalther
 - #1560, Return 405 Method not Allowed for GET of volatile RPC instead of 500 - @wolfgangwalther
 - #1584, Fix RPC return type handling and embedding for domains with composite base type (#1615) - @wolfgangwalther
 - #1608, #1635, Fix embedding through views that have COALESCE with subselect - @wolfgangwalther
 - #1572, Fix parsing of boolean config values for Docker environment variables, now it accepts double quoted truth values ("true", "false") and numbers("1", "0") - @wolfgangwalther
 - #1624, Fix using `app.settings.xxx` config options in Docker, now they can be used as `PGRST_APP_SETTINGS_xxx` - @wolfgangwalther
 - #1814, Fix panic when attempting to run with unix socket on non-unix host and properly close unix domain socket on exit - @monacoremo
 - #1825, Disregard internal junction(in non-exposed schema) when embedding - @steve-chavez
 - #1846, Fix requests for overloaded functions from html forms to no longer hang (#1848) - @laurenceisla
 - #1858, Add a hint and clarification to the no relationship found error - @laurenceisla
 - #1841, Show comprehensive error when an RPC is not found in a stale schema cache - @laurenceisla
 - #1875, Fix Location headers in headers only representation for null PK inserts on views - @laurenceisla

### Changed

 - #1522, #1528, #1535, Docker images are now built from scratch based on a the static PostgREST executable (#1494) and with Nix instead of a `Dockerfile`. This reduces the compressed image size from over 30mb to about 4mb - @monacoremo
 - #1461, Location header for POST request is only included when PK is available on the table - @wolfgangwalther
 - #1560, Volatile RPC called with GET now returns 405 Method not Allowed instead of 500 - @wolfgangwalther
 - #1584, #1849 Functions that declare `returns composite_type` no longer return a single object array by default, only functions with `returns setof composite_type` return an array of objects - @wolfgangwalther
 - #1604, Change the default logging level to `log-level=error`. Only requests with a status greater or equal than 500 will be logged. If you wish to go back to the previous behaviour and log all the requests, use `log-level=info` - @steve-chavez
   + Because currently there's no buffering for logging, defaulting to the `error` level(minimum logging) increases throughput by around 15% for simple GET queries(no embedding, with filters applied).
 - #1617, Dropped support for PostgreSQL 9.4 - @wolfgangwalther
 - #1679, Renamed config settings with fallback aliases. e.g. `max-rows` is now `db-max-rows`, but `max-rows` is still accepted - @wolfgangwalther
 - #1656, Allow `Prefer=headers-only` on POST requests and change default to `minimal` (#1813) - @laurenceisla
 - #1854, Dropped undocumented support for gzip compression (which was surprisingly slow and easily enabled by mistake). In some use-cases this makes Postgres up to 3x faster - @aljungberg
 - #1872, Send startup/worker logs to stderr to differentiate from access logs on stdout - @steve-chavez

## [7.0.1] - 2020-05-18

### Fixed

- #1473, Fix overloaded computed columns on RPC - @wolfgangwalther
- #1471, Fix POST, PATCH, DELETE with ?select= and return=minimal and PATCH with empty body - @wolfgangwalther
- #1500, Fix missing `openapi-server-proxy-uri` config option - @steve-chavez
- #1508, Fix `Content-Profile` not working for POST RPC - @steve-chavez
- #1452, Fix PUT restriction for all columns - @steve-chavez

### Changed

- From this version onwards, the release page will only include a single Linux static executable that can be run on any Linux distribution.

## [7.0.0] - 2020-04-03

### Added

- #1417, `Accept: application/vnd.pgrst.object+json` behavior is now enforced for POST/PATCH/DELETE regardless of `Prefer: return=representation/minimal` - @dwagin
- #1415, Add support for user defined socket permission via `server-unix-socket-mode` config option - @Dansvidania
- #1383, Add support for HEAD request - @steve-chavez
- #1378, Add support for `Prefer: count=planned` and `Prefer: count=estimated` on GET /table - @steve-chavez, @LorenzHenk
- #1327, Add support for optional query parameter `on_conflict` to upsert with specified keys for POST - @ykst
- #1430, Allow specifying the foreign key constraint name(`/source?select=fk_constraint(*)`) to disambiguate an embedding - @steve-chavez
- #1168, Allow access to the `Authorization` header through the `request.header.authorization` GUC - @steve-chavez
- #1435, Add `request.method` and `request.path` GUCs - @steve-chavez
- #1088, Allow adding headers to GET/POST/PATCH/PUT/DELETE responses through the `response.headers` GUC - @steve-chavez
- #1427, Allow overriding provided headers(Location, Content-Type, etc) through the `response.headers` GUC - @steve-chavez
- #1450, Allow multiple schemas to be exposed in one instance. The schema to use can be selected through the headers `Accept-Profile` for GET/HEAD and `Content-Profile` for POST/PATCH/PUT/DELETE - @steve-chavez, @mahmoudkassem

### Fixed

- #1301, Fix self join resource embedding on PATCH - @herulume, @steve-chavez
- #1389, Fix many to many resource embedding on RPC/PATCH - @steve-chavez
- #1355, Allow PATCH/DELETE without `return=minimal` on tables with no select privileges - @steve-chavez
- #1361, Fix embedding a VIEW when its source foreign key is UNIQUE - @bwbroersma

### Changed

- #1385, bulk RPC call now should be done by specifying a `Prefer: params=multiple-objects` header - @steve-chavez
- #1401, resource embedding now outputs an error when multiple relationships between two tables are found - @steve-chavez
- #1423, default Unix Socket file mode from 755 to 660 - @dwagin
- #1430, Remove embedding with duck typed column names `GET /projects?select=client(*)`- @steve-chavez
  + You can rename the foreign key to `client` to make this request work in the new version: `alter table projects rename constraint projects_client_id_fkey to client`
- #1413, Change `server-proxy-uri` config option to `openapi-server-proxy-uri` - @steve-chavez

## [6.0.2] - 2019-08-22

### Fixed

- #1369, Change `raw-media-types` to accept a string of comma separated MIME types - @Dansvidania
- #1368, Fix long column descriptions being truncated at 63 characters in PostgreSQL 12 - @amedeedaboville
- #1348, Go back to converting plus "+" to space " " in querystrings by default - @steve-chavez

### Deprecated

- #1348, Deprecate `.` symbol for disambiguating resource embedding(added in #918). The url-safe '!' should be used instead. We refrained from using `+` as part of our syntax because it conflicts with some http clients and proxies.

## [6.0.1] - 2019-07-30

### Added

- #1349, Add user defined raw output media types via `raw-media-types` config option - @Dansvidania
- #1243, Add websearch_to_tsquery support - @herulume

### Fixed

- #1336, Error when testing on Chrome/Firefox: text/html requested but a single column was not selected - @Dansvidania
- #1334, Unable to compile v6.0.0 on windows - @steve-chavez

## [6.0.0] - 2019-06-21

### Added

- #1186, Add support for user defined unix socket via `server-unix-socket` config option - @Dansvidania
- #690, Add `?columns` query parameter for faster bulk inserts, also ignores unspecified json keys in a payload - @steve-chavez
- #1239, Add support for resource embedding on materialized views - @vitorbaptista
- #1264, Add support for bulk RPC call - @steve-chavez
- #1278, Add db-pool-timeout config option - @qu4tro
- #1285, Abort on wrong database password - @qu4tro
- #790, Allow override of OpenAPI spec through `root-spec` config option - @steve-chavez
- #1308, Accept `text/plain` and `text/html` for raw output - @steve-chavez


### Fixed

- #1223, Fix incorrect OpenAPI externalDocs url - @steve-chavez
- #1221, Fix embedding other resources when having a self join - @steve-chavez
- #1242, Fix embedding a view having a select in a where - @steve-chavez
- #1238, Fix PostgreSQL to OpenAPI type mappings for numeric and character types - @fpusch
- #1265, Fix query generated on bulk upsert with an empty array - @qu4tro
- #1273, Fix RPC ignoring unknown arguments by default - @steve-chavez
- #1257, Fix incorrect status when a PATCH request doesn't find rows to change - @qu4tro

### Changed

- #1288, Change server-host default of 127.0.0.1 to !4

### Deprecated

- #1288, Deprecate `.` symbol for disambiguating resource embedding(added in #918). '+' should be used instead. Though '+' is url safe, certain clients might need to encode it to '%2B'.

### Removed

- #1288, Removed support for schema reloading with SIGHUP, SIGUSR1 should be used instead - @steve-chavez

## [5.2.0] - 2018-12-12

### Added

- #1205, Add support for parsing JSON Web Key Sets - @russelldavies
- #1203, Add support for reading db-uri from a separate file - @zhoufeng1989
- #1200, Add db-extra-search-path config for adding schemas to the search_path, solves issues related to extensions created on the public schema - @steve-chavez
- #1219, Add ability to quote column names on filters - @steve-chavez

### Fixed

- #1182, Fix embedding on views with composite pks - @steve-chavez
- #1180, Fix embedding on views with subselects in pg10 - @steve-chavez
- #1197, Allow CORS for PUT - @bkylerussell
- #1181, Correctly qualify function argument of custom type in public schema - @steve-chavez
- #1008, Allow columns that contain spaces in filters - @steve-chavez

## [5.1.0] - 2018-08-31

### Added

- #1099, Add support for getting json/jsonb by array index - @steve-chavez
- #1145, Add materialized view columns to OpenAPI output - @steve-chavez
- #709, Allow embedding on views with subselects/CTE - @steve-chavez
- #1148, OpenAPI: add `required` section for the non-nullable columns - @laughedelic
- #1158, Add summary to OpenAPI doc for RPC functions - @mdr1384

### Fixed

- #1113, Fix UPSERT failing when having a camel case PK column - @steve-chavez
- #945, Fix slow start-up time on big schemas - @steve-chavez
- #1129, Fix view embedding when table is capitalized - @steve-chavez
- #1149, OpenAPI: Change `GET` response type to array - @laughedelic
- #1152, Fix RPC failing when having arguments with reserved or uppercase keywords - @mdr1384
- #905, Fix intermittent empty replies - @steve-chavez
- #1139, Fix JWTIssuedAtFuture failure for valid iat claim - @steve-chavez
- #1141, Fix app.settings resetting on pool timeout - @steve-chavez

### Changed

- #1099, Numbers in json path `?select=data->1->>key` now get treated as json array indexes instead of keys - @steve-chavez
- #1128, Allow finishing a json path with a single arrow `->`. Now a json can be obtained without resorting to casting, Previously: `/json_arr?select=data->>2::json`, now: `/json_arr?select=data->2` - @steve-chavez
- #724, Change server-host default of *4 to 127.0.0.1

### Deprecated

- #724, SIGHUP deprecated, SIGUSR1 should be used instead

## [0.5.0.0] - 2018-05-14

### Added

- The configuration (e.g. `postgrest.conf`) now accepts arbitrary settings that will be passed through as session-local database settings. This can be used to pass in secret keys directly as strings, or via OS environment variables. For instance: `app.settings.jwt_secret = "$(MYAPP_JWT_SECRET)"` will take `MYAPP_JWT_SECRET` from the environment and make it available to postgresql functions as `current_setting('app.settings.jwt_secret')`. Only `app.settings.*` values in the configuration file are treated in this way. - @canadaduane
- #256, Add support for bulk UPSERT with POST and single UPSERT with PUT - @steve-chavez
- #1078, Add ability to specify source column in embed - @steve-chavez
- #821, Allow embeds alias to be used in filters - @steve-chavez
- #906, Add jspath configurable `role-claim-key` - @steve-chavez
- #1061, Add foreign tables to OpenAPI output - @rhyamada

### Fixed

- #828, Fix computed column only working in public schema - @steve-chavez
- #925, Fix RPC high memory usage by using parametrized query and avoiding json encoding - @steve-chavez
- #987, Fix embedding with self-reference foreign key - @steve-chavez
- #1044, Fix view parent embedding when having many views - @steve-chavez
- #781, Fix accepting misspelled desc/asc ordering modificators - @onporat, @steve-chavez

### Changed

- #828, A `SET SCHEMA <db-schema>` is done on each request, this has the following implications:
  - Computed columns now only work if they belong to the db-schema
  - Stored procedures might require a `search_path` to work properly, for further details see https://postgrest.org/en/v5.0/api.html#explicit-qualification
- To use RPC now the `json_to_record/json_to_recordset` functions are needed, these are available starting from PostgreSQL 9.4 - @steve-chavez
- Overloaded functions now depend on the `dbStructure`, restart/sighup may be needed for their correct functioning - @steve-chavez
- #1098, Removed support for:
  + curly braces `{}` in embeds, i.e. `/clients?select=*,projects{*}` can no longer be used, from now on parens `()` should be used `/clients?select=*,projects(*)` - @steve-chavez
  + "in" operator without parens, i.e. `/clients?id=in.1,2,3` no longer supported, `/clients?id=in.(1,2,3)` should be used - @steve-chavez
  + "@@", "@>" and "<@" operators, from now on their mnemonic equivalents should be used "fts", "cs" and "cd" respectively - @steve-chavez

## [0.4.4.0] - 2018-01-08

### Added

- #887, #601, #1007, Allow specifying dictionary and plain/phrase tsquery in full text search - @steve-chavez
- #328, Allow doing GET on rpc - @steve-chavez
- #917, Add ability to map RAISE errorcode/message to http status - @steve-chavez
- #940, Add ability to map GUC to http response headers - @steve-chavez
- #1022, Include git sha in version report - @begriffs
- Faster queries using json_agg - @ruslantalpa

### Fixed

- #876, Read secret files as binary, discard final LF if any - @eric-brechemier
- #968, Treat blank proxy uri as missing - @begriffs
- #933, OpenAPI externals docs url to current version - @steve-chavez
- #962, OpenAPI don't err on nonexistent schema - @steve-chavez
- #954, make OpenAPI rpc output dependent on user privileges - @steve-chavez
- #955, Support configurable aud claim - @statik
- #996, Fix embedded column conflicts table name - @grotsev
- #974, Fix RPC error when function has single OUT param - @steve-chavez
- #1021, Reduce join size in allColumns for faster program start - @nextstopsun
- #411, Remove the need for pk in &select for parent embed - @steve-chavez
- #1016, Fix anonymous requests when configured with jwt-aud - @ruslantalpa

## [0.4.3.0] - 2017-09-06

### Added

- #567, Support more JWT signing algorithms, including RSA - @begriffs
- #889, Allow more than two conditions in a single and/or - @steve-chavez
- #883, Binary output support for RPC - @steve-chavez
- #885, Postgres COMMENTs on SCHEMA/TABLE/COLUMN are used for OpenAPI - @ldesgoui
- #907, Ability to embed using a specific relation when there are multiple between tables - @ruslantalpa
- #930, Split table comment on newline to get OpenAPI operation summary and description - @daurnimator
- #938, Support for range operators - @russelldavies

### Fixed

- #877, Base64 secret read from a file ending with a newline - @eric-brechemier
- #896, Boolean env var interpolation in config file - @begriffs
- #885, OpenAPI repetition reduced by using more definitions- @ldesgoui
- #924, Improve relations initialization time - @9too
- #927, Treat blank pre-request as missing - @begriffs

### Changed

- #938, Deprecate symbol operators with mnemonic names. - @russelldavies

## [0.4.2.0] - 2017-06-11

### Added

- #742, Add connection retrying on startup and SIGHUP - @steve-chavez
- #652, Add and/or params for complex boolean logic - @steve-chavez
- #808, Env var interpolation in config file (helps Docker) - @begriffs
- #878 - CSV output support for RPC - @begriffs

### Fixed

- #822, Treat blank string JWT secret as no secret - @begriffs

## [0.4.1.0] - 2017-04-25

### Added
- Allow requesting binary output on GET - @steve-chavez
- Accept clients requesting `Content-Type: application/json` from / - @feynmanliang
- #493, Updating with empty JSON object makes zero updates @koulakis
- Make HTTP headers and cookies available as GUCs #800 - @ruslantalpa
- #701, Ability to quote values on IN filters - @steve-chavez
- #641, Allow IN filter to have no values - @steve-chavez

### Fixed
- #827, Avoid Warp reaper, extend socket timeout to 1 hour - @majorcode
- #791, malformed nested JSON error - @diogob
- Resource embedding in views referencing tables in public schema - @fab1an
- #777, Empty body is allowed when calling a non-parameterized RPC - @koulakis
- #831, Fix proc resource embedding issue with search_path - @steve-chavez
- #547, Use read-only transaction for stable/immutable RPC - @begriffs

## [0.4.0.0] - 2017-01-19

### Added
- Allow test database to be on another host - @dsimunic
- `Prefer: params=single-object` to treat payload as single json argument in RPC - @dsimunic
- Ability to generate an OpenAPI spec - @mainx07, @hudayou, @ruslantalpa, @begriffs
- Ability to generate an OpenAPI spec behind a proxy - @hudayou
- Ability to set addresses to listen on - @hudayou
- Filtering, shaping and embedding with &select for the /rpc path - @ruslantalpa
- Output names of used-defined types (instead of 'USER-DEFINED') - @martingms
- Implement support for singular representation responses for POST/PATCH requests - @ehamberg
- Include RPC endpoints in OpenAPI output - @begriffs, @LogvinovLeon
- Custom request validation with `--pre-request` argument - @begriffs
- Ability to order by jsonb keys - @steve-chavez
- Ability to specify offset for a deeper level - @ruslantalpa
- Ability to use binary base64 encoded secrets - @TrevorBasinger

### Fixed
- Do not apply limit to parent items - @ruslantalpa
- Fix bug in relation detection when selecting parents two levels up by using the name of the FK - @ruslantalpa
- Customize content negotiation per route - @begriffs
- Allow using nulls order without explicit order direction - @steve-chavez
- Fatal error on postgres unsupported version, format supported version in error message - @steve-chavez
- Prevent database memory consumption by prepared statements caches - @ruslantalpa
- Use specific columns in the RETURNING section - @ruslantalpa
- Fix columns alias for RETURNING - @steve-chavez

### Changed
- Replace `Prefer: plurality=singular` with `Accept: application/vnd.pgrst.object` - @begriffs
- Standardize arrays in responses for `Prefer: return=representation` - @begriffs
- Calling unknown RPC gives 404, not 400 - @begriffs
- Use HTTP 400 for raise\_exception - @begriffs
- Remove non-OpenAPI schema description - @begriffs
- Use comma rather than semicolon to separate Prefer header values - @begriffs
- Omit total query count by default - @begriffs
- No more reserved `jwt_claims` return type - @begriffs
- HTTP 401 rather than 400 for expired JWT - @begriffs
- Remove default JWT secret - @begriffs
- Use GUC request.jwt.claim.foo rather than postgrest.claims.foo - @begriffs
- Use config file rather than command line arguments - @begriffs

## [0.3.2.0] - 2016-06-10

### Added
- Reload database schema on SIGHUP - @begriffs
- Support "-" in column names - @ruslantalpa
- Support column/node renaming `alias:column` - @ruslantalpa
- Accept posts from HTML forms - @begriffs
- Ability to order embedded entities - @ruslantalpa
- Ability to paginate using &limit and &offset parameters - @ruslantalpa
- Ability to apply limits to embedded entities and enforce --max-rows on all levels - @ruslantalpa, @begriffs
- Add allow response header in OPTIONS - @begriffs

### Fixed
- Return 401 or 403 for access denied rather than 404 - @begriffs
- Omit Content-Type header for empty body - @begriffs
- Prevent role from being changed twice - @begriffs
- Use read-only transaction for read requests - @ruslantalpa
- Include entities from the same parent table using two different foreign keys - @ruslantalpa
- Ensure that Location header in 201 response is URL-encoded - @league
- Fix garbage collector CPU leak - @ruslantalpa et al.
- Return deleted items when return=representation header is sent - @ruslantalpa
- Use table default values for empty object inserts - @begriffs

## [0.3.1.1] - 2016-03-28

### Fixed
- Preserve unicode values in insert,update,rpc (regression) - @begriffs
- Prevent duplicate call to stored procs (regression) - @begriffs
- Allow SQL functions to generate registered JWT claims - @begriffs
- Terminate gracefully on SIGTERM (for use in Docker) - @recmo
- Relation detection fix for views that depend on multiple tables - @ruslantalpa
- Avoid count on plurality=singular and allow multiple Prefer values - @ruslantalpa

## [0.3.1.0] - 2016-02-28

### Fixed
- Prevent query error from infecting later connection - @begriffs, @ruslantalpa, @nikita-volkov, @jwiegley

### Added
- Applies range headers to RPC calls - @diogob

## [0.3.0.4] - 2016-02-12

### Fixed
- Improved usage screen - @begriffs
- Reject non-POSTs to rpc endpoints - @begriffs
- Throw an error for OPTIONS on nonexistent tables - @calebmer
- Remove deadlock on simultaneous contentious updates - @ruslantalpa, @begriffs

## [0.3.0.3] - 2016-01-08

### Fixed
- Fix bug in many-many relation detection - @ruslantalpa
- Inconsistent escaping of table names in read queries - @calebmer

## [0.3.0.2] - 2015-12-16

### Fixed
- Miscalculation of time used for expiring tokens - @calebmer
- Remove bcrypt dependency to fix Windows build - @begriffs
- Detect relations event when authenticator does not have rights to intermediate tables - @ruslantalpa
- Ensure db connections released on sigint - @begriffs
- Fix #396 include records with missing parents - @ruslantalpa
- `pgFmtIdent` always quotes #388 - @calebmer
- Default schema, changed from `"1"` to `public` - @calebmer
- #414 revert to separate count query - @ruslantalpa
- Fix #399, allow inserting in tables with no select privileges using "Prefer: representation=minimal" - @ruslantalpa

### Added
- Allow order by computed columns - @diogob
- Set max rows in response with --max-rows - @begriffs
- Selection by column name (can detect if `_id` is not included) - @calebmer

## [0.3.0.1] - 2015-11-27

### Fixed
- Filter columns on embedded parent items - @ruslantalpa

## [0.3.0.0] - 2015-11-24

### Fixed
- Use reasonable amount of memory during bulk inserts - @begriffs

### Added
- Ensure JWT expires - @calebmer
- Postgres connection string argument - @calebmer
- Encode JWT for procs that return type `jwt_claims` - @diogob
- Full text operators `@>`,`<@` - @ruslantalpa
- Shaping of the response body (filter columns, embed relations) with &select parameter for POST/PATCH - @ruslantalpa
- Detect relationships between public views and private tables - @calebmer
- `Prefer: plurality=singular` for selecting single objects - @calebmer

### Removed
- API versioning feature - @calebmer
- `--db-x` command line arguments - @calebmer
- Secure flag - @calebmer
- PUT request handling - @ruslantalpa

### Changed
- Embed foreign keys with {} rather than () - @begriffs
- Remove version number from binary filename in release - @begriffs

## [0.2.12.1] - 2015-11-12

### Fixed
- Correct order for -> and ->> in a json path - @ruslantalpa
- Return empty array instead of 500 when a set returning function returns an empty result set - @diogob

## [0.2.12.0] - 2015-10-25

### Added
- Embed associations, e.g. `/film?select=*,director(*)` - @ruslantalpa
- Filter columns, e.g. `?select=col1,col2` - @ruslantalpa
- Does not execute the count total if header "Prefer: count=none" - @diogob

### Fixed
- Tolerate a missing role in user creation - @calebmer
- Avoid unnecessary text re-encoding - @ruslantalpa

## [0.2.11.1] - 2015-09-01

### Fixed
- Accepts `*/*` in Accept header - @diogob

## [0.2.11.0] - 2015-08-28
### Added
- Negate any filter in a uniform way, e.g. `?col=not.eq=foo` - @diogob
- Call stored procedures
- Filter NOT IN values, e.g. `?col=notin.1,2,3` - @rall
- CSV responses to GET requests with `Accept: text/csv` - @diogob
- Debian init scripts - @mkhon
- Allow filters by computed columns - @diogob

### Fixed
- Reset user role on error
- Compatible with Stack
- Add materialized views to results in GET / - @diogob
- Indicate insertable=true for views that are insertable through triggers - @diogob
- Builds under GHC 7.10
- Allow the use of columns named "count" in relations queried - @diogob

## [0.2.10.0] - 2015-06-03
### Added
- Full text search, eg `/foo?text_vector=@@.bar`
- Include auth id as well as db role to views (for row-level security)

## [0.2.9.1] - 2015-05-20
### Fixed
- Put -Werror behind a cabal flag (for CI) so Hackage accepts package

## [0.2.9.0] - 2015-05-20
### Added
- Return range headers in PATCH
- Return PATCHed resources if header "Prefer: return=representation"
- Allow nested objects and arrays in JSON post for jsonb columns
- JSON Web Tokens - [Federico Rampazzo](https://github.com/framp)
- Expose PostgREST as a Haskell package

### Fixed
- Return 404 if no records updated by PATCH

## [0.2.8.0] - 2015-04-17
### Added
- Option to specify nulls first or last, eg `/people?order=age.desc.nullsfirst`
- Filter nulls, `?col=is.null` and `?col=isnot.null`
- Filter within jsonb, `?col->a->>b=eq.c`
- Accept CSV in post body for bulk inserts

### Fixed
- Allow NULL values in posts
- Show full command line usage on param errors

## [0.2.7.0] - 2015-03-03
### Added
- Server response logging
- Filter IN values, e.g. `?col=in.1,2,3`
- Return POSTed resource if header "Prefer: return=representation"
- Allow override of default (v1) schema

## [0.2.6.0] - 2015-02-18
### Added
- A changelog
- Filter by substring match, e.g. `?col=like.*hello*` (or ilike for
  case insensitivity).
- Access-Control-Expose-Headers for CORS

### Fixed
- Make filter position match docs, e.g. `?order=col.asc` rather
  than `?order=asc.col`.


================================================
FILE: CODE_OF_CONDUCT.md
================================================

# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at support@postgrest.org.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].

Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].

For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].

[homepage]: https://www.contributor-covenant.org
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to PostgREST

## Issues

For questions on how to use PostgREST, please use
[GitHub discussions](https://github.com/PostgREST/postgrest/discussions).

### Reporting an Issue

* Make sure you test against the latest [stable release](https://github.com/PostgREST/postgrest/releases/latest)
  and also against the latest [devel release](https://github.com/PostgREST/postgrest/releases/tag/devel).
  It is possible we already fixed the bug you're experiencing.

* Provide steps to reproduce the issue, including your OS version and
  the specific database schema that you are using.

* Please include SQL logs for issues involving runtime problems. To obtain logs first
  [enable logging all statements](http://www.microhowto.info/howto/log_all_queries_to_a_postgresql_server.html),
  then [find your logs](http://blog.endpoint.com/2014/11/dear-postgresql-where-are-my-logs.html).

* If your database schema has changed while the PostgREST server is running,
  [send the server a `SIGUSR1` signal](http://postgrest.org/en/latest/admin.html#schema-reloading) or restart it to ensure the schema cache
  is not stale. This sometimes fixes apparent bugs.

## Code

We have a fully nix-based development environment with many tools for a smooth development workflow available.
Check the [development docs](https://github.com/PostgREST/postgrest/blob/main/nix/README.md) on how to set it up and use it.

* All contributions must pass the tests before being merged. When
  you create a pull request your code will automatically be tested.

* All fixes or features must have a test proving the improvement.

* All code must also pass a [linter](http://community.haskell.org/~ndm/hlint/) and [styler](https://github.com/jaspervdj/stylish-haskell)
  with no warnings. This helps enforce a uniform style for all committers. Continuous integration will check this as well on every
  pull request. There are useful tools in the nix-shell that help with checking this locally. You can run `postgrest-check` to do this manually but
  we recommend adding it to `.git/hooks/pre-commit` as `nix-shell --run postgrest-check` to automatically check this before doing a commit.

### Running Tests

For instructions on running tests, see the [development docs](https://github.com/PostgREST/postgrest/blob/main/nix/README.md#testing).

### Structuring commits in pull requests

To simplify reviews, make it easy to split pull requests if deemed necessary, and to maintain clean and meaningful history of changes, you will be asked to update your PR if it does not follow the below rules:

* It must be possible to merge the PR branch into target using `git merge --ff-only`, ie. the source branch must be rebased on top of target.
* No merge commits in the source branch.
* All commits in the source branch must be self contained, meaning: it should be possible to treat each commit as a separate PR.
* Commits in the source branch must contain only related changes (related means the changes target a single problem/goal). For example, any refactorings should be isolated from the actual change implementation into separate commits.
* Tests, documentation, and changelog updates should be contained in the same commits as the actual code changes they relate to. An exception to this rule is when test or documentation changes are made in separate PR.
* Commit messages must be prefixed with one of the prefixes defined in [the list used by commit verification scripts](https://github.com/PostgREST/postgrest/blob/main/nix/tools/gitTools.nix#L11).
* Commit messages should contain a longer description of the purpose of the changes contained in the commit and, for non-trivial changes, a description of the changes themselves.

## AI Policy

We adhere to [Gentoo's AI policy](https://wiki.gentoo.org/wiki/Project:Council/AI_policy):

> It is expressly forbidden to contribute [...] any content that has been created with the assistance of Natural Language Processing artificial intelligence tools. This motion can be revisited, should a case been made over such a tool that does not pose copyright, ethical and quality concerns.

You can find more about its rationale [here](https://wiki.gentoo.org/wiki/Project:Council/AI_policy#Rationale).


================================================
FILE: Dockerfile
================================================
# 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:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c AS postgrest

RUN apt-get update -y \
    && apt install -y --no-install-recommends libpq-dev zlib1g-dev jq gcc libnuma-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

COPY postgrest /usr/bin/postgrest
RUN chmod +x /usr/bin/postgrest

EXPOSE 3000

USER 1000

# Use the array form to avoid running the command using bash, which does not handle `SIGTERM` properly. 
# See https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop 
CMD ["postgrest"]


================================================
FILE: LICENSE
================================================
Copyright (c) 2014-2026 The PostgREST contributors

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
![Logo](static/postgrest.png "Logo")

[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)](https://www.patreon.com/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)
[![Coverage Status](https://img.shields.io/codecov/c/github/postgrest/postgrest/main)](https://app.codecov.io/gh/PostgREST/postgrest)
[![Hackage docs](https://img.shields.io/hackage/v/postgrest.svg?label=hackage)](http://hackage.haskell.org/package/postgrest)

PostgREST serves a fully RESTful API from any existing PostgreSQL
database. It provides a cleaner, more standards-compliant, faster
API than you are likely to write from scratch.

## Sponsors

<table align="center">
  <tbody>
    <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.svg">
        </a>
      </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="static/supabase.svg">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.euronodes.com/postgrest" target="_blank">
          <img width="296px" src="static/euronodes.svg">
        </a>
      </td>
    </tr>
    <tr></tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://neon.tech/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="296px" src="static/neon.jpg">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.bytebase.com/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="296px" src="static/bytebase.svg">
        </a>
      </td>
    </tr>
  </tbody>
</table>

Big thanks to our sponsors! You can join them by supporting PostgREST on [Patreon](https://www.patreon.com/postgrest).

## Usage

1. See the docs for [how to install PostgREST on your platform](https://docs.postgrest.org/en/stable/explanations/install.html). You can also [use Docker](https://docs.postgrest.org/en/stable/explanations/install.html#docker).

2. Invoke for help:

    ```bash
    postgrest --help
    ```
## [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/tree/main/docs).

## Performance

TLDR; subsecond response times for up to 2000 requests/sec on Heroku
free tier. If you're used to servers written in interpreted languages,
prepare to be pleasantly surprised by PostgREST performance.

Three factors contribute to the speed. First the server is written
in [Haskell](https://www.haskell.org/) using the
[Warp](http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks)
HTTP server (aka a compiled language with lightweight threads).
Next it delegates as much calculation as possible to the database
including

* Serializing JSON responses directly in SQL
* Data validation
* Authorization
* Combined row counting and retrieval
* Data post in single command (`returning *`)

Finally it uses the database efficiently with the
[Hasql](https://nikita-volkov.github.io/hasql-benchmarks/) library
by

* Keeping a pool of db connections
* Using the PostgreSQL binary protocol
* Being stateless to allow horizontal scaling

## Security

PostgREST [handles
authentication](http://postgrest.org/en/stable/auth.html) (via JSON Web
Tokens) and delegates authorization to the role information defined in
the database. This ensures there is a single declarative source of truth
for security.  When dealing with the database the server assumes the
identity of the currently authenticated user, and for the duration of
the connection cannot do anything the user themselves couldn't. Other
forms of authentication can be built on top of the JWT primitive. See
the docs for more information.

## Versioning

A robust long-lived API needs the freedom to exist in multiple
versions. PostgREST does versioning through database schemas. This
allows you to expose tables and views without making the app brittle.
Underlying tables can be superseded and hidden behind public facing
views.

## Self-documentation

PostgREST uses the [OpenAPI](https://openapis.org/) standard to
generate up-to-date documentation for APIs. You can use a tool like
[Swagger-UI](https://github.com/swagger-api/swagger-ui) to render
interactive documentation for demo requests against the live API server.

This project uses HTTP to communicate other metadata as well.  For
instance the number of rows returned by an endpoint is reported by -
and limited with - range headers. More about
[that](http://begriffs.com/posts/2014-03-06-beyond-http-header-links.html).

## Data Integrity

Rather than relying on an Object Relational Mapper and custom
imperative coding, this system requires you to put declarative constraints
directly into your database. Hence no application can corrupt your
data (including your API server).

The PostgREST exposes HTTP interface with safeguards to prevent
surprises, such as enforcing idempotent PUT requests.

See examples of [PostgreSQL
constraints](http://www.tutorialspoint.com/postgresql/postgresql_constraints.htm)
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

Every donation will be spent on making PostgREST better for the whole community.

## Contributing

Contributions are always welcome and appreciated. Please see the [Contributing guidelines](https://github.com/PostgREST/postgrest/blob/main/CONTRIBUTING.md).

## Thanks

The PostgREST organization is grateful to:

- The project [sponsors and backers](https://github.com/PostgREST/postgrest/blob/main/BACKERS.md) who support PostgREST's development.
- The project [contributors](https://github.com/PostgREST/postgrest/graphs/contributors) who have improved PostgREST immensely with their code
  and good judgement. See more details in the [changelog](https://github.com/PostgREST/postgrest/blob/main/CHANGELOG.md).

The cool logo came from [Mikey Casalaina](https://github.com/casalaina).


================================================
FILE: Setup.hs
================================================
-- This file is required by Hackage.
import Distribution.Simple
main = defaultMain


================================================
FILE: cabal.project
================================================
packages: postgrest.cabal
tests: true


================================================
FILE: cabal.project.freeze
================================================
index-state: hackage.haskell.org 2025-10-29T04:02:18Z


================================================
FILE: default.nix
================================================
{ system ? builtins.currentSystem

, compiler ? "ghc948"

, # Commit of the Nixpkgs repository that we want to use.
  # It defaults to reading the inputs from flake.lock, which serves
  # as a compatibility layer for non-flake builds / default.nix / shell.nix.
  nixpkgsVersion ? let
    lock = builtins.fromJSON (builtins.readFile ./flake.lock);
  in
  {
    inherit (lock.nodes.nixpkgs.locked) owner repo rev;
    tarballHash = lock.nodes.nixpkgs.locked.narHash;
  }

, # 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";

  # PostgREST source files, filtered based on the rules in the .gitignore files
  # and file extensions. We want to include as little as possible, as the files
  # added here will increase the space used in the Nix store and trigger the
  # build of new Nix derivations when changed.
  src =
    pkgs.lib.sourceFilesBySuffices
      (pkgs.gitignoreSource ./.)
      [ ".cabal" ".hs" ".lhs" "LICENSE" ];

  allOverlays =
    import nix/overlays;

  overlays =
    [
      allOverlays.build-toolbox
      allOverlays.checked-shell-script
      allOverlays.gitignore
      (allOverlays.haskell-packages { inherit compiler; })
    ];

  # Evaluated expression of the Nixpkgs repository.
  pkgs =
    import nixpkgs { inherit overlays system; };

  postgresqlVersions =
    [
      { name = "pg-17"; postgresql = pkgs.postgresql_17.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
      { name = "pg-16"; postgresql = pkgs.postgresql_16.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
      { name = "pg-15"; postgresql = pkgs.postgresql_15.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
      { name = "pg-14"; postgresql = pkgs.postgresql_14.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
      { name = "pg-13"; postgresql = pkgs.postgresql_13.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
    ];

  haskellPackages = pkgs.haskell.packages."${compiler}";

  # Dynamic derivation for PostgREST
  postgrest = pkgs.lib.pipe (haskellPackages.callCabal2nix name src { }) [
    # To allow ghc-datasize to be used.
    lib.disableLibraryProfiling
    # We are never going to use dynamic haskell libraries anyway. "Dynamic" refers to how
    # non-haskell deps are linked. All haskell dependencies are always statically linked.
    lib.disableSharedLibraries
  ];

  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";

  inherit (pkgs.haskell) lib;
in
rec {
  inherit nixpkgs pkgs;

  # Derivation for the PostgREST Haskell package, including the executable,
  # libraries and documentation. We disable running the test suite on Nix
  # builds, as they require a database to be set up. We split the binary
  # into a separate output, so that the default distribution via flake.nix
  # has a much smaller closure size.
  postgrestPackage = pkgs.lib.pipe postgrest [
    lib.dontCheck
    lib.enableSeparateBinOutput
    (haskellPackages.generateOptparseApplicativeCompletions [ "postgrest" ])
  ];

  # Profiled dynamic executable.
  postgrestProfiled = pkgs.lib.pipe postgrestPackage [
    lib.enableExecutableProfiling
    lib.enableLibraryProfiling
    lib.dontHaddock
  ];

  inherit (postgrest) env;

  # Tooling for analyzing Haskell imports and exports.
  hsie =
    pkgs.callPackage nix/hsie {
      inherit (pkgs.haskell.packages."${compiler}") ghcWithPackages;
    };

  ### Tools

  cabalTools =
    pkgs.callPackage nix/tools/cabalTools.nix { inherit devCabalOptions postgrest; };

  withTools =
    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 { };

  # Git tools.
  gitTools =
    pkgs.callPackage nix/tools/gitTools.nix { };

  # Load testing tools.
  loadtest =
    pkgs.callPackage nix/tools/loadtest.nix { inherit withTools; };

  # Utility for updating the pinned version of Nixpkgs.
  nixpkgsTools =
    pkgs.callPackage nix/tools/nixpkgsTools.nix { };

  # Scripts for publishing new releases.
  release =
    pkgs.callPackage nix/tools/release.nix { };

  # Linting and styling tools.
  style =
    pkgs.callPackage nix/tools/style.nix { inherit hsie; };

  # Scripts for running tests.
  tests =
    pkgs.callPackage nix/tools/tests.nix {
      inherit postgrest devCabalOptions withTools;
      ghc = pkgs.haskell.compiler."${compiler}";
      inherit (pkgs.haskell.packages."${compiler}") hpc-codecov;
      inherit (pkgs.haskell.packages."${compiler}") weeder;
    };
} // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux rec {
  # Static executable.
  inherit (staticHaskellPackage) postgrestStatic;
  inherit (staticHaskellPackage) packagesStatic;

  # Docker images and loading script.
  docker =
    pkgs.callPackage nix/tools/docker { postgrest = postgrestStatic; };
}


================================================
FILE: docker-hub-readme.md
================================================
# PostgREST

[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)](https://www.patreon.com/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)

PostgREST serves a fully RESTful API from any existing PostgreSQL database. It
provides a cleaner, more standards-compliant, faster API than you are likely to
write from scratch.

## Sponsors

<table align="center">
  <tbody>
    <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.svg">
        </a>
      </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.svg">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.euronodes.com/postgrest" target="_blank">
          <img width="296px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/euronodes.svg">
        </a>
      </td>
    </tr>
    <tr></tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://neon.tech/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="296px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/neon.jpg">
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://www.bytebase.com/?utm_source=sponsor&utm_campaign=postgrest" target="_blank">
          <img width="296px" src="https://raw.githubusercontent.com/PostgREST/postgrest/main/static/bytebase.svg">
        </a>
      </td>
    </tr>
  </tbody>
</table>

# Usage

To learn how to use this container, see the [PostgREST Docker
documentation](https://postgrest.org/en/stable/install.html#docker).

You can configure the PostgREST image by setting
[environment variables](https://postgrest.org/en/stable/configuration.html).

# How this image is built

The image is built from scratch using
[Nix](https://nixos.org/nixpkgs/manual/#sec-pkgs-dockerTools) instead of a
`Dockerfile`, which yields a highly secure and optimized image. This is also why
no commands are listed in the image history. See the [PostgREST
repository](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.


================================================
FILE: docs/.gitignore
================================================
_build
Pipfile.lock
*.aux
*.log
_diagrams/db.pdf
misspellings
unuseddict
*.mo


================================================
FILE: docs/README.md
================================================
# PostgREST documentation https://postgrest.org/

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, 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.


================================================
FILE: docs/_diagrams/README.md
================================================
## ERD

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 ./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/

## UML

The UML diagrams are created with https://plantuml.com/.

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
plantuml -tsvg uml/arch.uml -o ../../_static
plantuml -tsvg -darkmode uml/dark/arch-dark.uml -o ../../../_static
```


================================================
FILE: docs/_diagrams/er/boxoffice.er
================================================
entity {font: "FreeSans"}
relationship {font: "FreeMono"}

[Box_Office]
*bo_date
*+film_id
gross_revenue

[Films]
*id
+director_id
title
`...`

Box_Office +--1 Films


================================================
FILE: docs/_diagrams/er/employees.er
================================================
# Build using: -e ortho

entity {font: "FreeSans"}
relationship {font: "FreeMono"}

[Employees]
*id
first_name
last_name
+supervisor_id

Employees 1--* Employees


================================================
FILE: docs/_diagrams/er/film.er
================================================
entity {font: "FreeSans"}
relationship {font: "FreeSerif"}

[Films]
*id
+director_id
title
year
rating
language

[Directors]
*id
first_name
last_name

[Actors]
*id
first_name
last_name

[Roles]
*+film_id
*+actor_id
character

[Competitions]
*id
name
year

[Nominations]
*+competition_id
*+film_id
rank

[Technical_Specs]
*+film_id
runtime
camera
sound

Roles *--1 Actors
Roles *--1 Films

Nominations *--1 Competitions
Nominations *--1 Films

Films *--1 Directors

Films 1--1 Technical_Specs


================================================
FILE: docs/_diagrams/er/orders.er
================================================
# Build using: -e ortho

entity {font: "FreeSans"}
relationship {font: "FreeMono"}

[Addresses]
*id
name
city
state
postal_code

[Orders]
*id
name
+billing_address_id
+shipping_address_id

Orders *--1 Addresses
Orders *--1 Addresses


================================================
FILE: docs/_diagrams/er/premieres.er
================================================
entity {font: "FreeSans"}
relationship {font: "FreeMono"}

[Premieres]
*id
location
date
+film_id

[Films]
*id
+director_id
title
`...`

Premieres *--1 Films


================================================
FILE: docs/_diagrams/er/presidents.er
================================================
# Build using: -e ortho

entity {font: "FreeSans"}
relationship {font: "FreeMono"}

[Presidents]
*id
first_name
last_name
+predecessor_id

Presidents 1--? Presidents


================================================
FILE: docs/_diagrams/er/users.er
================================================
# Build using: -e ortho

entity {font: "FreeSans"}
relationship {font: "FreeMono"}

[Users]
*id
first_name
last_name
username

[Subscriptions]
*+subscriber_id
*+subscribed_id
type

Users 1--* Subscriptions
Subscriptions *--1 Users


================================================
FILE: docs/_diagrams/uml/arch.uml
================================================
@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 : request with JWT
HTTPAPI <.l- Proxy

hexagon ExternalAuth
ExternalAuth -u[hidden]- Proxy
:user: .r-> ExternalAuth : login
:user: <.r- ExternalAuth : JWT

:operator: .d-> HTTPADMIN
:operator: .d-> CLI


PostgreSQL <.developer : "\t"
Listener -r.> "PostgreSQL"
"Connection Pool" -r.> "PostgreSQL" : "\t\t"

note bottom of Auth
  Validates the JWT
end note

note bottom of ApiRequest
  Parses the URL syntax
end note

note bottom of Plan
  Generates internal AST
end note

note bottom of Query
  Generates the SQL
end note

note top of Listener
  LISTEN session
end note

url of ExternalAuth is [[../explanations/external_auth.html]]
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 ApiRequest is [[../explanations/architecture.html#api-request]]
url of Plan is [[../explanations/architecture.html#plan]]
url of Query is [[../explanations/architecture.html#query]]
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 [[../explanations/architecture.html#http]]
url of HTTPAPI is [[../explanations/architecture.html#http]]
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


================================================
FILE: docs/_diagrams/uml/dark/arch-dark.uml
================================================
@startuml
!include ../arch.uml
@enduml


================================================
FILE: docs/_diagrams/uml/dark/sch-iso-dark.uml
================================================
@startuml
!include ../sch-iso.uml
@enduml


================================================
FILE: docs/_diagrams/uml/sch-iso.uml
================================================
@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


================================================
FILE: docs/_static/css/custom.css
================================================
.wy-nav-content {
  max-width: initial;
}

#postgrest-documentation > h1 {
  display: none;
}

div.wy-menu.rst-pro {
  display: none !important;
}

div.highlight {
  background: #fff !important;
}

div.line-block {
  margin-bottom: 0px !important;
}

#sponsors {
  text-align: center;
}

#sponsors h2 {
  text-align: left;
}

#sponsors img{
  margin: 10px;
  width: 13em; /* ".. image::" does not apply width properly to SVGs */
}

#thanks{
  text-align: center;
}

#thanks img{
  margin: 10px;
}

#thanks h2{
  text-align: left;
}

#thanks p{
  text-align: left;
}

#thanks ul{
  text-align: left;
}

.image-container {
  max-width: 800px;
  display: block;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 24px;
}

.wy-table-responsive table td {
    white-space: normal !important;
}

.wy-table-responsive {
    overflow: visible !important;
}

#tutorials span.caption-text {
    display: none;
}

#references span.caption-text {
    display: none;
}

#explanations span.caption-text {
    display: none;
}

#how-tos span.caption-text {
    display: none;
}

#ecosystem span.caption-text {
    display: none;
}

#integrations span.caption-text {
    display: none;
}

#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;
}


================================================
FILE: docs/conf.py
================================================
# -*- coding: utf-8 -*-
#
# PostgREST documentation build configuration file, created by
# sphinx-quickstart on Sun Oct  9 16:53:00 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import os

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
# sys.path.insert(0, os.path.abspath('.'))

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    "sphinx_tabs.tabs",
    "sphinx_copybutton",
    "sphinxext.opengraph",
    "sphinx_rtd_dark_mode",
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"

# The encoding of source files.
# source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = "index"

# This is overridden by readthedocs with the version tag anyway
version = "devel"
# To avoid repetition in <title> we set this to an empty string.
release = ""

# General information about the project.
project = "PostgREST " + version
author = "The PostgREST contributors"
copyright = "2017, " + author

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "shared/*.rst"]

# The reST default role (used for this markup: `text`) to use for all
# documents.
# default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"

# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False


# -- Options for HTML output ----------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = "sphinx_rtd_theme"

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []

# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
# html_title = u'PostgREST v0.4.0.0'

# A shorter title for the navigation bar.  Default is the same as html_title.
# html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None

# The name of an image file (relative to this directory) to use as a favicon of
# the docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = "_static/favicon.ico"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
# html_extra_path = []

# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
# html_last_updated_fmt = None

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}

# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}

# If false, no module index is generated.
# html_domain_indices = True

# If false, no index is generated.
# html_use_index = True

# If true, the index is split into individual pages for each letter.
# html_split_index = False

# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None

# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
# html_search_language = 'en'

# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
# html_search_options = {'type': 'default'}

# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
# html_search_scorer = 'scorer.js'

# Output file base name for HTML help builder.
htmlhelp_basename = "PostgRESTdoc"

# -- Options for LaTeX output ---------------------------------------------

latex_elements = {
    # The paper size ('letterpaper' or 'a4paper').
    #'papersize': 'letterpaper',
    # The font size ('10pt', '11pt' or '12pt').
    #'pointsize': '10pt',
    # Additional stuff for the LaTeX preamble.
    #'preamble': '',
    # Latex figure (float) alignment
    #'figure_align': 'htbp',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
#  author, documentclass [howto, manual, or own class]).
latex_documents = [
    (master_doc, "PostgREST.tex", "PostgREST Documentation", author, "manual"),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False

# If true, show page references after internal links.
# latex_show_pagerefs = False

# If true, show URL addresses after external links.
# latex_show_urls = False

# Documents to append as an appendix to all manuals.
# latex_appendices = []

# If false, no module index is generated.
# latex_domain_indices = True


# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, "postgrest", "PostgREST Documentation", [author], 1)]

# If true, show URL addresses after external links.
# man_show_urls = False


# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
    (
        master_doc,
        "PostgREST",
        "PostgREST Documentation",
        author,
        "PostgREST",
        "REST API for any PostgreSQL database",
        "Web",
    ),
]

# Documents to append as an appendix to all manuals.
# texinfo_appendices = []

# If false, no module index is generated.
# texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
# texinfo_no_detailmenu = False

# -- Custom setup ---------------------------------------------------------


def setup(app):
    app.add_css_file("css/custom.css")


user_agent = (
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0"
)

linkcheck_ignore = [
    # 403 only in CI / GitHub Actions
    r"https://www.patreon.com/postgrest",
    r"https://blog.frankel.ch/poor-man-api",
    r"https://www.cybertec-postgresql.com/.*",
    # Odd SSL error
    r"https://www.dripdepot.com",
    r"https://www.euronodes.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"
ogp_use_first_image = True
ogp_enable_meta_description = True
ogp_description_length = 300

## RTD sets html_baseurl, ensures we use the correct env for canonical URLs
## Useful to generate correct meta tags for Open Graph
## Refs: https://github.com/readthedocs/readthedocs.org/issues/10226, https://github.com/urllib3/urllib3/pull/3064
html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "/")


================================================
FILE: docs/ecosystem.rst
================================================
.. _community_tutorials:

Community Tutorials
-------------------

* `Building a Contacts List with PostgREST and Vue.js <https://www.youtube.com/watch?v=iHtsALtD5-U>`_ -
  In this video series, DigitalOcean shows how to build and deploy an Nginx + PostgREST(using a managed PostgreSQL database) + Vue.js webapp in an Ubuntu server droplet.

* `PostgREST + Auth0: Create REST API in minutes, 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.

* `"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).

* `How PostgreSQL triggers work when called with a PostgREST PATCH HTTP request <https://blog.fgribreau.com/2020/11/how-postgresql-triggers-works-when.html>`_ - A tutorial to see how the old and new values are set or not when doing a PATCH request to PostgREST.

* `REST Data Service on YugabyteDB / PostgreSQL <https://dev.to/yugabyte/rest-data-service-on-yugabytedb-postgresql-5f2h>`_

* `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.

.. * `Accessing a PostgreSQL database in Godot 4 via PostgREST <https://peterkingsbury.com/2022/08/16/godot-postgresql-postgrest/>`_

.. _templates:

Templates
---------

* `compose-postgrest <https://github.com/mattddowney/compose-postgrest>`_ - docker-compose setup with Nginx and HTML example
* `svelte-postgrest-template <https://github.com/guyromm/svelte-postgrest-template>`_ - Svelte/SvelteKit, PostgREST, EveryLayout and social auth

.. _eco_example_apps:

Example Apps
------------

* `archtika <https://github.com/thiloho/archtika>`_ - self-hosted 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
* `fullstack template <https://github.com/jenstroeger/fullstack-webapp-template>`_ - a complete fullstack webapp template using PG as db and message queue, Python and Dramatiq to implement async jobs, db migrations, test runners, and more.
* `general <https://github.com/PierreRochard/general>`_ - example auth back-end
* `guild-operators <https://github.com/cardano-community/koios-artifacts/tree/main/files/grest>`_ - example queries and functions that the Cardano Community uses for their Guild Operators' Repository
* `PostGUI <https://github.com/priyank-purohit/PostGUI>`_ - React Material UI admin panel
* `prospector <https://github.com/sfcta/prospector>`_ - data warehouse and visualization platform

.. _devops:

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
* `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 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
* `postgresql2websocket <https://github.com/frafra/postgresql2websocket>`_ - Websockets


.. _eco_extensions:

Extensions
----------

* `aiodata <https://github.com/Exahilosys/aiodata>`_ - Python, event-based proxy and caching client.
* `pg-safeupdate <https://github.com/eradman/pg-safeupdate>`_ - prevent full-table updates or deletes
* `postgrest-node <https://github.com/seveibar/postgrest-node>`_ - Run a PostgREST server in Node.js via npm module
* `PostgREST-writeAPI <https://github.com/ppKrauss/PostgREST-writeAPI>`_ - generate Nginx rewrite rules to fit an OpenAPI spec

.. _clientside_libraries:

Client-Side Libraries
---------------------

* `postgrest-csharp <https://github.com/supabase-community/postgrest-csharp>`_ - C#
* `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/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.
* `vue-postgrest <https://github.com/technowledgy/vue-postgrest>`_ - Vue.js



================================================
FILE: docs/explanations/architecture.rst
================================================
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>`_ generates an internal AST, filling 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`.


================================================
FILE: docs/explanations/db_authz.rst
================================================
.. _db_authz:

Database Authorization
######################

Database authorization is the process of granting and verifying database access permissions. PostgreSQL manages permissions using the concept of roles.

Users and Groups
================

A role can be thought of as either a database user, or a group of database users, depending on how the role is set up.

Roles for Each Web User
-----------------------

PostgREST can accommodate either viewpoint. If you treat a role as a single user then :ref:`user_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.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

  CREATE TABLE chat (
    message_uuid    UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    message_time    TIMESTAMP NOT NULL DEFAULT now(),
    message_from    NAME      NOT NULL DEFAULT current_user,
    message_to      NAME      NOT NULL,
    message_subject VARCHAR(64) NOT NULL,
    message_body    TEXT
  );

  ALTER TABLE chat ENABLE ROW LEVEL SECURITY;

We want to enforce a policy that ensures a user can see only those messages sent by them or intended for them. Also we want to prevent a user from forging the ``message_from`` column with another person's name.

PostgreSQL allows us to set this policy with row-level security:

.. code-block:: postgres

  CREATE POLICY chat_policy ON chat
    USING ((message_to = current_user) OR (message_from = current_user))
    WITH CHECK (message_from = current_user)

Anyone accessing the generated API endpoint for the chat table will see exactly the rows they should, without our needing custom imperative server-side coding.

.. warning::

   Roles are namespaced per-cluster rather than per-database so they may be prone to collision.

Web Users Sharing Role
----------------------

Alternately database roles can represent groups instead of (or in addition to) individual users. You may choose that all signed-in users for a web app share the role ``webuser``. You can distinguish individual users by including extra claims in the JWT such as email.

.. code:: json

  {
    "role": "webuser",
    "email": "john@doe.com"
  }

SQL code can access claims through PostgREST :ref:`tx_settings`. For instance to get the email claim, call this function:

.. code:: sql

  current_setting('request.jwt.claims', true)::json->>'email';

.. note::

  For PostgreSQL < 14

  .. code:: sql

    current_setting('request.jwt.claim.email', true);

This allows JWT generation services to include extra information and your database code to react to it. For instance the RLS example could be modified to use this ``current_setting`` rather than ``current_user``. The second ``'true'`` argument tells ``current_setting`` to return NULL if the setting is missing from the current configuration.

Hybrid User-Group Roles
-----------------------

You can mix the group and individual role policies. For instance we could still have a webuser role and individual users which inherit from it:

.. code-block:: postgres

  CREATE ROLE webuser NOLOGIN;
  -- grant this role access to certain tables etc

  CREATE ROLE user000 NOLOGIN;
  GRANT webuser TO user000;
  -- now user000 can do whatever webuser can

  GRANT user000 TO authenticator;
  -- allow authenticator to switch into user000 role
  -- (the role itself has nologin)

Schemas
=======

You must explicitly allow roles to access the exposed schemas in :ref:`db-schemas`.

.. code-block:: postgres

   GRANT USAGE ON SCHEMA api TO webuser;

Tables
======

To let web users access tables you must grant them privileges for the operations you want them to do.

.. code-block:: postgres

  GRANT
    SELECT
  , INSERT
  , UPDATE(message_body)
  , DELETE
  ON chat TO webuser;

You can also choose on which table columns the operation is valid. In the above example, the web user can only update the ``message_body`` column.

.. _func_privs:

Functions
=========

By default, when a function is created, the privilege to execute it is not restricted by role. The function access is ``PUBLIC`` — executable by all roles (more details at `PostgreSQL Privileges page <https://www.postgresql.org/docs/current/ddl-priv.html>`_). This is not ideal for an API schema. To disable this behavior, you can run the following SQL statement:

.. code-block:: postgres

  ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;

This will change the privileges for all functions created in the future in all schemas. Currently there is no way to limit it to a single schema. In our opinion it's a good practice anyway.

.. note::

    It is however possible to limit the effect of this clause only to functions you define. You can put the above statement at the beginning of the API schema definition, and then at the end reverse it with:

    .. code-block:: postgres

        ALTER DEFAULT PRIVILEGES GRANT EXECUTE ON FUNCTIONS TO PUBLIC;

    This will work because the :code:`alter default privileges` statement has effect on function created *after* it is executed. See `PostgreSQL alter default privileges <https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html>`_ for more details.

After that, you'll need to grant EXECUTE privileges on functions explicitly:

.. code-block:: postgres

   GRANT EXECUTE ON FUNCTION login TO anonymous;
   GRANT EXECUTE ON FUNCTION signup TO anonymous;

You can also grant execute on all functions in a schema to a higher privileged role:

.. code-block:: postgres

    GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA api TO web_user;

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 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.

.. code-block:: postgres

  -- login as a user which has privileges on the private schemas

  -- create a sample function
  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;
    -- other operations
    -- ...
  end;
  $$ language plpgsql security definer;

Note the ``SECURITY DEFINER`` keywords at the end of the function. See `PostgreSQL documentation <https://www.postgresql.org/docs/current/sql-createfunction.html#SQL-CREATEFUNCTION-SECURITY>`_ for more details.

Views
=====

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.

.. code-block:: postgres

  CREATE VIEW sample_view WITH (security_invoker = true) AS
  SELECT * FROM sample_table;

On PostgreSQL < 15, you can create a non-SUPERUSER role and make this role the view's owner.

.. code-block:: postgres

  CREATE ROLE api_views_owner NOSUPERUSER NOBYPASSRLS;
  ALTER VIEW sample_view OWNER TO api_views_owner;



================================================
FILE: docs/explanations/external_auth.rst
================================================
.. _external_auth:

External Authentication
-----------------------

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.


================================================
FILE: docs/explanations/install.rst
================================================
.. _install:

Installation
############

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.

.. include:: ../shared/installation.rst

.. _pg-dependency:

Supported PostgreSQL versions
=============================

=============== =================================
**Supported**   PostgreSQL >= 13
=============== =================================

PostgREST works with all PostgreSQL versions still `officially supported <https://www.postgresql.org/support/versioning/>`_.


Running PostgREST
=================

If you downloaded PostgREST from the release page, first extract the compressed file to obtain the executable.

.. code-block:: bash

  # For UN
Download .txt
gitextract_dt40gs3b/

├── .cirrus.yml
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── actionlint.yml
│   ├── actions/
│   │   ├── artifact-from-cirrus/
│   │   │   └── action.yaml
│   │   ├── cache-on-main/
│   │   │   └── action.yaml
│   │   └── setup-nix/
│   │       └── action.yaml
│   ├── codecov.yml
│   ├── renovate.json
│   └── workflows/
│       ├── backport.yaml
│       ├── build.yaml
│       ├── check.yaml
│       ├── ci.yaml
│       ├── docs.yaml
│       ├── linkcheck.yaml
│       ├── release.yaml
│       └── test.yaml
├── .gitignore
├── .readthedocs.yaml
├── .stylish-haskell.yaml
├── BACKERS.md
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── Setup.hs
├── cabal.project
├── cabal.project.freeze
├── default.nix
├── docker-hub-readme.md
├── docs/
│   ├── .gitignore
│   ├── README.md
│   ├── _diagrams/
│   │   ├── README.md
│   │   ├── er/
│   │   │   ├── boxoffice.er
│   │   │   ├── employees.er
│   │   │   ├── film.er
│   │   │   ├── orders.er
│   │   │   ├── premieres.er
│   │   │   ├── presidents.er
│   │   │   └── users.er
│   │   └── uml/
│   │       ├── arch.uml
│   │       ├── dark/
│   │       │   ├── arch-dark.uml
│   │       │   └── sch-iso-dark.uml
│   │       └── sch-iso.uml
│   ├── _static/
│   │   └── css/
│   │       └── custom.css
│   ├── conf.py
│   ├── ecosystem.rst
│   ├── explanations/
│   │   ├── architecture.rst
│   │   ├── db_authz.rst
│   │   ├── external_auth.rst
│   │   ├── install.rst
│   │   ├── nginx.rst
│   │   └── schema_isolation.rst
│   ├── how-tos/
│   │   ├── create-soap-endpoint.rst
│   │   ├── providing-html-content-using-htmx.rst
│   │   ├── providing-images-for-img.rst
│   │   ├── sql-user-management-using-postgres-users-and-passwords.rst
│   │   ├── sql-user-management.rst
│   │   └── working-with-postgresql-data-types.rst
│   ├── index.rst
│   ├── integrations/
│   │   ├── pg-safeupdate.rst
│   │   └── systemd.rst
│   ├── postgrest.dict
│   ├── references/
│   │   ├── admin_server.rst
│   │   ├── api/
│   │   │   ├── aggregate_functions.rst
│   │   │   ├── computed_fields.rst
│   │   │   ├── cors.rst
│   │   │   ├── domain_representations.rst
│   │   │   ├── functions.rst
│   │   │   ├── media_type_handlers.rst
│   │   │   ├── openapi.rst
│   │   │   ├── options.rst
│   │   │   ├── pagination_count.rst
│   │   │   ├── preferences.rst
│   │   │   ├── resource_embedding.rst
│   │   │   ├── resource_representation.rst
│   │   │   ├── schemas.rst
│   │   │   ├── tables_views.rst
│   │   │   ├── url_grammar.rst
│   │   │   └── vary_header.rst
│   │   ├── api.rst
│   │   ├── auth.rst
│   │   ├── cli.rst
│   │   ├── configuration.rst
│   │   ├── connection_pool.rst
│   │   ├── errors.rst
│   │   ├── listener.rst
│   │   ├── observability.rst
│   │   ├── schema_cache.rst
│   │   └── transactions.rst
│   ├── requirements.txt
│   ├── shared/
│   │   └── installation.rst
│   └── tutorials/
│       ├── tut0.rst
│       └── tut1.rst
├── flake.nix
├── main/
│   └── Main.hs
├── nix/
│   ├── README.md
│   ├── UPGRADE.md
│   ├── hsie/
│   │   ├── Main.hs
│   │   ├── README.md
│   │   └── default.nix
│   ├── overlays/
│   │   ├── build-toolbox/
│   │   │   ├── build-toolbox.nix
│   │   │   └── default.nix
│   │   ├── checked-shell-script/
│   │   │   ├── checked-shell-script.nix
│   │   │   └── default.nix
│   │   ├── default.nix
│   │   ├── gitignore.nix
│   │   └── haskell-packages.nix
│   ├── static.nix
│   └── tools/
│       ├── cabalTools.nix
│       ├── devTools.nix
│       ├── docker/
│       │   ├── README.md
│       │   └── default.nix
│       ├── docs.nix
│       ├── gen_rsa_materials.py
│       ├── generate_targets.py
│       ├── gitTools.nix
│       ├── loadtest.nix
│       ├── merge_monitor_result.py
│       ├── monitor_pid.py
│       ├── nixpkgsTools.nix
│       ├── release.nix
│       ├── style.nix
│       ├── tests.nix
│       └── withTools.nix
├── postgrest.cabal
├── shell.nix
├── src/
│   └── PostgREST/
│       ├── Admin.hs
│       ├── ApiRequest/
│       │   ├── Payload.hs
│       │   ├── Preferences.hs
│       │   ├── QueryParams.hs
│       │   └── Types.hs
│       ├── ApiRequest.hs
│       ├── App.hs
│       ├── AppState.hs
│       ├── Auth/
│       │   ├── Jwt.hs
│       │   ├── JwtCache.hs
│       │   └── Types.hs
│       ├── Auth.hs
│       ├── CLI.hs
│       ├── Cache/
│       │   └── Sieve.hs
│       ├── Client.hs
│       ├── Config/
│       │   ├── Database.hs
│       │   ├── JSPath.hs
│       │   ├── PgVersion.hs
│       │   └── Proxy.hs
│       ├── Config.hs
│       ├── Cors.hs
│       ├── Error/
│       │   └── Types.hs
│       ├── Error.hs
│       ├── Listener.hs
│       ├── Logger.hs
│       ├── MainTx.hs
│       ├── MediaType.hs
│       ├── Metrics.hs
│       ├── Network.hs
│       ├── Observation.hs
│       ├── Plan/
│       │   ├── CallPlan.hs
│       │   ├── MutatePlan.hs
│       │   ├── Negotiate.hs
│       │   ├── ReadPlan.hs
│       │   └── Types.hs
│       ├── Plan.hs
│       ├── Query/
│       │   ├── PreQuery.hs
│       │   ├── QueryBuilder.hs
│       │   ├── SqlFragment.hs
│       │   └── Statements.hs
│       ├── Query.hs
│       ├── RangeQuery.hs
│       ├── Response/
│       │   ├── GucHeader.hs
│       │   ├── OpenAPI.hs
│       │   └── Performance.hs
│       ├── Response.hs
│       ├── SchemaCache/
│       │   ├── Identifiers.hs
│       │   ├── Relationship.hs
│       │   ├── Representations.hs
│       │   ├── Routine.hs
│       │   └── Table.hs
│       ├── SchemaCache.hs
│       ├── TimeIt.hs
│       ├── Unix.hs
│       └── Version.hs
├── stack.yaml
└── test/
    ├── coverage.overlay
    ├── doc/
    │   └── Main.hs
    ├── io/
    │   ├── __snapshots__/
    │   │   └── test_cli/
    │   │       ├── test_schema_cache_snapshot[dbMediaHandlers].yaml
    │   │       ├── test_schema_cache_snapshot[dbRelationships].yaml
    │   │       ├── test_schema_cache_snapshot[dbRepresentations].yaml
    │   │       ├── test_schema_cache_snapshot[dbRoutines].yaml
    │   │       ├── test_schema_cache_snapshot[dbTables].yaml
    │   │       └── test_schema_cache_snapshot[dbTimezones].yaml
    │   ├── config.py
    │   ├── configs/
    │   │   ├── aliases.config
    │   │   ├── boolean-numeric.config
    │   │   ├── boolean-string.config
    │   │   ├── defaults.config
    │   │   ├── expected/
    │   │   │   ├── aliases.config
    │   │   │   ├── boolean-numeric.config
    │   │   │   ├── boolean-string.config
    │   │   │   ├── defaults.config
    │   │   │   ├── jwt-role-claim-key1.config
    │   │   │   ├── jwt-role-claim-key2.config
    │   │   │   ├── jwt-role-claim-key3.config
    │   │   │   ├── jwt-role-claim-key4.config
    │   │   │   ├── jwt-role-claim-key5.config
    │   │   │   ├── no-defaults-with-db-other-authenticator.config
    │   │   │   ├── no-defaults-with-db.config
    │   │   │   ├── no-defaults.config
    │   │   │   ├── types.config
    │   │   │   └── utf-8.config
    │   │   ├── invalid.yaml
    │   │   ├── jwt-role-claim-key1.config
    │   │   ├── jwt-role-claim-key2.config
    │   │   ├── jwt-role-claim-key3.config
    │   │   ├── jwt-role-claim-key4.config
    │   │   ├── jwt-role-claim-key5.config
    │   │   ├── no-defaults-env.yaml
    │   │   ├── no-defaults.config
    │   │   ├── sigusr2-settings.config
    │   │   ├── types.config
    │   │   └── utf-8.config
    │   ├── conftest.py
    │   ├── fixtures/
    │   │   ├── big_schema.sql
    │   │   ├── database.sql
    │   │   ├── db_config.sql
    │   │   ├── fixtures.yaml
    │   │   ├── load.sql
    │   │   ├── privileges.sql
    │   │   ├── replica.sql
    │   │   ├── roles.sql
    │   │   └── schema.sql
    │   ├── postgrest.py
    │   ├── secrets/
    │   │   ├── ascii.b64
    │   │   ├── ascii.jwt
    │   │   ├── ascii.noeol
    │   │   ├── ascii.txt
    │   │   ├── binary.b64
    │   │   ├── binary.eol
    │   │   ├── binary.jwt
    │   │   ├── binary.noeol
    │   │   ├── utf8.b64
    │   │   ├── utf8.jwt
    │   │   ├── utf8.noeol
    │   │   ├── utf8.txt
    │   │   ├── word.b64
    │   │   ├── word.jwt
    │   │   ├── word.noeol
    │   │   └── word.txt
    │   ├── test_auth.py
    │   ├── test_big_schema.py
    │   ├── test_cli.py
    │   ├── test_io.py
    │   ├── test_replica.py
    │   ├── test_sanity.py
    │   └── util.py
    ├── load/
    │   ├── bulk.json
    │   ├── errors.http
    │   ├── errors.sql
    │   ├── fixtures.sql
    │   ├── patch.json
    │   ├── post.json
    │   ├── put.json
    │   ├── rpc.json
    │   └── targets.http
    ├── memory/
    │   └── memory-tests.sh
    ├── observability/
    │   ├── Main.hs
    │   ├── ObsHelper.hs
    │   ├── Observation/
    │   │   └── JwtCache.hs
    │   └── fixtures/
    │       ├── database.sql
    │       ├── load.sql
    │       ├── privileges.sql
    │       ├── roles.sql
    │       └── schema.sql
    ├── pgbench/
    │   ├── 1567/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── 1652/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── 2676/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── 2677/
    │   │   ├── new.sql
    │   │   └── old.sql
    │   ├── README.md
    │   └── fixtures.sql
    ├── spec/
    │   ├── Feature/
    │   │   ├── Auth/
    │   │   │   ├── AsymmetricJwtSpec.hs
    │   │   │   ├── AudienceJwtSecretSpec.hs
    │   │   │   ├── AuthSpec.hs
    │   │   │   ├── BinaryJwtSecretSpec.hs
    │   │   │   ├── NoAnonSpec.hs
    │   │   │   └── NoJwtSecretSpec.hs
    │   │   ├── ConcurrentSpec.hs
    │   │   ├── CorsSpec.hs
    │   │   ├── ExtraSearchPathSpec.hs
    │   │   ├── NoSuperuserSpec.hs
    │   │   ├── ObservabilitySpec.hs
    │   │   ├── OpenApi/
    │   │   │   ├── DisabledOpenApiSpec.hs
    │   │   │   ├── IgnorePrivOpenApiSpec.hs
    │   │   │   ├── OpenApiSpec.hs
    │   │   │   ├── ProxySpec.hs
    │   │   │   ├── RootSpec.hs
    │   │   │   └── SecurityOpenApiSpec.hs
    │   │   ├── OptionsSpec.hs
    │   │   ├── Query/
    │   │   │   ├── AggregateFunctionsSpec.hs
    │   │   │   ├── AndOrParamsSpec.hs
    │   │   │   ├── ComputedRelsSpec.hs
    │   │   │   ├── CustomMediaSpec.hs
    │   │   │   ├── DeleteSpec.hs
    │   │   │   ├── EmbedDisambiguationSpec.hs
    │   │   │   ├── EmbedInnerJoinSpec.hs
    │   │   │   ├── ErrorSpec.hs
    │   │   │   ├── InsertSpec.hs
    │   │   │   ├── JsonOperatorSpec.hs
    │   │   │   ├── MultipleSchemaSpec.hs
    │   │   │   ├── NullsStripSpec.hs
    │   │   │   ├── PgSafeUpdateSpec.hs
    │   │   │   ├── PlanSpec.hs
    │   │   │   ├── PostGISSpec.hs
    │   │   │   ├── PreferencesSpec.hs
    │   │   │   ├── QueryLimitedSpec.hs
    │   │   │   ├── QuerySpec.hs
    │   │   │   ├── RangeSpec.hs
    │   │   │   ├── RawOutputTypesSpec.hs
    │   │   │   ├── RelatedQueriesSpec.hs
    │   │   │   ├── RpcSpec.hs
    │   │   │   ├── ServerTimingSpec.hs
    │   │   │   ├── SingularSpec.hs
    │   │   │   ├── SpreadQueriesSpec.hs
    │   │   │   ├── UnicodeSpec.hs
    │   │   │   ├── UpdateSpec.hs
    │   │   │   └── UpsertSpec.hs
    │   │   ├── RollbackSpec.hs
    │   │   └── RpcPreRequestGucsSpec.hs
    │   ├── Main.hs
    │   ├── SpecHelper.hs
    │   └── fixtures/
    │       ├── 1.twkb
    │       ├── data.sql
    │       ├── database.sql
    │       ├── draft04.json
    │       ├── jsonschema.sql
    │       ├── jwt.sql
    │       ├── lines.csv
    │       ├── lines.twkb
    │       ├── load.sql
    │       ├── openapi.json
    │       ├── privileges.sql
    │       ├── roles.sql
    │       └── schema.sql
    └── weeder.toml
Download .txt
SYMBOL INDEX (853 symbols across 22 files)

FILE: docs/conf.py
  function setup (line 290) | def setup(app):

FILE: nix/tools/gen_rsa_materials.py
  function main (line 10) | def main():

FILE: nix/tools/generate_targets.py
  function generate_jwt (line 28) | def generate_jwt(
  function append_targets (line 65) | def append_targets(lines: list[str], token: str, http_method: HttpMethod):
  function run_command (line 72) | def run_command(command: list[str]):
  function main (line 92) | def main():

FILE: test/io/config.py
  function hpctixfile (line 17) | def hpctixfile():
  function get_admin_host_and_port_from_config (line 36) | def get_admin_host_and_port_from_config(config):

FILE: test/io/conftest.py
  function dburi (line 8) | def dburi():
  function baseenv (line 17) | def baseenv():
  function defaultenv (line 27) | def defaultenv(baseenv):
  function replicaenv (line 39) | def replicaenv(defaultenv):
  function slow_schema_cache_env (line 60) | def slow_schema_cache_env(defaultenv):
  function metapostgrest (line 73) | def metapostgrest():
  class YamlSnapshotExtension (line 89) | class YamlSnapshotExtension(SingleFileSnapshotExtension):
  function snapshot_yaml (line 94) | def snapshot_yaml(snapshot):

FILE: test/io/fixtures/big_schema.sql
  function apflora (line 175) | CREATE FUNCTION apflora.ap_insert_add_apart() RETURNS trigger
  function apflora (line 189) | CREATE FUNCTION apflora.ap_insert_add_idealbiotop() RETURNS trigger
  function apflora (line 203) | CREATE FUNCTION apflora.correct_vornach_beginnap_stati(apid uuid) RETURN...
  function apflora (line 531) | CREATE FUNCTION apflora.qk_pop_ohne_popmassnber(apid uuid, berichtjahr i...
  function apflora (line 595) | CREATE FUNCTION apflora.qk_tpop_ohne_massnber(apid uuid, berichtjahr int...
  function apflora (line 643) | CREATE FUNCTION apflora.qk_tpop_ohne_tpopber(apid uuid, berichtjahr inte...
  function apflora (line 685) | CREATE FUNCTION apflora.tpop_max_one_massnber_per_year() RETURNS trigger
  function apflora (line 713) | CREATE FUNCTION apflora.tpop_max_one_tpopber_per_year() RETURNS trigger
  function auth (line 741) | CREATE FUNCTION auth.algorithm_sign(signables text, secret text, algorit...
  function auth (line 772) | CREATE FUNCTION auth.encrypt_pass() RETURNS trigger
  function auth (line 786) | CREATE FUNCTION auth.sign(payload json, secret text, algorithm text DEFA...
  function auth (line 807) | CREATE FUNCTION auth.url_decode(data text) RETURNS bytea
  function auth (line 831) | CREATE FUNCTION auth.user_role(username text, pass text) RETURNS name
  function auth (line 846) | CREATE FUNCTION auth.verify(token text, secret text, algorithm text DEFA...
  function public (line 858) | CREATE FUNCTION public.adresse_on_update_set_mut() RETURNS trigger
  function public (line 871) | CREATE FUNCTION public.ap_bearbstand_werte_on_update_set_mut() RETURNS t...
  function public (line 884) | CREATE FUNCTION public.ap_erfbeurtkrit_werte_on_update_set_mut() RETURNS...
  function public (line 897) | CREATE FUNCTION public.ap_erfkrit_werte_on_update_set_mut() RETURNS trigger
  function public (line 910) | CREATE FUNCTION public.ap_on_update_set_mut() RETURNS trigger
  function public (line 923) | CREATE FUNCTION public.ap_umsetzung_werte_on_update_set_mut() RETURNS tr...
  function public (line 936) | CREATE FUNCTION public.apber_on_update_set_mut() RETURNS trigger
  function public (line 949) | CREATE FUNCTION public.apberuebersicht_on_update_set_mut() RETURNS trigger
  function public (line 962) | CREATE FUNCTION public.assozart_on_update_set_mut() RETURNS trigger
  function public (line 975) | CREATE FUNCTION public.beob_on_update_set_mut() RETURNS trigger
  function public (line 988) | CREATE FUNCTION public.beob_zuordnung_set_quelleid_on_insert() RETURNS t...
  function public (line 1006) | CREATE FUNCTION public.beobzuordnung_on_update_set_mut() RETURNS trigger
  function public (line 1019) | CREATE FUNCTION public.ber_on_update_set_mut() RETURNS trigger
  function public (line 1032) | CREATE FUNCTION public.current_user_name() RETURNS text
  function public (line 1041) | CREATE FUNCTION public.dsql2(i_text text) RETURNS integer
  function public (line 1059) | CREATE FUNCTION public.erfkrit_on_update_set_mut() RETURNS trigger
  function public (line 1072) | CREATE FUNCTION public.idealbiotop_on_update_set_mut() RETURNS trigger
  function public (line 1085) | CREATE FUNCTION public.pop_entwicklung_werte_on_update_set_mut() RETURNS...
  function public (line 1098) | CREATE FUNCTION public.pop_on_update_set_mut() RETURNS trigger
  function public (line 1111) | CREATE FUNCTION public.pop_status_werte_on_update_set_mut() RETURNS trigger
  function public (line 1124) | CREATE FUNCTION public.popber_on_update_set_mut() RETURNS trigger
  function public (line 1137) | CREATE FUNCTION public.popmassnber_on_update_set_mut() RETURNS trigger
  function public (line 1150) | CREATE FUNCTION public.projekt_on_update_set_mut() RETURNS trigger
  function public (line 1163) | CREATE FUNCTION public.tabelle_delete_notify() RETURNS trigger
  function public (line 1175) | CREATE FUNCTION public.tabelle_insert_notify() RETURNS trigger
  function public (line 1187) | CREATE FUNCTION public.tabelle_update_notify() RETURNS trigger
  function public (line 1199) | CREATE FUNCTION public.tpop_apberrelevant_werte_on_update_set_mut() RETU...
  function public (line 1212) | CREATE FUNCTION public.tpop_entwicklung_werte_on_update_set_mut() RETURN...
  function public (line 1225) | CREATE FUNCTION public.tpop_on_update_set_mut() RETURNS trigger
  function public (line 1238) | CREATE FUNCTION public.tpopber_on_update_set_mut() RETURNS trigger
  function public (line 1251) | CREATE FUNCTION public.tpopkontr_idbiotuebereinst_werte_on_update_set_mu...
  function public (line 1264) | CREATE FUNCTION public.tpopkontr_on_update_set_mut() RETURNS trigger
  function public (line 1277) | CREATE FUNCTION public.tpopkontr_typ_werte_on_update_set_mut() RETURNS t...
  function public (line 1290) | CREATE FUNCTION public.tpopkontrzaehl_einheit_werte_on_update_set_mut() ...
  function public (line 1303) | CREATE FUNCTION public.tpopkontrzaehl_methode_werte_on_update_set_mut() ...
  function public (line 1316) | CREATE FUNCTION public.tpopkontrzaehl_on_update_set_mut() RETURNS trigger
  function public (line 1329) | CREATE FUNCTION public.tpopmassn_erfbeurt_werte_on_update_set_mut() RETU...
  function public (line 1342) | CREATE FUNCTION public.tpopmassn_on_update_set_mut() RETURNS trigger
  function public (line 1355) | CREATE FUNCTION public.tpopmassn_typ_werte_on_update_set_mut() RETURNS t...
  function public (line 1368) | CREATE FUNCTION public.tpopmassnber_on_update_set_mut() RETURNS trigger
  function public (line 1381) | CREATE FUNCTION public.ziel_on_update_set_mut() RETURNS trigger
  function public (line 1394) | CREATE FUNCTION public.ziel_typ_werte_on_update_set_mut() RETURNS trigger
  function public (line 1407) | CREATE FUNCTION public.zielber_on_update_set_mut() RETURNS trigger
  function request (line 1420) | CREATE FUNCTION request.cookie(c text) RETURNS text
  function request (line 1429) | CREATE FUNCTION request.env_var(v text) RETURNS text
  function request (line 1438) | CREATE FUNCTION request.header(h text) RETURNS text
  function request (line 1447) | CREATE FUNCTION request.jwt_claim(c text) RETURNS text
  function request (line 1456) | CREATE FUNCTION request.user_name() RETURNS text
  function request (line 1468) | CREATE FUNCTION request.user_role() RETURNS text
  type apflora (line 1481) | CREATE TABLE apflora._variable (
  type apflora (line 1512) | CREATE TABLE apflora.adresse (
  type apflora (line 1585) | CREATE TABLE apflora.ae_eigenschaften (
  type apflora (line 1605) | CREATE TABLE apflora.ae_lrdelarze (
  type apflora (line 1623) | CREATE TABLE apflora.ap (
  type apflora (line 1693) | CREATE TABLE apflora.ap_bearbstand_werte (
  type apflora (line 1717) | CREATE TABLE apflora.ap_erfbeurtkrit_werte (
  type apflora (line 1741) | CREATE TABLE apflora.ap_erfkrit_werte (
  type apflora (line 1769) | CREATE TABLE apflora.ap_umsetzung_werte (
  type apflora (line 1793) | CREATE TABLE apflora.apart (
  type apflora (line 1825) | CREATE TABLE apflora.apber (
  type apflora (line 1950) | CREATE TABLE apflora.apberuebersicht (
  type apflora (line 2005) | CREATE TABLE apflora.assozart (
  type apflora (line 2056) | CREATE TABLE apflora.beob (
  type apflora (line 2128) | CREATE TABLE apflora.beob_quelle_werte (
  type apflora (line 2151) | CREATE TABLE apflora.ber (
  type apflora (line 2216) | CREATE TABLE apflora.erfkrit (
  type apflora (line 2271) | CREATE TABLE apflora.evab_typologie (
  type apflora (line 2280) | CREATE TABLE apflora.gemeinde (
  type apflora (line 2288) | CREATE TABLE apflora.idealbiotop (
  type apflora (line 2404) | CREATE TABLE apflora.message (
  type apflora (line 2433) | CREATE TABLE apflora.pop (
  type apflora (line 2520) | CREATE TABLE apflora.pop_status_werte (
  type apflora (line 2548) | CREATE TABLE apflora.popber (
  type apflora (line 2608) | CREATE TABLE apflora.popmassnber (
  type apflora (line 2668) | CREATE TABLE apflora.projekt (
  type apflora (line 2701) | CREATE TABLE apflora.tpop (
  type apflora (line 2863) | CREATE TABLE apflora.tpop_apberrelevant_werte (
  type apflora (line 2886) | CREATE TABLE apflora.tpop_entwicklung_werte (
  type apflora (line 2910) | CREATE TABLE apflora.tpopber (
  type apflora (line 2966) | CREATE TABLE apflora.tpopkontr (
  type apflora (line 3216) | CREATE TABLE apflora.tpopkontr_idbiotuebereinst_werte (
  type apflora (line 3240) | CREATE TABLE apflora.tpopkontr_typ_werte (
  type apflora (line 3264) | CREATE TABLE apflora.tpopkontrzaehl (
  type apflora (line 3316) | CREATE TABLE apflora.tpopkontrzaehl_einheit_werte (
  type apflora (line 3340) | CREATE TABLE apflora.tpopkontrzaehl_methode_werte (
  type apflora (line 3364) | CREATE TABLE apflora.tpopmassn (
  type apflora (line 3495) | CREATE TABLE apflora.tpopmassn_erfbeurt_werte (
  type apflora (line 3523) | CREATE TABLE apflora.tpopmassn_typ_werte (
  type apflora (line 3552) | CREATE TABLE apflora.tpopmassnber (
  type apflora (line 3608) | CREATE TABLE apflora."user" (
  type apflora (line 3635) | CREATE TABLE apflora.ziel (
  type apflora (line 3681) | CREATE TABLE apflora.ziel_typ_werte (
  type apflora (line 3709) | CREATE VIEW apflora.v_abper_ziel AS
  type apflora (line 3728) | CREATE VIEW apflora.v_ap AS
  type apflora (line 3747) | CREATE VIEW apflora.v_ap_anzkontr AS
  type apflora (line 3767) | CREATE VIEW apflora.v_ap_anzkontrinjahr AS
  type apflora (line 3783) | CREATE VIEW apflora.v_ap_anzmassn AS
  type apflora (line 3803) | CREATE VIEW apflora.v_ap_anzmassnprojahr0 AS
  type apflora (line 3819) | CREATE VIEW apflora.v_massn_jahre AS
  type apflora (line 3829) | CREATE VIEW apflora.v_ap_massnjahre AS
  type apflora (line 3840) | CREATE VIEW apflora.v_ap_anzmassnprojahr AS
  type apflora (line 3851) | CREATE VIEW apflora.v_ap_anzmassnbisjahr AS
  type apflora (line 3864) | CREATE VIEW apflora.v_ap_apberrelevant AS
  type apflora (line 3875) | CREATE VIEW apflora.v_ap_apberundmassn AS
  type apflora (line 3903) | CREATE VIEW apflora.v_ap_mitmassninjahr0 AS
  type apflora (line 3941) | CREATE VIEW apflora.v_ap_ohnepop AS
  type apflora (line 3961) | CREATE VIEW apflora.v_ap_tpopmassnjahr0 AS
  type apflora (line 3977) | CREATE VIEW apflora.v_apbeob AS
  type apflora (line 4004) | CREATE VIEW apflora.v_apber AS
  type apflora (line 4039) | CREATE VIEW apflora.v_apber_a10lpop AS
  type apflora (line 4050) | CREATE VIEW apflora.v_apber_a10ltpop AS
  type apflora (line 4061) | CREATE VIEW apflora.v_apber_a2lpop AS
  type apflora (line 4072) | CREATE VIEW apflora.v_apber_a2ltpop AS
  type apflora (line 4083) | CREATE VIEW apflora.v_apber_a3lpop AS
  type apflora (line 4095) | CREATE VIEW apflora.v_apber_a3ltpop AS
  type apflora (line 4107) | CREATE VIEW apflora.v_apber_a4lpop AS
  type apflora (line 4119) | CREATE VIEW apflora.v_apber_a4ltpop AS
  type apflora (line 4131) | CREATE VIEW apflora.v_apber_a5lpop AS
  type apflora (line 4142) | CREATE VIEW apflora.v_apber_a5ltpop AS
  type apflora (line 4153) | CREATE VIEW apflora.v_apber_a8lpop AS
  type apflora (line 4165) | CREATE VIEW apflora.v_apber_a8ltpop AS
  type apflora (line 4177) | CREATE VIEW apflora.v_apber_a9lpop AS
  type apflora (line 4189) | CREATE VIEW apflora.v_apber_a9ltpop AS
  type apflora (line 4201) | CREATE VIEW apflora.v_apber_b1lpop AS
  type apflora (line 4214) | CREATE VIEW apflora.v_apber_b1ltpop AS
  type apflora (line 4227) | CREATE VIEW apflora.v_apber_b1rpop AS
  type apflora (line 4240) | CREATE VIEW apflora.v_apber_b1rtpop AS
  type apflora (line 4253) | CREATE VIEW apflora.v_apber_b2lpop AS
  type apflora (line 4266) | CREATE VIEW apflora.v_apber_b2ltpop AS
  type apflora (line 4279) | CREATE VIEW apflora.v_pop_letzterpopber0 AS
  type apflora (line 4292) | CREATE VIEW apflora.v_pop_letzterpopber AS
  type apflora (line 4302) | CREATE VIEW apflora.v_apber_b2rpop AS
  type apflora (line 4315) | CREATE VIEW apflora.v_tpop_letztertpopber0 AS
  type apflora (line 4329) | CREATE VIEW apflora.v_tpop_letztertpopber AS
  type apflora (line 4339) | CREATE VIEW apflora.v_apber_b2rtpop AS
  type apflora (line 4352) | CREATE VIEW apflora.v_apber_b3lpop AS
  type apflora (line 4365) | CREATE VIEW apflora.v_apber_b3ltpop AS
  type apflora (line 4378) | CREATE VIEW apflora.v_apber_b3rpop AS
  type apflora (line 4391) | CREATE VIEW apflora.v_apber_b3rtpop AS
  type apflora (line 4404) | CREATE VIEW apflora.v_apber_b4lpop AS
  type apflora (line 4417) | CREATE VIEW apflora.v_apber_b4ltpop AS
  type apflora (line 4430) | CREATE VIEW apflora.v_apber_b4rpop AS
  type apflora (line 4443) | CREATE VIEW apflora.v_apber_b4rtpop AS
  type apflora (line 4456) | CREATE VIEW apflora.v_apber_b5lpop AS
  type apflora (line 4469) | CREATE VIEW apflora.v_apber_b5ltpop AS
  type apflora (line 4482) | CREATE VIEW apflora.v_apber_b5rpop AS
  type apflora (line 4495) | CREATE VIEW apflora.v_apber_b5rtpop AS
  type apflora (line 4508) | CREATE VIEW apflora.v_apber_b6lpop AS
  type apflora (line 4521) | CREATE VIEW apflora.v_apber_b6ltpop AS
  type apflora (line 4534) | CREATE VIEW apflora.v_apber_b6rpop AS
  type apflora (line 4547) | CREATE VIEW apflora.v_apber_b6rtpop AS
  type apflora (line 4560) | CREATE VIEW apflora.v_apber_b7lpop AS
  type apflora (line 4571) | CREATE VIEW apflora.v_apber_b7ltpop AS
  type apflora (line 4582) | CREATE VIEW apflora.v_apber_c1lpop AS
  type apflora (line 4595) | CREATE VIEW apflora.v_apber_c1ltpop AS
  type apflora (line 4608) | CREATE VIEW apflora.v_apber_c1rpop AS
  type apflora (line 4621) | CREATE VIEW apflora.v_apber_c1rtpop AS
  type apflora (line 4634) | CREATE VIEW apflora.v_pop_letztermassnber0 AS
  type apflora (line 4648) | CREATE VIEW apflora.v_pop_letztermassnber AS
  type apflora (line 4658) | CREATE VIEW apflora.v_apber_c3rpop AS
  type apflora (line 4670) | CREATE VIEW apflora.v_tpop_letztermassnber0 AS
  type apflora (line 4684) | CREATE VIEW apflora.v_tpop_letztermassnber AS
  type apflora (line 4694) | CREATE VIEW apflora.v_apber_c3rtpop AS
  type apflora (line 4707) | CREATE VIEW apflora.v_apber_c4rpop AS
  type apflora (line 4719) | CREATE VIEW apflora.v_apber_c4rtpop AS
  type apflora (line 4732) | CREATE VIEW apflora.v_apber_c5rpop AS
  type apflora (line 4744) | CREATE VIEW apflora.v_apber_c5rtpop AS
  type apflora (line 4757) | CREATE VIEW apflora.v_apber_c6rpop AS
  type apflora (line 4769) | CREATE VIEW apflora.v_apber_c6rtpop AS
  type apflora (line 4782) | CREATE VIEW apflora.v_apber_c7rpop AS
  type apflora (line 4794) | CREATE VIEW apflora.v_apber_c7rtpop AS
  type apflora (line 4807) | CREATE VIEW apflora.v_erstemassnproap AS
  type apflora (line 4819) | CREATE VIEW apflora.v_apber_injahr AS
  type apflora (line 4840) | CREATE VIEW apflora.v_apber_pop_uebersicht AS
  type apflora (line 4868) | CREATE VIEW apflora.v_apber_uebe AS
  type apflora (line 4905) | CREATE VIEW apflora.v_apber_uebe_apid AS
  type apflora (line 4919) | CREATE VIEW apflora.v_apber_uebkm AS
  type apflora (line 4941) | CREATE VIEW apflora.v_apber_uebma AS
  type apflora (line 4955) | CREATE VIEW apflora.v_apber_uebma_apid AS
  type apflora (line 4967) | CREATE VIEW apflora.v_apber_uebme AS
  type apflora (line 5003) | CREATE VIEW apflora.v_apber_uebme_apid AS
  type apflora (line 5017) | CREATE VIEW apflora.v_apber_uebne_apid AS
  type apflora (line 5031) | CREATE VIEW apflora.v_apber_uebse_apid AS
  type apflora (line 5045) | CREATE VIEW apflora.v_apber_uebun_apid AS
  type apflora (line 5059) | CREATE VIEW apflora.v_apber_uebwe_apid AS
  type apflora (line 5073) | CREATE VIEW apflora.v_apber_uebnb AS
  type apflora (line 5091) | CREATE VIEW apflora.v_apber_uebnb00 AS
  type apflora (line 5105) | CREATE VIEW apflora.v_apber_uebnb000 AS
  type apflora (line 5118) | CREATE VIEW apflora.v_apber_uebnb0 AS
  type apflora (line 5130) | CREATE VIEW apflora.v_apber_uebne AS
  type apflora (line 5166) | CREATE VIEW apflora.v_apber_uebse AS
  type apflora (line 5202) | CREATE VIEW apflora.v_apber_uebun AS
  type apflora (line 5238) | CREATE VIEW apflora.v_apber_uebwe AS
  type apflora (line 5274) | CREATE VIEW apflora.v_apber_uet01 AS
  type apflora (line 5301) | CREATE VIEW apflora.v_apber_uet_veraengegenvorjahr AS
  type apflora (line 5313) | CREATE TABLE apflora.zielber (
  type apflora (line 5359) | CREATE VIEW apflora.v_apber_zielber AS
  type apflora (line 5374) | CREATE VIEW apflora.v_apbera1lpop AS
  type apflora (line 5385) | CREATE VIEW apflora.v_apbera1ltpop AS
  type apflora (line 5396) | CREATE VIEW apflora.v_assozart AS
  type apflora (line 5420) | CREATE VIEW apflora.v_auswapbearbmassninjahr0 AS
  type apflora (line 5458) | CREATE VIEW apflora.v_beob AS
  type apflora (line 5496) | CREATE VIEW apflora.v_beob__mit_data AS
  type apflora (line 5535) | CREATE VIEW apflora.v_ber AS
  type apflora (line 5560) | CREATE VIEW apflora.v_bertpopfuerangezeigteap0 AS
  type apflora (line 5592) | CREATE VIEW apflora.v_datenstruktur AS
  type apflora (line 5608) | CREATE VIEW apflora.v_erfkrit AS
  type apflora (line 5632) | CREATE VIEW apflora.v_exportevab_beob AS
  type apflora (line 5652) | CREATE VIEW apflora.v_tpopkontr_maxanzahl AS
  type apflora (line 5663) | CREATE VIEW apflora.v_exportevab_projekt AS
  type apflora (line 5696) | CREATE VIEW apflora.v_exportevab_raum AS
  type apflora (line 5729) | CREATE VIEW apflora.v_exportevab_ort AS
  type apflora (line 5778) | CREATE VIEW apflora.v_exportevab_zeit AS
  type apflora (line 5813) | CREATE VIEW apflora.v_idealbiotop AS
  type apflora (line 5853) | CREATE VIEW apflora.v_kontrzaehl_anzproeinheit AS
  type apflora (line 5957) | CREATE VIEW apflora.v_massn AS
  type apflora (line 6034) | CREATE VIEW apflora.v_massn_fuergis_read AS
  type apflora (line 6107) | CREATE VIEW apflora.v_massn_fuergis_write AS
  type apflora (line 6135) | CREATE VIEW apflora.v_massn_webgisbun AS
  type apflora (line 6183) | CREATE VIEW apflora.v_pop AS
  type apflora (line 6211) | CREATE VIEW apflora.v_pop_anzkontr AS
  type apflora (line 6241) | CREATE VIEW apflora.v_pop_anzmassn AS
  type apflora (line 6271) | CREATE VIEW apflora.v_tpop_berjahrundmassnjahr AS
  type apflora (line 6286) | CREATE VIEW apflora.v_pop_berjahrundmassnjahrvontpop AS
  type apflora (line 6296) | CREATE VIEW apflora.v_pop_berundmassnjahre AS
  type apflora (line 6311) | CREATE VIEW apflora.v_pop_fuergis_read AS
  type apflora (line 6340) | CREATE VIEW apflora.v_pop_fuergis_write AS
  type apflora (line 6358) | CREATE VIEW apflora.v_pop_kml AS
  type apflora (line 6374) | CREATE VIEW apflora.v_pop_kmlnamen AS
  type apflora (line 6390) | CREATE VIEW apflora.v_pop_letzterpopber0_overall AS
  type apflora (line 6400) | CREATE VIEW apflora.v_pop_letzterpopber_overall AS
  type apflora (line 6413) | CREATE VIEW apflora.v_pop_letzterpopbermassn AS
  type apflora (line 6423) | CREATE VIEW apflora.v_pop_massnseitbeginnap AS
  type apflora (line 6435) | CREATE VIEW apflora.v_pop_mit_letzter_popber AS
  type apflora (line 6473) | CREATE VIEW apflora.v_pop_mit_letzter_popmassnber AS
  type apflora (line 6511) | CREATE VIEW apflora.v_pop_ohnekoord AS
  type apflora (line 6540) | CREATE VIEW apflora.v_pop_popberundmassnber AS
  type apflora (line 6587) | CREATE VIEW apflora.v_pop_vonapohnestatus AS
  type apflora (line 6604) | CREATE VIEW apflora.v_popber AS
  type apflora (line 6638) | CREATE VIEW apflora.v_popber_angezapbestjahr0 AS
  type apflora (line 6659) | CREATE VIEW apflora.v_popmassnber AS
  type apflora (line 6695) | CREATE VIEW apflora.v_popmassnber_anzmassn0 AS
  type apflora (line 6709) | CREATE VIEW apflora.v_popmassnber_anzmassn AS
  type apflora (line 6747) | CREATE VIEW apflora.v_q_ziel_ohnejahr AS
  type apflora (line 6760) | CREATE VIEW apflora.v_q_ziel_ohnetyp AS
  type apflora (line 6774) | CREATE VIEW apflora.v_q_ziel_ohneziel AS
  type apflora (line 6788) | CREATE VIEW apflora.v_qk_apber_ohnebeurteilung AS
  type apflora (line 6803) | CREATE VIEW apflora.v_qk_apber_ohnejahr AS
  type apflora (line 6814) | CREATE VIEW apflora.v_qk_apber_ohnevergleichvorjahrgesamtziel AS
  type apflora (line 6829) | CREATE VIEW apflora.v_qk_assozart_ohneart AS
  type apflora (line 6843) | CREATE VIEW apflora.v_qk_erfkrit_ohnebeurteilung AS
  type apflora (line 6857) | CREATE VIEW apflora.v_qk_erfkrit_ohnekriterien AS
  type apflora (line 6871) | CREATE VIEW apflora.v_qk_feldkontr_ohnebearb AS
  type apflora (line 6887) | CREATE VIEW apflora.v_qk_feldkontr_ohnejahr AS
  type apflora (line 6903) | CREATE VIEW apflora.v_qk_feldkontr_ohnetyp AS
  type apflora (line 6920) | CREATE VIEW apflora.v_qk_feldkontr_ohnezaehlung AS
  type apflora (line 6932) | CREATE VIEW apflora.v_qk_feldkontrzaehlung_ohneanzahl AS
  type apflora (line 6950) | CREATE VIEW apflora.v_qk_feldkontrzaehlung_ohneeinheit AS
  type apflora (line 6968) | CREATE VIEW apflora.v_qk_feldkontrzaehlung_ohnemethode AS
  type apflora (line 6986) | CREATE VIEW apflora.v_qk_freiwkontr_ohnebearb AS
  type apflora (line 7002) | CREATE VIEW apflora.v_qk_freiwkontr_ohnejahr AS
  type apflora (line 7018) | CREATE VIEW apflora.v_qk_freiwkontr_ohnezaehlung AS
  type apflora (line 7030) | CREATE VIEW apflora.v_qk_freiwkontrzaehlung_ohneanzahl AS
  type apflora (line 7048) | CREATE VIEW apflora.v_qk_freiwkontrzaehlung_ohneeinheit AS
  type apflora (line 7066) | CREATE VIEW apflora.v_qk_freiwkontrzaehlung_ohnemethode AS
  type apflora (line 7084) | CREATE VIEW apflora.v_qk_massn_ohnebearb AS
  type apflora (line 7100) | CREATE VIEW apflora.v_qk_massn_ohnejahr AS
  type apflora (line 7116) | CREATE VIEW apflora.v_qk_massn_ohnetyp AS
  type apflora (line 7133) | CREATE VIEW apflora.v_qk_massnber_ohneerfbeurt AS
  type apflora (line 7150) | CREATE VIEW apflora.v_qk_massnber_ohnejahr AS
  type apflora (line 7166) | CREATE VIEW apflora.v_qk_pop_koordentsprechenkeinertpop AS
  type apflora (line 7184) | CREATE VIEW apflora.v_qk_pop_mit_ber_abnehmend_ohne_tpopber_abnehmend AS
  type apflora (line 7204) | CREATE VIEW apflora.v_qk_pop_mit_ber_erloschen_ohne_tpopber_erloschen AS
  type apflora (line 7224) | CREATE VIEW apflora.v_qk_pop_mit_ber_erloschen_und_tpopber_nicht_erlosch...
  type apflora (line 7244) | CREATE VIEW apflora.v_qk_pop_mit_ber_zunehmend_ohne_tpopber_zunehmend AS
  type apflora (line 7264) | CREATE VIEW apflora.v_qk_pop_mitstatusunklarohnebegruendung AS
  type apflora (line 7278) | CREATE VIEW apflora.v_qk_pop_ohnebekanntseit AS
  type apflora (line 7292) | CREATE VIEW apflora.v_qk_pop_ohnekoord AS
  type apflora (line 7306) | CREATE VIEW apflora.v_qk_pop_ohnepopname AS
  type apflora (line 7320) | CREATE VIEW apflora.v_qk_pop_ohnepopnr AS
  type apflora (line 7334) | CREATE VIEW apflora.v_qk_pop_ohnepopstatus AS
  type apflora (line 7348) | CREATE VIEW apflora.v_qk_pop_ohnetpop AS
  type apflora (line 7363) | CREATE VIEW apflora.v_qk_pop_ohnetpopmitgleichemstatus AS
  type apflora (line 7379) | CREATE VIEW apflora.v_qk_pop_popnrmehrdeutig AS
  type apflora (line 7400) | CREATE VIEW apflora.v_qk_pop_status101tpopstatusanders AS
  type apflora (line 7416) | CREATE VIEW apflora.v_qk_pop_status200tpopstatusunzulaessig AS
  type apflora (line 7432) | CREATE VIEW apflora.v_qk_pop_status201tpopstatusunzulaessig AS
  type apflora (line 7448) | CREATE VIEW apflora.v_qk_pop_status202tpopstatusanders AS
  type apflora (line 7464) | CREATE VIEW apflora.v_qk_pop_status210tpopstatusunzulaessig AS
  type apflora (line 7480) | CREATE VIEW apflora.v_qk_pop_status211tpopstatusunzulaessig AS
  type apflora (line 7496) | CREATE VIEW apflora.v_qk_pop_status300tpopstatusanders AS
  type apflora (line 7512) | CREATE VIEW apflora.v_qk_pop_statusaktuellletzterpopbererloschen AS
  type apflora (line 7538) | CREATE VIEW apflora.v_qk_pop_statusangesiedeltmittpopurspruenglich AS
  type apflora (line 7553) | CREATE VIEW apflora.v_qk_pop_statusansaatversuchalletpoperloschen AS
  type apflora (line 7571) | CREATE VIEW apflora.v_qk_pop_statusansaatversuchmitaktuellentpop AS
  type apflora (line 7586) | CREATE VIEW apflora.v_qk_pop_statusansaatversuchmittpopursprerloschen AS
  type apflora (line 7601) | CREATE VIEW apflora.v_qk_pop_statuserloschenletzterpopberabnehmend AS
  type apflora (line 7627) | CREATE VIEW apflora.v_qk_pop_statuserloschenletzterpopberaktuell AS
  type apflora (line 7643) | CREATE VIEW apflora.v_qk_pop_statuserloschenletzterpopbererloschenmitans...
  type apflora (line 7669) | CREATE VIEW apflora.v_qk_pop_statuserloschenletzterpopberstabil AS
  type apflora (line 7695) | CREATE VIEW apflora.v_qk_pop_statuserloschenletzterpopberunsicher AS
  type apflora (line 7721) | CREATE VIEW apflora.v_qk_pop_statuserloschenletzterpopberzunehmend AS
  type apflora (line 7747) | CREATE VIEW apflora.v_qk_pop_statuserloschenmittpopaktuell AS
  type apflora (line 7762) | CREATE VIEW apflora.v_qk_pop_statuserloschenmittpopansaatversuch AS
  type apflora (line 7777) | CREATE VIEW apflora.v_qk_pop_statuspotwuchsortmittpopanders AS
  type apflora (line 7792) | CREATE VIEW apflora.v_qk_popber_ohneentwicklung AS
  type apflora (line 7808) | CREATE VIEW apflora.v_qk_popber_ohnejahr AS
  type apflora (line 7823) | CREATE VIEW apflora.v_qk_popmassnber_ohneentwicklung AS
  type apflora (line 7839) | CREATE VIEW apflora.v_qk_popmassnber_ohnejahr AS
  type apflora (line 7854) | CREATE VIEW apflora.v_qk_tpop_erloschenundrelevantaberletztebeobvor1950_...
  type apflora (line 7864) | CREATE VIEW apflora.v_qk_tpop_erloschenundrelevantaberletztebeobvor1950 AS
  type apflora (line 7885) | CREATE VIEW apflora.v_qk_tpop_mitstatusaktuellundtpopbererloschen_maxtpo...
  type apflora (line 7894) | CREATE VIEW apflora.v_tpopkontr_letztesjahr AS
  type apflora (line 7906) | CREATE VIEW apflora.v_tpopkontr_letzteid AS
  type apflora (line 7917) | CREATE VIEW apflora.v_qk_tpop_mitstatusansaatversuchundzaehlungmitanzahl AS
  type apflora (line 7937) | CREATE VIEW apflora.v_qk_tpop_mitstatuspotentiellundmassnansiedlung AS
  type apflora (line 7955) | CREATE VIEW apflora.v_qk_tpop_mitstatuspotentiellundzaehlungmitanzahl AS
  type apflora (line 7976) | CREATE VIEW apflora.v_qk_tpop_mitstatusunklarohnebegruendung AS
  type apflora (line 7991) | CREATE VIEW apflora.v_qk_tpop_ohneapberrelevant AS
  type apflora (line 8006) | CREATE VIEW apflora.v_qk_tpop_ohnebekanntseit AS
  type apflora (line 8020) | CREATE VIEW apflora.v_qk_tpop_ohneflurname AS
  type apflora (line 8035) | CREATE VIEW apflora.v_qk_tpop_ohnekoordinaten AS
  type apflora (line 8050) | CREATE VIEW apflora.v_qk_tpop_ohnenr AS
  type apflora (line 8065) | CREATE VIEW apflora.v_qk_tpop_ohnestatus AS
  type apflora (line 8080) | CREATE VIEW apflora.v_qk_tpop_popnrtpopnrmehrdeutig AS
  type apflora (line 8102) | CREATE VIEW apflora.v_qk_tpop_statusaktuellletztertpopbererloschen AS
  type apflora (line 8128) | CREATE VIEW apflora.v_tpop_letztertpopber0_overall AS
  type apflora (line 8138) | CREATE VIEW apflora.v_qk_tpop_statuserloschenletzterpopberaktuell AS
  type apflora (line 8156) | CREATE VIEW apflora.v_qk_tpop_statuserloschenletztertpopberabnehmend AS
  type apflora (line 8182) | CREATE VIEW apflora.v_qk_tpop_statuserloschenletztertpopbererloschenmita...
  type apflora (line 8208) | CREATE VIEW apflora.v_qk_tpop_statuserloschenletztertpopberstabil AS
  type apflora (line 8234) | CREATE VIEW apflora.v_qk_tpop_statuserloschenletztertpopberunsicher AS
  type apflora (line 8260) | CREATE VIEW apflora.v_qk_tpop_statuserloschenletztertpopberzunehmend AS
  type apflora (line 8286) | CREATE VIEW apflora.v_qk_tpop_statuspotentiellfuerapberrelevant AS
  type apflora (line 8301) | CREATE VIEW apflora.v_qk_tpopber_ohneentwicklung AS
  type apflora (line 8318) | CREATE VIEW apflora.v_qk_tpopber_ohnejahr AS
  type apflora (line 8334) | CREATE VIEW apflora.v_qk_ziel_ohnejahr AS
  type apflora (line 8348) | CREATE VIEW apflora.v_qk_ziel_ohnetyp AS
  type apflora (line 8362) | CREATE VIEW apflora.v_qk_ziel_ohneziel AS
  type apflora (line 8376) | CREATE VIEW apflora.v_qk_zielber_ohneentwicklung AS
  type apflora (line 8392) | CREATE VIEW apflora.v_qk_zielber_ohnejahr AS
  type apflora (line 8407) | CREATE VIEW apflora.v_tpop AS
  type apflora (line 8464) | CREATE VIEW apflora.v_tpop_letztekontrid AS
  type apflora (line 8474) | CREATE VIEW apflora.v_tpopkontr AS
  type apflora (line 8579) | CREATE VIEW apflora.v_tpop_anzkontrinklletzter AS
  type apflora (line 8674) | CREATE VIEW apflora.v_tpopber_letzteid AS
  type apflora (line 8691) | CREATE VIEW apflora.v_tpopber_mitletzterid AS
  type apflora (line 8707) | CREATE VIEW apflora.v_tpop_anzkontrinklletzterundletztertpopber AS
  type apflora (line 8808) | CREATE VIEW apflora.v_tpop_anzmassn AS
  type apflora (line 8863) | CREATE VIEW apflora.v_tpop_for_ap AS
  type apflora (line 8900) | CREATE VIEW apflora.v_tpop_fuergis_read AS
  type apflora (line 8952) | CREATE VIEW apflora.v_tpop_fuergis_write AS
  type apflora (line 8985) | CREATE VIEW apflora.v_tpop_kml AS
  type apflora (line 9002) | CREATE VIEW apflora.v_tpop_kmlnamen AS
  type apflora (line 9019) | CREATE VIEW apflora.v_tpop_kontrjahrundberjahrundmassnjahr AS
  type apflora (line 9039) | CREATE VIEW apflora.v_tpop_mitapaberohnestatus AS
  type apflora (line 9060) | CREATE VIEW apflora.v_tpop_ohneapberichtrelevant AS
  type apflora (line 9079) | CREATE VIEW apflora.v_tpop_ohnebekanntseit AS
  type apflora (line 9099) | CREATE VIEW apflora.v_tpop_ohnekoord AS
  type apflora (line 9120) | CREATE VIEW apflora.v_tpop_popberundmassnber AS
  type apflora (line 9188) | CREATE VIEW apflora.v_tpopber_letzterber AS
  type apflora (line 9197) | CREATE VIEW apflora.v_tpop_statuswidersprichtbericht AS
  type apflora (line 9221) | CREATE VIEW apflora.v_tpop_webgisbun AS
  type apflora (line 9278) | CREATE VIEW apflora.v_tpopber AS
  type apflora (line 9337) | CREATE VIEW apflora.v_tpopkontr_fuergis_read AS
  type apflora (line 9412) | CREATE VIEW apflora.v_tpopkontr_fuergis_write AS
  type apflora (line 9460) | CREATE VIEW apflora.v_tpopkontr_webgisbun AS
  type apflora (line 9539) | CREATE VIEW apflora.v_tpopkoord AS
  type apflora (line 9555) | CREATE VIEW apflora.v_tpopmassn_0 AS
  type apflora (line 9597) | CREATE VIEW apflora.v_tpopmassn_fueraktap0 AS
  type apflora (line 9664) | CREATE VIEW apflora.v_tpopmassnber AS
  type apflora (line 9723) | CREATE VIEW apflora.v_tpopmassnber_fueraktap0 AS
  type apflora (line 9772) | CREATE VIEW apflora.v_ziel AS
  type apflora (line 9796) | CREATE VIEW apflora.v_zielber AS
  type public (line 9854) | CREATE TABLE public.migrations (
  type apflora (line 10223) | CREATE INDEX "_variable_ApArtId_idx" ON apflora._variable USING btree ("...
  type apflora (line 10227) | CREATE INDEX "_variable_JBerJahr_idx" ON apflora._variable USING btree (...
  type apflora (line 10231) | CREATE INDEX "adb_eigenschaften_Artname_idx" ON apflora.ae_eigenschaften...
  type apflora (line 10235) | CREATE INDEX "adb_eigenschaften_TaxonomieId_idx" ON apflora.ae_eigenscha...
  type adb_eigenschaften_id_idx (line 10239) | CREATE INDEX adb_eigenschaften_id_idx ON apflora.ae_eigenschaften USING ...
  type apflora (line 10243) | CREATE INDEX "adb_lr_Id_idx" ON apflora.ae_lrdelarze USING btree (sort)
  type apflora (line 10247) | CREATE INDEX "adb_lr_Label_idx" ON apflora.ae_lrdelarze USING btree (label)
  type adb_lr_id_idx (line 10251) | CREATE INDEX adb_lr_id_idx ON apflora.ae_lrdelarze USING btree (id)
  type adresse_freiw_erfko_idx (line 10255) | CREATE INDEX adresse_freiw_erfko_idx ON apflora.adresse USING btree (fre...
  type adresse_id_idx (line 10259) | CREATE INDEX adresse_id_idx ON apflora.adresse USING btree (id)
  type adresse_name_idx (line 10263) | CREATE INDEX adresse_name_idx ON apflora.adresse USING btree (name)
  type ap_art_id_idx (line 10267) | CREATE INDEX ap_art_id_idx ON apflora.ap USING btree (art_id)
  type ap_bearbeiter_idx (line 10271) | CREATE INDEX ap_bearbeiter_idx ON apflora.ap USING btree (bearbeiter)
  type ap_bearbeitung_idx (line 10275) | CREATE INDEX ap_bearbeitung_idx ON apflora.ap USING btree (bearbeitung)
  type apflora (line 10279) | CREATE INDEX "ap_bearbstand_werte_DomainCode_idx" ON apflora.ap_bearbsta...
  type apflora (line 10283) | CREATE INDEX "ap_bearbstand_werte_DomainOrd_idx" ON apflora.ap_bearbstan...
  type ap_bearbstand_werte_id_idx (line 10287) | CREATE INDEX ap_bearbstand_werte_id_idx ON apflora.ap_bearbstand_werte U...
  type apflora (line 10291) | CREATE INDEX "ap_erfbeurtkrit_werte_DomainCode_idx" ON apflora.ap_erfbeu...
  type apflora (line 10295) | CREATE INDEX "ap_erfbeurtkrit_werte_DomainOrd_idx" ON apflora.ap_erfbeur...
  type ap_erfbeurtkrit_werte_id_idx (line 10299) | CREATE INDEX ap_erfbeurtkrit_werte_id_idx ON apflora.ap_erfbeurtkrit_wer...
  type apflora (line 10303) | CREATE INDEX "ap_erfkrit_werte_BeurteilId_idx" ON apflora.ap_erfkrit_wer...
  type apflora (line 10307) | CREATE INDEX "ap_erfkrit_werte_BeurteilOrd_idx" ON apflora.ap_erfkrit_we...
  type ap_erfkrit_werte_id_idx (line 10311) | CREATE INDEX ap_erfkrit_werte_id_idx ON apflora.ap_erfkrit_werte USING b...
  type ap_id_idx (line 10315) | CREATE INDEX ap_id_idx ON apflora.ap USING btree (id)
  type ap_proj_id_idx (line 10319) | CREATE INDEX ap_proj_id_idx ON apflora.ap USING btree (proj_id)
  type ap_start_jahr_idx (line 10323) | CREATE INDEX ap_start_jahr_idx ON apflora.ap USING btree (start_jahr)
  type ap_umsetzung_idx (line 10327) | CREATE INDEX ap_umsetzung_idx ON apflora.ap USING btree (umsetzung)
  type apflora (line 10331) | CREATE INDEX "ap_umsetzung_werte_DomainCode_idx" ON apflora.ap_umsetzung...
  type apflora (line 10335) | CREATE INDEX "ap_umsetzung_werte_DomainOrd_idx" ON apflora.ap_umsetzung_...
  type ap_umsetzung_werte_id_idx (line 10339) | CREATE INDEX ap_umsetzung_werte_id_idx ON apflora.ap_umsetzung_werte USI...
  type apart_ap_id_idx (line 10343) | CREATE INDEX apart_ap_id_idx ON apflora.apart USING btree (ap_id)
  type apart_art_id_idx (line 10347) | CREATE INDEX apart_art_id_idx ON apflora.apart USING btree (art_id)
  type apber_ap_id_idx (line 10351) | CREATE INDEX apber_ap_id_idx ON apflora.apber USING btree (ap_id)
  type apber_bearbeiter_idx (line 10355) | CREATE INDEX apber_bearbeiter_idx ON apflora.apber USING btree (bearbeiter)
  type apber_beurteilung_idx (line 10359) | CREATE INDEX apber_beurteilung_idx ON apflora.apber USING btree (beurtei...
  type apber_id_idx (line 10363) | CREATE INDEX apber_id_idx ON apflora.apber USING btree (id)
  type apber_jahr_idx (line 10367) | CREATE INDEX apber_jahr_idx ON apflora.apber USING btree (jahr)
  type apberuebersicht_id_idx (line 10371) | CREATE INDEX apberuebersicht_id_idx ON apflora.apberuebersicht USING btr...
  type apberuebersicht_jahr_idx (line 10375) | CREATE INDEX apberuebersicht_jahr_idx ON apflora.apberuebersicht USING b...
  type apberuebersicht_proj_id_idx (line 10379) | CREATE INDEX apberuebersicht_proj_id_idx ON apflora.apberuebersicht USIN...
  type assozart_ae_id_idx (line 10383) | CREATE INDEX assozart_ae_id_idx ON apflora.assozart USING btree (ae_id)
  type assozart_ap_id_idx (line 10387) | CREATE INDEX assozart_ap_id_idx ON apflora.assozart USING btree (ap_id)
  type assozart_id_idx (line 10391) | CREATE INDEX assozart_id_idx ON apflora.assozart USING btree (id)
  type beob_art_id_idx (line 10395) | CREATE INDEX beob_art_id_idx ON apflora.beob USING btree (art_id)
  type beob_id_idx (line 10399) | CREATE INDEX beob_id_idx ON apflora.beob USING btree (id)
  type beob_nicht_zuordnen_idx (line 10403) | CREATE INDEX beob_nicht_zuordnen_idx ON apflora.beob USING btree (nicht_...
  type beob_quelle_id_idx (line 10407) | CREATE INDEX beob_quelle_id_idx ON apflora.beob USING btree (quelle_id)
  type beob_quelle_werte_id_idx (line 10411) | CREATE INDEX beob_quelle_werte_id_idx ON apflora.beob_quelle_werte USING...
  type beob_tpop_id_idx (line 10415) | CREATE INDEX beob_tpop_id_idx ON apflora.beob USING btree (tpop_id)
  type beob_x_idx (line 10419) | CREATE INDEX beob_x_idx ON apflora.beob USING btree (x)
  type beob_y_idx (line 10423) | CREATE INDEX beob_y_idx ON apflora.beob USING btree (y)
  type beobart_id_idx (line 10427) | CREATE INDEX beobart_id_idx ON apflora.apart USING btree (id)
  type ber_ap_id_idx (line 10431) | CREATE INDEX ber_ap_id_idx ON apflora.ber USING btree (ap_id)
  type ber_id_idx (line 10435) | CREATE INDEX ber_id_idx ON apflora.ber USING btree (id)
  type ber_jahr_idx (line 10439) | CREATE INDEX ber_jahr_idx ON apflora.ber USING btree (jahr)
  type erfkrit_ap_id_idx (line 10443) | CREATE INDEX erfkrit_ap_id_idx ON apflora.erfkrit USING btree (ap_id)
  type erfkrit_erfolg_idx (line 10447) | CREATE INDEX erfkrit_erfolg_idx ON apflora.erfkrit USING btree (erfolg)
  type erfkrit_id_idx (line 10451) | CREATE INDEX erfkrit_id_idx ON apflora.erfkrit USING btree (id)
  type idealbiotop_ap_id_idx (line 10455) | CREATE INDEX idealbiotop_ap_id_idx ON apflora.idealbiotop USING btree (a...
  type idealbiotop_id_idx (line 10459) | CREATE INDEX idealbiotop_id_idx ON apflora.idealbiotop USING btree (id)
  type message_id_idx (line 10463) | CREATE INDEX message_id_idx ON apflora.message USING btree (id)
  type message_time_idx (line 10467) | CREATE INDEX message_time_idx ON apflora.message USING btree ("time")
  type pop_ap_id_idx (line 10471) | CREATE INDEX pop_ap_id_idx ON apflora.pop USING btree (ap_id)
  type pop_bekannt_seit_idx (line 10475) | CREATE INDEX pop_bekannt_seit_idx ON apflora.pop USING btree (bekannt_seit)
  type pop_id_idx (line 10479) | CREATE INDEX pop_id_idx ON apflora.pop USING btree (id)
  type pop_name_idx (line 10483) | CREATE INDEX pop_name_idx ON apflora.pop USING btree (name)
  type pop_nr_idx (line 10487) | CREATE INDEX pop_nr_idx ON apflora.pop USING btree (nr)
  type pop_status_idx (line 10491) | CREATE INDEX pop_status_idx ON apflora.pop USING btree (status)
  type apflora (line 10495) | CREATE INDEX "pop_status_werte_HerkunftId_idx" ON apflora.pop_status_wer...
  type apflora (line 10499) | CREATE INDEX "pop_status_werte_HerkunftOrd_idx" ON apflora.pop_status_we...
  type apflora (line 10503) | CREATE INDEX "pop_status_werte_HerkunftTxt_idx" ON apflora.pop_status_we...
  type pop_status_werte_id_idx (line 10507) | CREATE INDEX pop_status_werte_id_idx ON apflora.pop_status_werte USING b...
  type pop_x_idx (line 10511) | CREATE INDEX pop_x_idx ON apflora.pop USING btree (x)
  type pop_y_idx (line 10515) | CREATE INDEX pop_y_idx ON apflora.pop USING btree (y)
  type popber_entwicklung_idx (line 10519) | CREATE INDEX popber_entwicklung_idx ON apflora.popber USING btree (entwi...
  type popber_id_idx (line 10523) | CREATE INDEX popber_id_idx ON apflora.popber USING btree (id)
  type popber_jahr_idx (line 10527) | CREATE INDEX popber_jahr_idx ON apflora.popber USING btree (jahr)
  type popber_pop_id_idx (line 10531) | CREATE INDEX popber_pop_id_idx ON apflora.popber USING btree (pop_id)
  type popmassnber_beurteilung_idx (line 10535) | CREATE INDEX popmassnber_beurteilung_idx ON apflora.popmassnber USING bt...
  type popmassnber_id_idx (line 10539) | CREATE INDEX popmassnber_id_idx ON apflora.popmassnber USING btree (id)
  type popmassnber_jahr_idx (line 10543) | CREATE INDEX popmassnber_jahr_idx ON apflora.popmassnber USING btree (jahr)
  type popmassnber_pop_id_idx (line 10547) | CREATE INDEX popmassnber_pop_id_idx ON apflora.popmassnber USING btree (...
  type projekt_id_idx (line 10551) | CREATE INDEX projekt_id_idx ON apflora.projekt USING btree (id)
  type projekt_name_idx (line 10555) | CREATE INDEX projekt_name_idx ON apflora.projekt USING btree (name)
  type tpop_apber_relevant_idx (line 10559) | CREATE INDEX tpop_apber_relevant_idx ON apflora.tpop USING btree (apber_...
  type apflora (line 10563) | CREATE INDEX "tpop_apberrelevant_werte_DomainCode_idx" ON apflora.tpop_a...
  type apflora (line 10567) | CREATE INDEX "tpop_apberrelevant_werte_DomainTxt_idx" ON apflora.tpop_ap...
  type tpop_apberrelevant_werte_id_idx (line 10571) | CREATE INDEX tpop_apberrelevant_werte_id_idx ON apflora.tpop_apberreleva...
  type apflora (line 10575) | CREATE INDEX "tpop_entwicklung_werte_EntwicklungCode_idx" ON apflora.tpo...
  type apflora (line 10579) | CREATE INDEX "tpop_entwicklung_werte_EntwicklungOrd_idx" ON apflora.tpop...
  type tpop_entwicklung_werte_id_idx (line 10583) | CREATE INDEX tpop_entwicklung_werte_id_idx ON apflora.tpop_entwicklung_w...
  type tpop_flurname_idx (line 10587) | CREATE INDEX tpop_flurname_idx ON apflora.tpop USING btree (flurname)
  type tpop_id_idx (line 10591) | CREATE INDEX tpop_id_idx ON apflora.tpop USING btree (id)
  type tpop_nr_idx (line 10595) | CREATE INDEX tpop_nr_idx ON apflora.tpop USING btree (nr)
  type tpop_pop_id_idx (line 10599) | CREATE INDEX tpop_pop_id_idx ON apflora.tpop USING btree (pop_id)
  type tpop_status_idx (line 10603) | CREATE INDEX tpop_status_idx ON apflora.tpop USING btree (status)
  type tpop_x_idx (line 10607) | CREATE INDEX tpop_x_idx ON apflora.tpop USING btree (x)
  type tpop_y_idx (line 10611) | CREATE INDEX tpop_y_idx ON apflora.tpop USING btree (y)
  type tpopber_entwicklung_idx (line 10615) | CREATE INDEX tpopber_entwicklung_idx ON apflora.tpopber USING btree (ent...
  type tpopber_id_idx (line 10619) | CREATE INDEX tpopber_id_idx ON apflora.tpopber USING btree (id)
  type tpopber_jahr_idx (line 10623) | CREATE INDEX tpopber_jahr_idx ON apflora.tpopber USING btree (jahr)
  type tpopber_tpop_id_idx (line 10627) | CREATE INDEX tpopber_tpop_id_idx ON apflora.tpopber USING btree (tpop_id)
  type tpopkontr_bearbeiter_idx (line 10631) | CREATE INDEX tpopkontr_bearbeiter_idx ON apflora.tpopkontr USING btree (...
  type tpopkontr_datum_idx (line 10635) | CREATE INDEX tpopkontr_datum_idx ON apflora.tpopkontr USING btree (datum)
  type tpopkontr_entwicklung_idx (line 10639) | CREATE INDEX tpopkontr_entwicklung_idx ON apflora.tpopkontr USING btree ...
  type tpopkontr_id_idx (line 10643) | CREATE INDEX tpopkontr_id_idx ON apflora.tpopkontr USING btree (id)
  type tpopkontr_idbiotuebereinst_werte_code_idx (line 10647) | CREATE INDEX tpopkontr_idbiotuebereinst_werte_code_idx ON apflora.tpopko...
  type tpopkontr_idbiotuebereinst_werte_id_idx (line 10651) | CREATE INDEX tpopkontr_idbiotuebereinst_werte_id_idx ON apflora.tpopkont...
  type tpopkontr_idbiotuebereinst_werte_sort_idx (line 10655) | CREATE INDEX tpopkontr_idbiotuebereinst_werte_sort_idx ON apflora.tpopko...
  type tpopkontr_idealbiotop_uebereinstimmung_idx (line 10659) | CREATE INDEX tpopkontr_idealbiotop_uebereinstimmung_idx ON apflora.tpopk...
  type tpopkontr_jahr_idx (line 10663) | CREATE INDEX tpopkontr_jahr_idx ON apflora.tpopkontr USING btree (jahr)
  type tpopkontr_tpop_id_idx (line 10667) | CREATE INDEX tpopkontr_tpop_id_idx ON apflora.tpopkontr USING btree (tpo...
  type tpopkontr_typ_idx (line 10671) | CREATE INDEX tpopkontr_typ_idx ON apflora.tpopkontr USING btree (typ)
  type tpopkontr_typ_werte_id_idx (line 10675) | CREATE INDEX tpopkontr_typ_werte_id_idx ON apflora.tpopkontr_typ_werte U...
  type tpopkontr_zeit_id_idx (line 10679) | CREATE UNIQUE INDEX tpopkontr_zeit_id_idx ON apflora.tpopkontr USING btr...
  type tpopkontrzaehl_anzahl_idx (line 10683) | CREATE INDEX tpopkontrzaehl_anzahl_idx ON apflora.tpopkontrzaehl USING b...
  type tpopkontrzaehl_einheit_idx (line 10687) | CREATE INDEX tpopkontrzaehl_einheit_idx ON apflora.tpopkontrzaehl USING ...
  type tpopkontrzaehl_einheit_werte_code_idx (line 10691) | CREATE INDEX tpopkontrzaehl_einheit_werte_code_idx ON apflora.tpopkontrz...
  type tpopkontrzaehl_einheit_werte_id_idx (line 10695) | CREATE INDEX tpopkontrzaehl_einheit_werte_id_idx ON apflora.tpopkontrzae...
  type tpopkontrzaehl_einheit_werte_sort_idx (line 10699) | CREATE INDEX tpopkontrzaehl_einheit_werte_sort_idx ON apflora.tpopkontrz...
  type tpopkontrzaehl_id_idx (line 10703) | CREATE INDEX tpopkontrzaehl_id_idx ON apflora.tpopkontrzaehl USING btree...
  type tpopkontrzaehl_methode_idx (line 10707) | CREATE INDEX tpopkontrzaehl_methode_idx ON apflora.tpopkontrzaehl USING ...
  type tpopkontrzaehl_methode_werte_code_idx (line 10711) | CREATE INDEX tpopkontrzaehl_methode_werte_code_idx ON apflora.tpopkontrz...
  type tpopkontrzaehl_methode_werte_id_idx (line 10715) | CREATE INDEX tpopkontrzaehl_methode_werte_id_idx ON apflora.tpopkontrzae...
  type tpopkontrzaehl_methode_werte_sort_idx (line 10719) | CREATE INDEX tpopkontrzaehl_methode_werte_sort_idx ON apflora.tpopkontrz...
  type tpopkontrzaehl_tpopkontr_id_idx2 (line 10723) | CREATE INDEX tpopkontrzaehl_tpopkontr_id_idx2 ON apflora.tpopkontrzaehl ...
  type tpopmassn_bearbeiter_idx (line 10727) | CREATE INDEX tpopmassn_bearbeiter_idx ON apflora.tpopmassn USING btree (...
  type tpopmassn_erfbeurt_werte_code_idx (line 10731) | CREATE INDEX tpopmassn_erfbeurt_werte_code_idx ON apflora.tpopmassn_erfb...
  type tpopmassn_erfbeurt_werte_id_idx (line 10735) | CREATE INDEX tpopmassn_erfbeurt_werte_id_idx ON apflora.tpopmassn_erfbeu...
  type tpopmassn_erfbeurt_werte_sort_idx (line 10739) | CREATE INDEX tpopmassn_erfbeurt_werte_sort_idx ON apflora.tpopmassn_erfb...
  type tpopmassn_id_idx (line 10743) | CREATE UNIQUE INDEX tpopmassn_id_idx ON apflora.tpopmassn USING btree (id)
  type tpopmassn_jahr_idx (line 10747) | CREATE INDEX tpopmassn_jahr_idx ON apflora.tpopmassn USING btree (jahr)
  type tpopmassn_tpop_id_idx (line 10751) | CREATE INDEX tpopmassn_tpop_id_idx ON apflora.tpopmassn USING btree (tpo...
  type tpopmassn_typ_idx (line 10755) | CREATE INDEX tpopmassn_typ_idx ON apflora.tpopmassn USING btree (typ)
  type tpopmassn_typ_werte_code_idx (line 10759) | CREATE INDEX tpopmassn_typ_werte_code_idx ON apflora.tpopmassn_typ_werte...
  type tpopmassn_typ_werte_id_idx (line 10763) | CREATE INDEX tpopmassn_typ_werte_id_idx ON apflora.tpopmassn_typ_werte U...
  type tpopmassn_typ_werte_sort_idx (line 10767) | CREATE INDEX tpopmassn_typ_werte_sort_idx ON apflora.tpopmassn_typ_werte...
  type tpopmassnber_beurteilung_idx (line 10771) | CREATE INDEX tpopmassnber_beurteilung_idx ON apflora.tpopmassnber USING ...
  type tpopmassnber_id_idx (line 10775) | CREATE INDEX tpopmassnber_id_idx ON apflora.tpopmassnber USING btree (id)
  type tpopmassnber_jahr_idx (line 10779) | CREATE INDEX tpopmassnber_jahr_idx ON apflora.tpopmassnber USING btree (...
  type tpopmassnber_tpop_id_idx (line 10783) | CREATE INDEX tpopmassnber_tpop_id_idx ON apflora.tpopmassnber USING btre...
  type user_id_idx (line 10787) | CREATE INDEX user_id_idx ON apflora."user" USING btree (id)
  type user_name_idx (line 10791) | CREATE INDEX user_name_idx ON apflora."user" USING btree (name)
  type usermessage_id_idx (line 10795) | CREATE INDEX usermessage_id_idx ON apflora.usermessage USING btree (id)
  type usermessage_message_id_idx (line 10799) | CREATE INDEX usermessage_message_id_idx ON apflora.usermessage USING btr...
  type usermessage_user_name_idx (line 10803) | CREATE INDEX usermessage_user_name_idx ON apflora.usermessage USING btre...
  type ziel_ap_id_idx (line 10807) | CREATE INDEX ziel_ap_id_idx ON apflora.ziel USING btree (ap_id)
  type ziel_id_idx (line 10811) | CREATE INDEX ziel_id_idx ON apflora.ziel USING btree (id)
  type ziel_jahr_idx (line 10815) | CREATE INDEX ziel_jahr_idx ON apflora.ziel USING btree (jahr)
  type ziel_typ_idx (line 10819) | CREATE INDEX ziel_typ_idx ON apflora.ziel USING btree (typ)
  type ziel_typ_werte_code_idx (line 10823) | CREATE INDEX ziel_typ_werte_code_idx ON apflora.ziel_typ_werte USING btr...
  type ziel_typ_werte_id_idx (line 10827) | CREATE INDEX ziel_typ_werte_id_idx ON apflora.ziel_typ_werte USING btree...
  type ziel_typ_werte_sort_idx (line 10831) | CREATE INDEX ziel_typ_werte_sort_idx ON apflora.ziel_typ_werte USING btr...
  type zielber_id_idx (line 10835) | CREATE INDEX zielber_id_idx ON apflora.zielber USING btree (id)
  type zielber_jahr_idx (line 10839) | CREATE INDEX zielber_jahr_idx ON apflora.zielber USING btree (jahr)
  type zielber_ziel_id_idx (line 10843) | CREATE INDEX zielber_ziel_id_idx ON apflora.zielber USING btree (ziel_id)
  type apflora (line 10847) | CREATE OR REPLACE VIEW apflora.v_exportevab_beob AS
  type apflora (line 10906) | CREATE OR REPLACE VIEW apflora.v_qk_apber_ohnejahr AS
  type apflora (line 10920) | CREATE OR REPLACE VIEW apflora.v_qk_feldkontr_ohnezaehlung AS
  type apflora (line 10938) | CREATE OR REPLACE VIEW apflora.v_qk_freiwkontr_ohnezaehlung AS

FILE: test/io/fixtures/db_config.sql
  function set_statement_timeout (line 116) | create function set_statement_timeout(role text, milliseconds int) retur...

FILE: test/io/fixtures/replica.sql
  function replica (line 3) | create or replace function replica.is_replica() returns bool as $$
  function replica (line 7) | create or replace function replica.get_replica_slot() returns name as $$
  type replica (line 11) | create table replica.items as select x as id from generate_series(1, 10) x

FILE: test/io/fixtures/schema.sql
  type projects (line 7) | CREATE TABLE projects AS SELECT FROM generate_series(1,5)
  type cats (line 8) | CREATE TABLE cats(id uuid primary key, name text)
  type items (line 9) | CREATE TABLE items AS SELECT x AS id FROM generate_series(1,5) x
  type directors (line 12) | CREATE TABLE directors (
  type films (line 17) | CREATE TABLE films (
  function get_guc_value (line 49) | create function get_guc_value(name text) returns text as $$
  function v1 (line 53) | create function v1.get_guc_value(name text) returns text as $$
  function uses_prepared_statements (line 57) | create function uses_prepared_statements() returns bool as $$
  function change_max_rows_config (line 61) | create function change_max_rows_config(val int, notify bool default fals...
  function reset_max_rows_config (line 71) | create function reset_max_rows_config() returns void as $_$
  function change_db_schema_and_full_reload (line 76) | create function change_db_schema_and_full_reload(schemas text) returns v...
  function v1 (line 85) | create function v1.reset_db_schema_config() returns void as $_$
  function invalid_role_claim_key_reload (line 92) | create function invalid_role_claim_key_reload() returns void as $_$
  function notify_do_nothing (line 98) | create function notify_do_nothing() returns void as $_$
  function sleep (line 116) | create or replace function sleep(seconds double precision) returns void ...
  function hello (line 120) | create or replace function hello() returns text as $$
  function drop_change_cats (line 124) | create function drop_change_cats() returns void
  function change_role_statement_timeout (line 133) | create function change_role_statement_timeout(timeout text) returns void...
  type items_w_isolation_level (line 140) | create view items_w_isolation_level as
  function default_isolation_level (line 146) | create function default_isolation_level()
  function serializable_isolation_level (line 152) | create function serializable_isolation_level()
  function repeatable_read_isolation_level (line 158) | create function repeatable_read_isolation_level()
  function create_function (line 164) | create or replace function create_function() returns void as $_$
  function migrate_function (line 172) | create or replace function migrate_function() returns void as $_$
  function get_pgrst_version (line 180) | create or replace function get_pgrst_version() returns text
  function terminate_pgrst (line 189) | create function terminate_pgrst(appname text) returns setof record as $$
  function one_sec_timeout (line 193) | create or replace function one_sec_timeout() returns void as $$
  function four_sec_timeout (line 197) | create or replace function four_sec_timeout() returns void as $$
  function get_postgres_version (line 201) | create function get_postgres_version() returns int as $$
  function rpc_work_mem (line 205) | create or replace function rpc_work_mem() returns items as $$
  function rpc_with_one_hoisted (line 210) | create or replace function rpc_with_one_hoisted() returns items as $$
  function rpc_with_two_hoisted (line 216) | create or replace function rpc_with_two_hoisted() returns items as $$
  function get_work_mem (line 222) | create function get_work_mem(items) returns text as $$
  function get_statement_timeout (line 226) | create function get_statement_timeout(items) returns text as $$
  function change_db_schemas_config (line 230) | create function change_db_schemas_config() returns void as $_$
  function reset_db_schemas_config (line 235) | create function reset_db_schemas_config() returns void as $_$
  function test (line 240) | create function test.get_current_schema() returns text as $$
  function root (line 244) | create or replace function root() returns json as $_$
  type infinite_recursion (line 248) | create view infinite_recursion as
  type infinite_recursion (line 251) | create or replace view infinite_recursion as
  function "true" (line 254) | create or replace function "true"() returns boolean as $_$

FILE: test/io/postgrest.py
  function sleep_until_postgrest_scache_reload (line 19) | def sleep_until_postgrest_scache_reload():
  function sleep_until_postgrest_config_reload (line 24) | def sleep_until_postgrest_config_reload():
  function sleep_until_postgrest_full_reload (line 29) | def sleep_until_postgrest_full_reload():
  class PostgrestTimedOut (line 34) | class PostgrestTimedOut(Exception):
  class PostgrestSession (line 38) | class PostgrestSession(requests_unixsocket.Session):
    method __init__ (line 41) | def __init__(self, baseurl, *args, **kwargs):
    method request (line 45) | def request(self, method, url, *args, **kwargs):
  class PostgrestProcess (line 53) | class PostgrestProcess:
    method read_stdout (line 61) | def read_stdout(self, nlines=1):
    method wait_until_scache_starts_loading (line 74) | def wait_until_scache_starts_loading(self, max_seconds=1):
  function run (line 83) | def run(
  function freeport (line 168) | def freeport(used_ports=None):
  function wait_until_exit (line 179) | def wait_until_exit(postgrest):
  function wait_until_status_code (line 187) | def wait_until_status_code(url, max_seconds, status_code):
  function sleep_pool_connection (line 207) | def sleep_pool_connection(url, seconds):
  function is_ipv6 (line 219) | def is_ipv6(addr):
  function set_statement_timeout (line 227) | def set_statement_timeout(postgrest, role, milliseconds):
  function reset_statement_timeout (line 239) | def reset_statement_timeout(postgrest, role):

FILE: test/io/test_auth.py
  function test_read_secret_from_file (line 24) | def test_read_secret_from_file(secretpath, defaultenv):
  function test_read_secret_from_stdin (line 41) | def test_read_secret_from_stdin(defaultenv):
  function test_read_secret_from_stdin_dbconfig (line 57) | def test_read_secret_from_stdin_dbconfig(defaultenv):
  function test_jwt_errors (line 70) | def test_jwt_errors(defaultenv):
  function test_fail_with_invalid_password (line 166) | def test_fail_with_invalid_password(defaultenv):
  function test_role_claim_key (line 178) | def test_role_claim_key(roleclaim, defaultenv):
  function test_jwt_aud_in_role_claim_key (line 197) | def test_jwt_aud_in_role_claim_key(jwtaudroleclaim, defaultenv):
  function test_iat_claim (line 214) | def test_iat_claim(defaultenv):
  function test_jwt_secret_reload (line 236) | def test_jwt_secret_reload(tmp_path, defaultenv):
  function test_jwt_secret_external_file_reload (line 260) | def test_jwt_secret_external_file_reload(tmp_path, defaultenv):
  function test_jwt_cache_server_timing (line 311) | def test_jwt_cache_server_timing(defaultenv):
  function test_jwt_cache_without_server_timing (line 347) | def test_jwt_cache_without_server_timing(defaultenv):
  function test_jwt_cache_without_exp_claim (line 368) | def test_jwt_cache_without_exp_claim(defaultenv):
  function test_invalidate_jwt_cache_when_secret_changes (line 395) | def test_invalidate_jwt_cache_when_secret_changes(tmp_path, defaultenv):

FILE: test/io/test_big_schema.py
  function test_schema_cache_load_max_duration (line 11) | def test_schema_cache_load_max_duration(defaultenv):
  function test_openapi_in_big_schema (line 46) | def test_openapi_in_big_schema(defaultenv):
  function test_stackoverflow_is_logged (line 60) | def test_stackoverflow_is_logged(defaultenv):
  function test_should_not_fail_with_stack_overflow (line 80) | def test_should_not_fail_with_stack_overflow(defaultenv):
  function test_second_request_for_non_existent_table_should_be_quick (line 97) | def test_second_request_for_non_existent_table_should_be_quick(defaultenv):

FILE: test/io/test_cli.py
  class ExtraNewLinesDumper (line 19) | class ExtraNewLinesDumper(yaml.SafeDumper):
    method write_line_break (line 22) | def write_line_break(self, data=None):
  function itemgetter (line 28) | def itemgetter(*items):
  class PostgrestError (line 44) | class PostgrestError(Exception):
  function cli (line 48) | def cli(args, env=None, stdin=None, expect_error=False):
  function dumpconfig (line 83) | def dumpconfig(configpath=None, env=None, stdin=None):
  function test_cli (line 98) | def test_cli(args, env, use_defaultenv, expect, defaultenv):
  function test_server_port_and_admin_port_same_value (line 119) | def test_server_port_and_admin_port_same_value(defaultenv):
  function test_expected_config (line 136) | def test_expected_config(expectedconfig):
  function test_expected_config_from_environment (line 151) | def test_expected_config_from_environment():
  function test_expected_config_from_db_settings (line 168) | def test_expected_config_from_db_settings(baseenv, role, expectedconfig):
  function test_stable_config (line 189) | def test_stable_config(tmp_path, config, defaultenv):
  function test_invalid_role_claim_key (line 221) | def test_invalid_role_claim_key(invalidroleclaimkey, defaultenv):
  function test_invalid_openapi_mode (line 233) | def test_invalid_openapi_mode(invalidopenapimodes, defaultenv):
  function test_schema_cache_snapshot (line 256) | def test_schema_cache_snapshot(baseenv, key, snapshot_yaml):
  function test_jwt_aud_config_set_to_invalid_uri (line 269) | def test_jwt_aud_config_set_to_invalid_uri(defaultenv):
  function test_jwt_secret_min_length (line 280) | def test_jwt_secret_min_length(defaultenv):
  function test_invalid_client_error_verbosity (line 289) | def test_invalid_client_error_verbosity(defaultenv):
  function test_restricted_db_schemas (line 301) | def test_restricted_db_schemas(restricted_schema, defaultenv):
  function test_cli_ready_flag_success (line 317) | def test_cli_ready_flag_success(host, defaultenv):
  function test_cli_ready_flag_fail_when_schema_cache_not_loaded (line 333) | def test_cli_ready_flag_fail_when_schema_cache_not_loaded(defaultenv, me...
  function test_cli_ready_flag_fail_with_http_exception (line 363) | def test_cli_ready_flag_fail_with_http_exception(defaultenv):
  function test_cli_ready_flag_fail_with_special_hostname (line 392) | def test_cli_ready_flag_fail_with_special_hostname(defaultenv):
  function test_cli_ready_flag_fail_when_no_admin_server (line 407) | def test_cli_ready_flag_fail_when_no_admin_server(defaultenv):

FILE: test/io/test_io.py
  function test_connect_with_dburi (line 24) | def test_connect_with_dburi(dburi, defaultenv):
  function test_read_dburi_from_stdin_without_eol (line 36) | def test_read_dburi_from_stdin_without_eol(dburi, defaultenv):
  function test_read_dburi_from_stdin_with_eol (line 49) | def test_read_dburi_from_stdin_with_eol(dburi, defaultenv):
  function test_app_settings_flush_pool (line 62) | def test_app_settings_flush_pool(defaultenv):
  function test_flush_pool_no_interrupt (line 86) | def test_flush_pool_no_interrupt(defaultenv):
  function test_graceful_shutdown_waits_for_in_flight_request (line 109) | def test_graceful_shutdown_waits_for_in_flight_request(defaultenv):
  function test_random_port_bound (line 130) | def test_random_port_bound(defaultenv):
  function test_app_settings_reload (line 137) | def test_app_settings_reload(tmp_path, defaultenv):
  function test_db_schema_reload (line 159) | def test_db_schema_reload(tmp_path, defaultenv):
  function test_db_schema_notify_reload (line 186) | def test_db_schema_notify_reload(defaultenv):
  function test_max_rows_reload (line 211) | def test_max_rows_reload(defaultenv):
  function test_max_rows_notify_reload (line 241) | def test_max_rows_notify_reload(defaultenv):
  function test_invalid_role_claim_key_notify_reload (line 272) | def test_invalid_role_claim_key_notify_reload(defaultenv):
  function test_notify_do_nothing (line 295) | def test_notify_do_nothing(defaultenv):
  function test_db_prepared_statements_enable (line 314) | def test_db_prepared_statements_enable(defaultenv):
  function test_db_prepared_statements_disable (line 322) | def test_db_prepared_statements_disable(defaultenv):
  function test_statement_timeout (line 335) | def test_statement_timeout(defaultenv, metapostgrest):
  function test_change_statement_timeout (line 360) | def test_change_statement_timeout(defaultenv, metapostgrest):
  function test_pool_size (line 401) | def test_pool_size(defaultenv, metapostgrest):
  function test_pool_acquisition_timeout (line 433) | def test_pool_acquisition_timeout(level, defaultenv, metapostgrest):
  function test_change_statement_timeout_held_connection (line 462) | def test_change_statement_timeout_held_connection(defaultenv, metapostgr...
  function test_admin_schema_cache (line 514) | def test_admin_schema_cache(defaultenv):
  function test_admin_ready_w_channel (line 523) | def test_admin_ready_w_channel(defaultenv):
  function test_admin_ready_wo_channel (line 536) | def test_admin_ready_wo_channel(defaultenv):
  function test_admin_ready_includes_schema_cache_state (line 549) | def test_admin_ready_includes_schema_cache_state(defaultenv, metapostgre...
  function test_metrics_include_schema_cache_fails (line 580) | def test_metrics_include_schema_cache_fails(defaultenv, metapostgrest):
  function test_admin_not_found (line 618) | def test_admin_not_found(defaultenv):
  function test_admin_ready_dependent_on_main_app (line 626) | def test_admin_ready_dependent_on_main_app(defaultenv):
  function test_admin_live_good (line 636) | def test_admin_live_good(defaultenv):
  function test_admin_live_dependent_on_main_app (line 644) | def test_admin_live_dependent_on_main_app(defaultenv):
  function test_admin_works_with_host_special_values (line 655) | def test_admin_works_with_host_special_values(specialhostvalue, defaulte...
  function test_log_level (line 667) | def test_log_level(level, defaultenv):
  function test_log_query (line 740) | def test_log_query(level, defaultenv):
  function test_no_pool_connection_required_on_bad_http_logic (line 859) | def test_no_pool_connection_required_on_bad_http_logic(defaultenv):
  function test_no_pool_connection_required_on_options (line 874) | def test_no_pool_connection_required_on_options(defaultenv):
  function test_no_pool_connection_required_on_bad_jwt_claim (line 891) | def test_no_pool_connection_required_on_bad_jwt_claim(defaultenv):
  function test_no_pool_connection_required_on_bad_embedding (line 903) | def test_no_pool_connection_required_on_bad_embedding(defaultenv):
  function test_notify_reloading_catalog_cache (line 913) | def test_notify_reloading_catalog_cache(defaultenv):
  function test_role_settings (line 934) | def test_role_settings(defaultenv):
  function test_isolation_level (line 976) | def test_isolation_level(defaultenv):
  function test_schema_cache_concurrent_notifications (line 1049) | def test_schema_cache_concurrent_notifications(slow_schema_cache_env):
  function test_schema_cache_query_sleep_logs (line 1083) | def test_schema_cache_query_sleep_logs(defaultenv):
  function test_schema_cache_load_sleep_logs (line 1108) | def test_schema_cache_load_sleep_logs(defaultenv):
  function test_get_pgrst_version_with_uri_connection_string (line 1134) | def test_get_pgrst_version_with_uri_connection_string(dburi_type, dburi,...
  function test_get_pgrst_version_with_keyval_connection_string (line 1156) | def test_get_pgrst_version_with_keyval_connection_string(defaultenv):
  function test_log_postgrest_version (line 1174) | def test_log_postgrest_version(defaultenv):
  function test_log_postgrest_host_and_port (line 1187) | def test_log_postgrest_host_and_port(host, defaultenv):
  function test_succeed_w_role_having_superuser_settings (line 1207) | def test_succeed_w_role_having_superuser_settings(defaultenv):
  function test_get_granted_superuser_setting (line 1219) | def test_get_granted_superuser_setting(defaultenv):
  function test_fail_with_invalid_dbname_and_automatic_recovery_disabled (line 1237) | def test_fail_with_invalid_dbname_and_automatic_recovery_disabled(defaul...
  function test_fail_with_automatic_recovery_disabled_and_terminated_using_query (line 1252) | def test_fail_with_automatic_recovery_disabled_and_terminated_using_quer...
  function test_preflight_request_with_cors_allowed_origin_config (line 1272) | def test_preflight_request_with_cors_allowed_origin_config(defaultenv):
  function test_preflight_request_with_empty_cors_allowed_origin_config (line 1295) | def test_preflight_request_with_empty_cors_allowed_origin_config(default...
  function test_no_preflight_request_with_CORS_config_should_return_header (line 1316) | def test_no_preflight_request_with_CORS_config_should_return_header(defa...
  function test_no_preflight_request_with_CORS_config_should_not_return_header (line 1334) | def test_no_preflight_request_with_CORS_config_should_not_return_header(...
  function test_db_error_logging_to_stderr (line 1353) | def test_db_error_logging_to_stderr(level, defaultenv, metapostgrest):
  function test_function_setting_statement_timeout_fails (line 1385) | def test_function_setting_statement_timeout_fails(defaultenv):
  function test_function_setting_statement_timeout_passes (line 1398) | def test_function_setting_statement_timeout_passes(defaultenv):
  function test_function_setting_work_mem (line 1408) | def test_function_setting_work_mem(defaultenv):
  function test_multiple_func_settings (line 1422) | def test_multiple_func_settings(defaultenv):
  function test_first_hoisted_setting_is_applied (line 1440) | def test_first_hoisted_setting_is_applied(defaultenv):
  function test_second_hoisted_setting_is_applied (line 1456) | def test_second_hoisted_setting_is_applied(defaultenv):
  function test_admin_metrics (line 1472) | def test_admin_metrics(defaultenv):
  function test_schema_cache_startup_load_with_in_db_config (line 1487) | def test_schema_cache_startup_load_with_in_db_config(defaultenv, metapos...
  function test_pgrst_log_503_client_error_to_stderr (line 1504) | def test_pgrst_log_503_client_error_to_stderr(defaultenv):
  function test_log_error_when_empty_schema_cache_on_startup_to_stderr (line 1523) | def test_log_error_when_empty_schema_cache_on_startup_to_stderr(defaulte...
  function test_no_double_schema_cache_reload_on_empty_schema (line 1544) | def test_no_double_schema_cache_reload_on_empty_schema(defaultenv):
  function test_log_pool_req_observation (line 1567) | def test_log_pool_req_observation(level, defaultenv):
  function test_proxy_status_header (line 1594) | def test_proxy_status_header(defaultenv, metapostgrest):
  function test_allow_configs_to_be_set_to_empty (line 1614) | def test_allow_configs_to_be_set_to_empty(defaultenv):
  function test_schema_cache_error_observation (line 1627) | def test_schema_cache_error_observation(defaultenv):
  function test_log_listener_connection_errors (line 1647) | def test_log_listener_connection_errors(defaultenv):
  function test_log_listener_connection_start (line 1665) | def test_log_listener_connection_start(defaultenv):
  function test_db_pre_config_with_pg_reserved_words (line 1684) | def test_db_pre_config_with_pg_reserved_words(defaultenv):
  function test_requests_with_resource_embedding_wait_for_schema_cache_reload (line 1710) | def test_requests_with_resource_embedding_wait_for_schema_cache_reload(d...
  function test_requests_without_resource_embedding_wait_for_schema_cache_reload (line 1732) | def test_requests_without_resource_embedding_wait_for_schema_cache_reloa...
  function test_server_timing_transaction_duration (line 1758) | def test_server_timing_transaction_duration(defaultenv, metapostgrest):
  function test_client_error_verbosity_config (line 1784) | def test_client_error_verbosity_config(defaultenv):
  function test_vary_custom_header_set (line 1816) | def test_vary_custom_header_set(defaultenv):
  function test_vary_default_header_set (line 1827) | def test_vary_default_header_set(defaultenv):

FILE: test/io/test_replica.py
  function test_sanity_replica (line 6) | def test_sanity_replica(replicaenv):

FILE: test/io/test_sanity.py
  function test_port_connection (line 8) | def test_port_connection(defaultenv):
  function test_plain_get (line 14) | def test_plain_get(defaultenv):
  function test_no_pool_connection_available (line 21) | def test_no_pool_connection_available(defaultenv):

FILE: test/io/util.py
  class Thread (line 5) | class Thread(threading.Thread):
    method __init__ (line 8) | def __init__(self, *args, **kwargs):
    method run (line 12) | def run(self):
    method join (line 18) | def join(self):
  function authheader (line 24) | def authheader(token):
  function jwtauthheader (line 29) | def jwtauthheader(claim, secret):
  function parse_server_timings_header (line 34) | def parse_server_timings_header(header):

FILE: test/load/fixtures.sql
  type test (line 8) | CREATE TABLE test.actors (
  type test (line 17) | CREATE TABLE test.films (
  type test (line 30) | CREATE TABLE test.roles (
  function test (line 39) | CREATE FUNCTION test.call_me (name TEXT) RETURNS TEXT

FILE: test/observability/fixtures/schema.sql
  type authors_only (line 11) | CREATE TABLE authors_only (

FILE: test/spec/fixtures/jsonschema.sql
  function public (line 23) | CREATE OR REPLACE FUNCTION public._validate_json_schema_type(type text, ...
  function test (line 41) | CREATE OR REPLACE FUNCTION test.validate_json_schema(schema jsonb, data ...

FILE: test/spec/fixtures/jwt.sql
  function jwt (line 10) | CREATE OR REPLACE FUNCTION jwt.url_encode(data bytea) RETURNS text LANGU...
  function jwt (line 15) | CREATE OR REPLACE FUNCTION jwt.url_decode(data text) RETURNS bytea LANGU...
  function jwt (line 27) | CREATE OR REPLACE FUNCTION jwt.algorithm_sign(signables text, secret tex...
  function jwt (line 40) | CREATE OR REPLACE FUNCTION jwt.sign(payload json, secret text, algorithm...
  function jwt (line 59) | CREATE OR REPLACE FUNCTION jwt.verify(token text, secret text, algorithm...

FILE: test/spec/fixtures/schema.sql
  function check_role_exists (line 64) | CREATE FUNCTION check_role_exists() RETURNS trigger
  function set_authors_only_owner (line 81) | CREATE FUNCTION set_authors_only_owner() RETURNS trigger
  function update_owner (line 95) | CREATE FUNCTION update_owner() RETURNS trigger
  type items (line 126) | CREATE TABLE items (
  type items2 (line 130) | CREATE TABLE items2 (
  type items3 (line 134) | CREATE TABLE items3 (
  function search (line 138) | CREATE FUNCTION search(id BIGINT) RETURNS SETOF items
  function always_true (line 145) | CREATE FUNCTION always_true(test.items) RETURNS boolean
  function computed_overload (line 149) | CREATE FUNCTION computed_overload(test.items) RETURNS boolean
  function computed_overload (line 153) | CREATE FUNCTION computed_overload(test.items2) RETURNS boolean
  function is_first (line 157) | CREATE FUNCTION is_first(test.items) RETURNS boolean
  function anti_id (line 162) | CREATE FUNCTION anti_id(test.items) RETURNS bigint
  function always_false (line 168) | CREATE FUNCTION always_false(test.items) RETURNS boolean
  type public_consumers (line 172) | create table public_consumers (
  type public_orders (line 178) | create table public_orders (
  type orders_view (line 195) | create view orders_view as
  type consumers_view (line 198) | create view consumers_view as
  type consumers_view_view (line 201) | create view consumers_view_view as
  type public (line 204) | create view public.consumers_extra as
  type consumers_extra_view (line 207) | create view consumers_extra_view as
  function getitemrange (line 214) | CREATE FUNCTION getitemrange(min bigint, max bigint) RETURNS SETOF items
  function noparamsproc (line 225) | CREATE FUNCTION noparamsproc() RETURNS text
  function login (line 236) | CREATE FUNCTION login(id text, pass text) RETURNS public.jwt_token
  function varied_arguments (line 251) | CREATE FUNCTION varied_arguments(
  function varied_arguments_openapi (line 285) | CREATE FUNCTION varied_arguments_openapi(
  function json_argument (line 336) | CREATE FUNCTION json_argument(arg json) RETURNS text
  function jwt_test (line 347) | CREATE FUNCTION jwt_test() RETURNS public.jwt_token
  function switch_role (line 363) | CREATE OR REPLACE FUNCTION switch_role() RETURNS void
  function problem (line 421) | CREATE FUNCTION problem() RETURNS void
  function test (line 1269) | create function test.single_column_table_return () returns table (a text...
  function test (line 1273) | create function test.multi_column_table_return () returns table (a text,...
  function test (line 1277) | CREATE FUNCTION test.variadic_param(VARIADIC v TEXT[] DEFAULT '{}') RETU...
  function test (line 1283) | CREATE FUNCTION test.sayhello_variadic(name TEXT, VARIADIC v TEXT[]) RET...
  function test (line 1289) | create or replace function test.raise_pt402() returns void as $$
  function test (line 1303) | create or replace function test.send_body_status_403() returns json as $$
  function test (line 1310) | create or replace function test.send_bad_status() returns json as $$
  function test (line 1317) | create or replace function test.get_projects_and_guc_headers() returns s...
  function test (line 1322) | create or replace function test.get_int_and_guc_headers(num int) returns...
  function test (line 1327) | create or replace function test.bad_guc_headers_1() returns void as $$
  function test (line 1331) | create or replace function test.bad_guc_headers_2() returns void as $$
  function test (line 1335) | create or replace function test.bad_guc_headers_3() returns void as $$
  function test (line 1339) | create or replace function test.set_cookie_twice() returns void as $$
  function test (line 1343) | create or replace function test.three_defaults(a int default 1, b int de...
  function test (line 1347) | create or replace function test.overloaded() returns setof int as $$
  function test (line 1359) | create or replace function test.overloaded(a text, b text, c text) retur...
  function test (line 1363) | create or replace function test.overloaded_default(opt_param text defaul...
  function test (line 1367) | create or replace function test.overloaded_default(must_param int) retur...
  function test (line 1371) | create or replace function test.overloaded_default(a int, opt_param text...
  function test (line 1375) | create or replace function test.overloaded_default(a int, must_param int...
  function test (line 1379) | create or replace function test.overloaded_html_form() returns setof int...
  function test (line 1391) | create or replace function test.overloaded_html_form(a text, b text, c t...
  function test (line 1395) | create or replace function test.overloaded_same_args(arg integer) return...
  function test (line 1402) | create or replace function test.overloaded_same_args(arg xml) returns js...
  function test (line 1409) | create or replace function test.overloaded_same_args(arg text, num integ...
  type test (line 1416) | create table test.leak(
  function test (line 1421) | create function test.leak(blob bytea) returns void as $$ begin end; $$ l...
  type designers (line 2735) | CREATE TABLE designers (
  type videogames (line 2740) | CREATE TABLE videogames (
  function test (line 2747) | CREATE FUNCTION test.computed_designers(test.videogames) RETURNS SETOF t...
  type public (line 2934) | create table public.i2459_simple_t1 (
  type public (line 2938) | create table public.i2459_simple_t2 (
  type i2459_simple_v1 (line 2942) | create view i2459_simple_v1 as table public.i2459_simple_t1;
  type public (line 2948) | create table public.i2459_composite_t1 (
  type public (line 2954) | create table public.i2459_composite_t2 (
  type i2459_composite_v1 (line 2960) | create view i2459_composite_v1 as table public.i2459_composite_t1;
  type public (line 2970) | create table public.i2459_self_t (
  type i2459_self_v1 (line 2977) | create view i2459_self_v1 as
  type i2459_self_v2 (line 2986) | create view i2459_self_v2 as
  type public (line 2996) | CREATE TABLE public.ta (
  type public (line 3002) | CREATE TABLE public.tb (
  type test (line 3008) | CREATE VIEW test.va AS SELECT a1 FROM public.ta
  type test (line 3009) | CREATE VIEW test.vb AS SELECT b1 FROM public.tb
  type test (line 3011) | create table test.trash(
  type test (line 3015) | create table test.trash_details(
  type test (line 3020) | CREATE TABLE test.groups (
  type test (line 3024) | CREATE TABLE test.yards (
  type test (line 3028) | CREATE TABLE test.group_yard (
  type test (line 3041) | create table test.posters(
  type test (line 3046) | create table test.subscriptions(
Condensed preview — 354 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,952K chars).
[
  {
    "path": ".cirrus.yml",
    "chars": 1061,
    "preview": "freebsd_instance:\n  image_family: freebsd-14-3\n\nbuild_task:\n  # Don't change this name without adjusting .github/workflo"
  },
  {
    "path": ".editorconfig",
    "chars": 147,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 2\nindent_style = space\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".gitattributes",
    "chars": 26,
    "preview": "/CHANGELOG.md merge=union\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 66,
    "preview": "# These are supported funding model platforms\n\npatreon: postgrest\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 781,
    "preview": "---\nname: Bug report\nabout: Create a bug report to help us improve\ntype: Bug\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n<!"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 28,
    "preview": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 270,
    "preview": "---\nname: Feature request\nabout: Suggest an enhancement for this project\ntype: Feature\ntitle: ''\nlabels: ''\nassignees: '"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 826,
    "preview": "<!--\nWhen submitting a new feature or fix:\n\n- Add a new entry to the CHANGELOG - https://github.com/PostgREST/postgrest/"
  },
  {
    "path": ".github/actionlint.yml",
    "chars": 158,
    "preview": "# TODO: Remove this once a new actionlint release has been cut\n# and made its way to us through nixpkgs.\nself-hosted-run"
  },
  {
    "path": ".github/actions/artifact-from-cirrus/action.yaml",
    "chars": 4413,
    "preview": "name: Artifact from Cirrus\n\ndescription: Waits for a specific Cirrus CI run to complete, then downloads the artifact and"
  },
  {
    "path": ".github/actions/cache-on-main/action.yaml",
    "chars": 1359,
    "preview": "name: Cache on main\n\ndescription: Stores caches on main and release branches only, but restores them on all branches.\n\ni"
  },
  {
    "path": ".github/actions/setup-nix/action.yaml",
    "chars": 766,
    "preview": "name: Setup Nix\n\ndescription: Installs nix, sets up cachix and installs a subset of tooling.\n\ninputs:\n  authToken:\n    d"
  },
  {
    "path": ".github/codecov.yml",
    "chars": 280,
    "preview": "codecov:\n  branch: main\n  require_ci_to_pass: false\n\ncomment: false\n\ncoverage:\n  status:\n    project:\n      default:\n   "
  },
  {
    "path": ".github/renovate.json",
    "chars": 1269,
    "preview": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\n    \"config:best-practices\"\n  ],\n  \"b"
  },
  {
    "path": ".github/workflows/backport.yaml",
    "chars": 1850,
    "preview": "name: Backport\n\non:\n  pull_request_target:\n    types:\n      - closed\n      - labeled\n\njobs:\n  backport:\n    name: Backpo"
  },
  {
    "path": ".github/workflows/build.yaml",
    "chars": 6803,
    "preview": "name: Build\n\non:\n  workflow_call:\n    secrets:\n      CACHIX_AUTH_TOKEN:\n        required: false\n  pull_request:\n    bran"
  },
  {
    "path": ".github/workflows/check.yaml",
    "chars": 1823,
    "preview": "name: Check\n\non:\n  workflow_call:\n    secrets:\n      CACHIX_AUTH_TOKEN:\n        required: false\n  pull_request:\n    bran"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "chars": 1743,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - main\n      - v[0-9]+\n\njobs:\n  check:\n    name: Check\n    uses: ./.github/wor"
  },
  {
    "path": ".github/workflows/docs.yaml",
    "chars": 1431,
    "preview": "name: Docs\n\non:\n  workflow_call:\n    secrets:\n      CACHIX_AUTH_TOKEN:\n        required: false\n  pull_request:\n    branc"
  },
  {
    "path": ".github/workflows/linkcheck.yaml",
    "chars": 424,
    "preview": "name: Linkcheck\n\non:\n  schedule:\n    - cron: '1 2 * * 3'\n  workflow_dispatch:\n\njobs:\n  linkcheck:\n    runs-on: ubuntu-24"
  },
  {
    "path": ".github/workflows/release.yaml",
    "chars": 7595,
    "preview": "name: Release\n\non:\n  push:\n    tags:\n      - devel\n      - v*\n\nconcurrency:\n  # Terminate all previous runs of the same "
  },
  {
    "path": ".github/workflows/test.yaml",
    "chars": 5479,
    "preview": "name: Test\n\non:\n  workflow_call:\n    secrets:\n      CACHIX_AUTH_TOKEN:\n        required: false\n      CODECOV_TOKEN:\n    "
  },
  {
    "path": ".gitignore",
    "chars": 275,
    "preview": ".DS_Store\ndb\ndist\n.cabal-sandbox\ncabal.sandbox.config\nhscope.out\ncodex.tags\n.anvil\n.stack-work*\ntags\nsite\n*~\n*#*\n.#*\n*.s"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 164,
    "preview": "version: 2\nsphinx:\n  configuration: docs/conf.py\npython:\n   install:\n   - requirements: docs/requirements.txt\nbuild:\n  o"
  },
  {
    "path": ".stylish-haskell.yaml",
    "chars": 7804,
    "preview": "# stylish-haskell configuration file\n# ==================================\n\n# The stylish-haskell tool is mainly configur"
  },
  {
    "path": "BACKERS.md",
    "chars": 3594,
    "preview": "# Sponsors & Backers\n\nPostgREST ongoing development is only possible thanks to our Sponsors and Backers, listed below. I"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 76635,
    "preview": "# Change Log\n\nAll notable changes to this project will be documented in this file. From version `14.0` onwards PostgREST"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5488,
    "preview": "\n# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make particip"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4229,
    "preview": "# Contributing to PostgREST\n\n## Issues\n\nFor questions on how to use PostgREST, please use\n[GitHub discussions](https://g"
  },
  {
    "path": "Dockerfile",
    "chars": 725,
    "preview": "# PostgREST Docker Hub image for aarch64.\n# The x86-64 is a single-static-binary image built via Nix, see:\n# nix/tools/d"
  },
  {
    "path": "LICENSE",
    "chars": 1075,
    "preview": "Copyright (c) 2014-2026 The PostgREST contributors\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "README.md",
    "chars": 6843,
    "preview": "![Logo](static/postgrest.png \"Logo\")\n\n[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)]("
  },
  {
    "path": "Setup.hs",
    "chars": 83,
    "preview": "-- This file is required by Hackage.\nimport Distribution.Simple\nmain = defaultMain\n"
  },
  {
    "path": "cabal.project",
    "chars": 38,
    "preview": "packages: postgrest.cabal\ntests: true\n"
  },
  {
    "path": "cabal.project.freeze",
    "chars": 54,
    "preview": "index-state: hackage.haskell.org 2025-10-29T04:02:18Z\n"
  },
  {
    "path": "default.nix",
    "chars": 5305,
    "preview": "{ system ? builtins.currentSystem\n\n, compiler ? \"ghc948\"\n\n, # Commit of the Nixpkgs repository that we want to use.\n  # "
  },
  {
    "path": "docker-hub-readme.md",
    "chars": 2970,
    "preview": "# PostgREST\n\n[![Donate](https://img.shields.io/badge/Donate-Patreon-orange.svg?colorB=F96854)](https://www.patreon.com/p"
  },
  {
    "path": "docs/.gitignore",
    "chars": 78,
    "preview": "_build\nPipfile.lock\n*.aux\n*.log\n_diagrams/db.pdf\nmisspellings\nunuseddict\n*.mo\n"
  },
  {
    "path": "docs/README.md",
    "chars": 944,
    "preview": "# PostgREST documentation https://postgrest.org/\n\nPostgREST docs use the reStructuredText format, check this [cheatsheet"
  },
  {
    "path": "docs/_diagrams/README.md",
    "chars": 783,
    "preview": "## ERD\n\nThe ER diagrams were created with https://github.com/BurntSushi/erd/.\n\nYou can go download erd from https://gith"
  },
  {
    "path": "docs/_diagrams/er/boxoffice.er",
    "chars": 166,
    "preview": "entity {font: \"FreeSans\"}\nrelationship {font: \"FreeMono\"}\n\n[Box_Office]\n*bo_date\n*+film_id\ngross_revenue\n\n[Films]\n*id\n+d"
  },
  {
    "path": "docs/_diagrams/er/employees.er",
    "chars": 162,
    "preview": "# Build using: -e ortho\n\nentity {font: \"FreeSans\"}\nrelationship {font: \"FreeMono\"}\n\n[Employees]\n*id\nfirst_name\nlast_name"
  },
  {
    "path": "docs/_diagrams/er/film.er",
    "chars": 492,
    "preview": "entity {font: \"FreeSans\"}\nrelationship {font: \"FreeSerif\"}\n\n[Films]\n*id\n+director_id\ntitle\nyear\nrating\nlanguage\n\n[Direct"
  },
  {
    "path": "docs/_diagrams/er/orders.er",
    "chars": 233,
    "preview": "# Build using: -e ortho\n\nentity {font: \"FreeSans\"}\nrelationship {font: \"FreeMono\"}\n\n[Addresses]\n*id\nname\ncity\nstate\npost"
  },
  {
    "path": "docs/_diagrams/er/premieres.er",
    "chars": 158,
    "preview": "entity {font: \"FreeSans\"}\nrelationship {font: \"FreeMono\"}\n\n[Premieres]\n*id\nlocation\ndate\n+film_id\n\n[Films]\n*id\n+director"
  },
  {
    "path": "docs/_diagrams/er/presidents.er",
    "chars": 166,
    "preview": "# Build using: -e ortho\n\nentity {font: \"FreeSans\"}\nrelationship {font: \"FreeMono\"}\n\n[Presidents]\n*id\nfirst_name\nlast_nam"
  },
  {
    "path": "docs/_diagrams/er/users.er",
    "chars": 231,
    "preview": "# Build using: -e ortho\n\nentity {font: \"FreeSans\"}\nrelationship {font: \"FreeMono\"}\n\n[Users]\n*id\nfirst_name\nlast_name\nuse"
  },
  {
    "path": "docs/_diagrams/uml/arch.uml",
    "chars": 2370,
    "preview": "@startuml\n\nskinparam backgroundColor transparent\n\npackage \"PostgREST\" {\n  () HTTP as HTTPAPI\n  HTTPAPI  - [Auth]\n  [Auth"
  },
  {
    "path": "docs/_diagrams/uml/dark/arch-dark.uml",
    "chars": 39,
    "preview": "@startuml\n!include ../arch.uml\n@enduml\n"
  },
  {
    "path": "docs/_diagrams/uml/dark/sch-iso-dark.uml",
    "chars": 42,
    "preview": "@startuml\n!include ../sch-iso.uml\n@enduml\n"
  },
  {
    "path": "docs/_diagrams/uml/sch-iso.uml",
    "chars": 456,
    "preview": "@startuml\n\nskinparam backgroundColor transparent\nskinparam linetype ortho\n\nskinparam node {\n  backgroundColor transparen"
  },
  {
    "path": "docs/_static/css/custom.css",
    "chars": 2333,
    "preview": ".wy-nav-content {\n  max-width: initial;\n}\n\n#postgrest-documentation > h1 {\n  display: none;\n}\n\ndiv.wy-menu.rst-pro {\n  d"
  },
  {
    "path": "docs/conf.py",
    "chars": 10783,
    "preview": "# -*- coding: utf-8 -*-\n#\n# PostgREST documentation build configuration file, created by\n# sphinx-quickstart on Sun Oct "
  },
  {
    "path": "docs/ecosystem.rst",
    "chars": 6151,
    "preview": ".. _community_tutorials:\n\nCommunity Tutorials\n-------------------\n\n* `Building a Contacts List with PostgREST and Vue.js"
  },
  {
    "path": "docs/explanations/architecture.rst",
    "chars": 2889,
    "preview": "Architecture\n############\n\nThis page describes the architecture of PostgREST.\n\nBird's Eye View\n===============\n\nYou can "
  },
  {
    "path": "docs/explanations/db_authz.rst",
    "chars": 7996,
    "preview": ".. _db_authz:\n\nDatabase Authorization\n######################\n\nDatabase authorization is the process of granting and veri"
  },
  {
    "path": "docs/explanations/external_auth.rst",
    "chars": 1183,
    "preview": ".. _external_auth:\n\nExternal Authentication\n-----------------------\n\nJWT from Auth0\n~~~~~~~~~~~~~~\n\nAn external service "
  },
  {
    "path": "docs/explanations/install.rst",
    "chars": 7930,
    "preview": ".. _install:\n\nInstallation\n############\n\nThe release page has `pre-compiled binaries for macOS, Windows, Linux and FreeB"
  },
  {
    "path": "docs/explanations/nginx.rst",
    "chars": 3788,
    "preview": ".. _nginx:\n\nNginx\n=====\n\nPostgREST is a fast way to construct a RESTful API. Its default behavior is great for scaffoldi"
  },
  {
    "path": "docs/explanations/schema_isolation.rst",
    "chars": 1117,
    "preview": ".. _schema_isolation:\n\nSchema Isolation\n================\n\nA PostgREST instance exposes all the tables, views, and functi"
  },
  {
    "path": "docs/how-tos/create-soap-endpoint.rst",
    "chars": 5990,
    "preview": ".. _create_soap_endpoint:\n\nCreate a SOAP endpoint\n======================\n\n:author: `fjf2002 <https://github.com/fjf2002>"
  },
  {
    "path": "docs/how-tos/providing-html-content-using-htmx.rst",
    "chars": 12895,
    "preview": "\n.. _providing_html_htmx:\n\nProviding HTML Content Using Htmx\n=================================\n\n:author: `Laurence Isla "
  },
  {
    "path": "docs/how-tos/providing-images-for-img.rst",
    "chars": 4855,
    "preview": ".. _providing_img:\n\nProviding images for ``<img>``\n==============================\n\n:author: `pkel <https://github.com/pk"
  },
  {
    "path": "docs/how-tos/sql-user-management-using-postgres-users-and-passwords.rst",
    "chars": 11119,
    "preview": ".. _sql-user-management-using-postgres-users-and-passwords:\n\nSQL User Management using postgres' users and passwords\n==="
  },
  {
    "path": "docs/how-tos/sql-user-management.rst",
    "chars": 7505,
    "preview": ".. _sql_user_management:\n\nSQL User Management\n===================\n\nAs mentioned on :ref:`jwt_generation`, an external se"
  },
  {
    "path": "docs/how-tos/working-with-postgresql-data-types.rst",
    "chars": 16598,
    "preview": ".. _working_with_types:\n\nWorking with PostgreSQL data types\n==================================\n\n:author: `Laurence Isla "
  },
  {
    "path": "docs/index.rst",
    "chars": 8923,
    "preview": ".. title:: PostgREST Documentation\n\nPostgREST Documentation\n=======================\n\n.. container:: image-container\n\n  ."
  },
  {
    "path": "docs/integrations/pg-safeupdate.rst",
    "chars": 1407,
    "preview": "pg-safeupdate\n#############\n\n.. _block_fulltable:\n\nBlock Full-Table Operations\n---------------------------\n\nIf the :ref:"
  },
  {
    "path": "docs/integrations/systemd.rst",
    "chars": 1653,
    "preview": "systemd\n=======\n\nFor Linux distributions that use **systemd** (Ubuntu, Debian, Arch Linux) you can create a daemon in th"
  },
  {
    "path": "docs/postgrest.dict",
    "chars": 1465,
    "preview": "personal_ws-1.1 en 0 utf-8\napi\nAPI's\nAPIs\nAPISIX\nAST\nasync\naud\nAuth\nauth\nauthenticator\nbackoff\nbooleans\nBOM\nBytea\nCardan"
  },
  {
    "path": "docs/references/admin_server.rst",
    "chars": 2073,
    "preview": ".. _admin_server:\n\nAdmin Server\n############\n\nPostgREST provides an admin server that can be enabled by setting :ref:`ad"
  },
  {
    "path": "docs/references/api/aggregate_functions.rst",
    "chars": 7705,
    "preview": ".. _aggregate_functions:\n\nAggregate Functions\n###################\n\nPostgREST supports the following aggregate functions:"
  },
  {
    "path": "docs/references/api/computed_fields.rst",
    "chars": 2498,
    "preview": ".. _computed_cols:\n\nComputed Fields\n###############\n\nComputed fields are virtual columns that are not stored in a table."
  },
  {
    "path": "docs/references/api/cors.rst",
    "chars": 1440,
    "preview": ".. _cors:\n\nCORS\n####\n\nBy default, PostgREST sets highly permissive cross origin resource sharing, that is why it accepts"
  },
  {
    "path": "docs/references/api/domain_representations.rst",
    "chars": 6740,
    "preview": ".. _domain_reps:\n\nDomain Representations\n######################\n\nDomain Representations separates \"how the data is prese"
  },
  {
    "path": "docs/references/api/functions.rst",
    "chars": 12221,
    "preview": ".. _functions:\n\nFunctions as RPC\n================\n\n*\"A single resource can be the equivalent of a database function, wit"
  },
  {
    "path": "docs/references/api/media_type_handlers.rst",
    "chars": 10768,
    "preview": ".. _custom_media:\n\nMedia Type Handlers\n###################\n\nMedia Type Handlers allow PostgREST to deliver custom media "
  },
  {
    "path": "docs/references/api/openapi.rst",
    "chars": 3355,
    "preview": ".. _open-api:\n\nOpenAPI\n=======\n\nPostgREST automatically serves a full `OpenAPI <https://www.openapis.org/>`_ description"
  },
  {
    "path": "docs/references/api/options.rst",
    "chars": 3129,
    "preview": ".. _options_requests:\n\nOPTIONS method\n==============\n\nYou can verify which HTTP methods are allowed on endpoints for tab"
  },
  {
    "path": "docs/references/api/pagination_count.rst",
    "chars": 4518,
    "preview": "Pagination and Count\n####################\n\nPagination controls the number of rows returned for an :doc:`API resource <.."
  },
  {
    "path": "docs/references/api/preferences.rst",
    "chars": 8630,
    "preview": ".. _preferences:\n\nPrefer Header\n#############\n\nPostgREST honors the Prefer HTTP header specified on `RFC 7240 <https://w"
  },
  {
    "path": "docs/references/api/resource_embedding.rst",
    "chars": 39214,
    "preview": ".. _resource_embedding:\n\nResource Embedding\n##################\n\nPostgREST allows including related resources in a single"
  },
  {
    "path": "docs/references/api/resource_representation.rst",
    "chars": 5671,
    "preview": "Resource Representation\n#######################\n\nPostgREST uses proper HTTP content negotiation (`RFC7231 <https://datat"
  },
  {
    "path": "docs/references/api/schemas.rst",
    "chars": 3905,
    "preview": ".. _schemas:\n\nSchemas\n=======\n\nPostgREST can expose a single or multiple schema's tables, views and functions. The :ref:"
  },
  {
    "path": "docs/references/api/tables_views.rst",
    "chars": 24820,
    "preview": ".. _tables_views:\n\nTables and Views\n################\n\nAll tables and views of the :ref:`exposed schema <schemas>` and ac"
  },
  {
    "path": "docs/references/api/url_grammar.rst",
    "chars": 2388,
    "preview": ".. note::\n\n  This page is a work in progress.\n\n.. _url_grammar:\n\nURL Grammar\n===========\n\n.. _custom_queries:\n\nCustom Qu"
  },
  {
    "path": "docs/references/api/vary_header.rst",
    "chars": 603,
    "preview": ".. _vary_header:\n\nVary Header\n===========\n\nIn order to assist caching proxies and CDNs, PostgREST includes a ``Vary`` he"
  },
  {
    "path": "docs/references/api.rst",
    "chars": 6686,
    "preview": ".. _api:\n\nAPI\n###\n\nPostgREST exposes three database objects of a schema as resources: tables, views and functions.\n\n.. t"
  },
  {
    "path": "docs/references/auth.rst",
    "chars": 15399,
    "preview": ".. _authn:\n\nAuthentication\n==============\n\nPostgREST is designed to keep the database at the center of API security. All"
  },
  {
    "path": "docs/references/cli.rst",
    "chars": 1927,
    "preview": ".. _cli:\n\nCLI\n===\n\nPostgREST provides a CLI with the options listed below:\n\n.. code:: text\n\n  Usage: postgrest [-v|--ver"
  },
  {
    "path": "docs/references/configuration.rst",
    "chars": 32359,
    "preview": ".. _configuration:\n\nConfiguration\n#############\n\nConfiguration parameters can be provided via:\n\n- :ref:`file_config`.\n- "
  },
  {
    "path": "docs/references/connection_pool.rst",
    "chars": 5589,
    "preview": ".. _connection_pool:\n\nConnection Pool\n===============\n\nA connection pool is a cache of reusable database connections. It"
  },
  {
    "path": "docs/references/errors.rst",
    "chars": 29566,
    "preview": ".. _error_source:\n\nErrors\n######\n\nPostgREST error messages follow the PostgreSQL error structure. It includes ``MESSAGE`"
  },
  {
    "path": "docs/references/listener.rst",
    "chars": 2592,
    "preview": ".. _listener:\n\nListener\n########\n\nPostgREST uses `LISTEN <https://www.postgresql.org/docs/current/sql-listen.html>`_ to "
  },
  {
    "path": "docs/references/observability.rst",
    "chars": 13695,
    "preview": ".. _observability:\n\nObservability\n#############\n\nObservability allows measuring a system's current state based on the da"
  },
  {
    "path": "docs/references/schema_cache.rst",
    "chars": 4493,
    "preview": ".. _schema_cache:\n\nSchema Cache\n============\n\nPostgREST requires metadata from the database schema to provide a REST API"
  },
  {
    "path": "docs/references/transactions.rst",
    "chars": 11801,
    "preview": ".. _transactions:\n\nTransactions\n============\n\nAfter :ref:`user_impersonation`, every request to an :doc:`API resource <a"
  },
  {
    "path": "docs/requirements.txt",
    "chars": 195,
    "preview": "# This file is auto-generated by postgrest-nixpkgs-upgrade\nsphinx==8.2.3\nsphinx-copybutton==0.5.2\nsphinx-rtd-dark-mode=="
  },
  {
    "path": "docs/shared/installation.rst",
    "chars": 1231,
    "preview": ".. tabs::\n\n  .. group-tab:: macOS\n\n    You can install PostgREST from the `Homebrew official repo <https://formulae.brew"
  },
  {
    "path": "docs/tutorials/tut0.rst",
    "chars": 9826,
    "preview": ".. _tut0:\n\nTutorial 0 - Get it Running\n===========================\n\n:author: `begriffs <https://github.com/begriffs>`_\n\n"
  },
  {
    "path": "docs/tutorials/tut1.rst",
    "chars": 9274,
    "preview": ".. _tut1:\n\nTutorial 1 - The Golden Key\n===========================\n\n:author: `begriffs <https://github.com/begriffs>`_\n\n"
  },
  {
    "path": "flake.nix",
    "chars": 1457,
    "preview": "{\n  description = \"REST API for any Postgres database\";\n\n  inputs = {\n    nixpkgs.url = \"github:nixos/nixpkgs/nixpkgs-25"
  },
  {
    "path": "main/Main.hs",
    "chars": 526,
    "preview": "module Main (main) where\n\nimport System.IO (BufferMode (..), hSetBuffering)\n\nimport qualified PostgREST.CLI as CLI\n\nimpo"
  },
  {
    "path": "nix/README.md",
    "chars": 13133,
    "preview": "# Nix development and build environment\n\nWith Nix it's possible to quickly and reliably recreate the full environments\nf"
  },
  {
    "path": "nix/UPGRADE.md",
    "chars": 2889,
    "preview": "# Checklist for upgrading Nix dependencies\n\nThe Nix dependencies of PostgREST should be updated regularly, in most cases"
  },
  {
    "path": "nix/hsie/Main.hs",
    "chars": 12817,
    "preview": "{-# LANGUAGE DeriveAnyClass    #-}\n{-# LANGUAGE DeriveGeneric     #-}\n{-# LANGUAGE NamedFieldPuns    #-}\n{-# LANGUAGE Ov"
  },
  {
    "path": "nix/hsie/README.md",
    "chars": 1900,
    "preview": "# hsie - Swiss army knife for HaSkell Imports and Exports\n\nThis tool parses Haskell source code to analyse the imports a"
  },
  {
    "path": "nix/hsie/default.nix",
    "chars": 822,
    "preview": "{ ghcWithPackages\n, runCommand\n}:\nlet\n  name = \"hsie\";\n  src = ./Main.hs;\n  modules = ps: [\n    ps.aeson\n    ps.aeson-pr"
  },
  {
    "path": "nix/overlays/build-toolbox/build-toolbox.nix",
    "chars": 454,
    "preview": "# Creates an environment that exposes bash-completion arguments from all checkedShellScripts\n{ buildEnv }:\n{ name\n, tool"
  },
  {
    "path": "nix/overlays/build-toolbox/default.nix",
    "chars": 144,
    "preview": "_: super:\n# Overlay that adds `buildToolbox`, an enhanced version of `buildEnv`\n{\n  buildToolbox = super.callPackage ./b"
  },
  {
    "path": "nix/overlays/checked-shell-script/checked-shell-script.nix",
    "chars": 4383,
    "preview": "# Create a bash script that is checked with shellcheck. You can either use it\n# directly, or use the .bin attribute to g"
  },
  {
    "path": "nix/overlays/checked-shell-script/default.nix",
    "chars": 195,
    "preview": "_: super:\n# Overlay that adds `checkedShellScript`, an enhanced version of\n# writeShellScript and writeShellScriptBin\n{\n"
  },
  {
    "path": "nix/overlays/default.nix",
    "chars": 192,
    "preview": "{\n  build-toolbox = import ./build-toolbox;\n  checked-shell-script = import ./checked-shell-script;\n  gitignore = import"
  },
  {
    "path": "nix/overlays/gitignore.nix",
    "chars": 715,
    "preview": "_: super:\n# Overlay that adds the `gitignoreSource` function from Hercules-CI.\n# This function is useful for filtering w"
  },
  {
    "path": "nix/overlays/haskell-packages.nix",
    "chars": 3526,
    "preview": "{ compiler }:\n\nself: super:\nlet\n  inherit (self.haskell) lib;\n\n  overrides =\n    _: prev:\n    rec {\n      # To pin custo"
  },
  {
    "path": "nix/static.nix",
    "chars": 911,
    "preview": "{ compiler\n, name\n, pkgs\n, src\n}:\nlet\n  # This builds a static PostgREST executable based on pkgsStatic.\n  inherit (pkgs"
  },
  {
    "path": "nix/tools/cabalTools.nix",
    "chars": 3858,
    "preview": "{ buildToolbox\n, cabal-install\n, checkedShellScript\n, devCabalOptions\n, postgrest\n}:\nlet\n  build =\n    checkedShellScrip"
  },
  {
    "path": "nix/tools/devTools.nix",
    "chars": 13881,
    "preview": "{ buildToolbox\n, cabal-install\n, cachix\n, checkedShellScript\n, curl\n, devCabalOptions\n, entr\n, git\n, graphviz\n, hsie\n, n"
  },
  {
    "path": "nix/tools/docker/README.md",
    "chars": 5897,
    "preview": "# Docker image built with Nix\n\nIn order to build an optimal PostgREST Docker image, we create the image from\nscratch (i."
  },
  {
    "path": "nix/tools/docker/default.nix",
    "chars": 884,
    "preview": "{ buildToolbox\n, postgrest\n, dockerTools\n, checkedShellScript\n}:\nlet\n  image =\n    dockerTools.buildImage {\n      name ="
  },
  {
    "path": "nix/tools/docs.nix",
    "chars": 5246,
    "preview": "{ aspell\n, aspellDicts\n, buildToolbox\n, checkedShellScript\n, lib\n, plantuml\n, python3\n, python3Packages\n, writeTextFile\n"
  },
  {
    "path": "nix/tools/gen_rsa_materials.py",
    "chars": 1344,
    "preview": "# Generate RSA JWK/public material for loadtests.\n\nimport argparse\nimport sys\nfrom pathlib import Path\n\nimport jwcrypto."
  },
  {
    "path": "nix/tools/generate_targets.py",
    "chars": 6489,
    "preview": "# generates a file to be used by the vegeta load testing tool\n\n# It includes a worst case scenario for the JWT cache:\n# "
  },
  {
    "path": "nix/tools/gitTools.nix",
    "chars": 1869,
    "preview": "{ buildToolbox\n, checkedShellScript\n, commitlint\n, writeText\n}:\nlet\n  # Rules format: [<severity>, <\"always\"/\"never\">, <"
  },
  {
    "path": "nix/tools/loadtest.nix",
    "chars": 12849,
    "preview": "{ buildToolbox\n, checkedShellScript\n, jq\n, python3Packages\n, vegeta\n, withTools\n, writers\n}:\nlet\n  runner =\n    checkedS"
  },
  {
    "path": "nix/tools/merge_monitor_result.py",
    "chars": 1276,
    "preview": "import os\nimport sys\nimport pandas as pd\n\nKEY = \"Elapsed seconds\"\nBASE_METRICS = [\"CPU (%)\", \"Real (MB)\"]\nbranch_order ="
  },
  {
    "path": "nix/tools/monitor_pid.py",
    "chars": 1421,
    "preview": "# Monitor a process pid with psutil and emits a CSV.\nimport sys\nimport time\nimport psutil\nimport pandas as pd\n\nKEY = \"El"
  },
  {
    "path": "nix/tools/nixpkgsTools.nix",
    "chars": 710,
    "preview": "{ buildToolbox\n, checkedShellScript\n}:\n# Utility script for pinning the latest stable version of Nixpkgs.\n\n# Instead of "
  },
  {
    "path": "nix/tools/release.nix",
    "chars": 3575,
    "preview": "{ buildToolbox\n, checkedShellScript\n}:\nlet\n  release =\n    checkedShellScript\n      {\n        name = \"postgrest-release\""
  },
  {
    "path": "nix/tools/style.nix",
    "chars": 3256,
    "preview": "{ actionlint\n, black\n, buildToolbox\n, checkedShellScript\n, deadnix\n, git\n, hlint\n, hsie\n, nixpkgs-fmt\n, python3Packages\n"
  },
  {
    "path": "nix/tools/tests.nix",
    "chars": 10422,
    "preview": "{ buildToolbox\n, cabal-install\n, checkedShellScript\n, curl\n, devCabalOptions\n, ghc\n, glibcLocales ? null\n, gnugrep\n, hpc"
  },
  {
    "path": "nix/tools/withTools.nix",
    "chars": 13981,
    "preview": "{ buildToolbox\n, checkedShellScript\n, curl\n, git\n, lib\n, postgresqlVersions\n, postgrest\n, python3Packages\n, writeText\n, "
  },
  {
    "path": "postgrest.cabal",
    "chars": 16421,
    "preview": "name:               postgrest\nversion:            15\nsynopsis:           REST API for any Postgres database\ndescription:"
  },
  {
    "path": "shell.nix",
    "chars": 1744,
    "preview": "# The additional modules below have large dependencies and are therefore\n# disabled by default. You can activate them by"
  },
  {
    "path": "src/PostgREST/Admin.hs",
    "chars": 2962,
    "preview": "module PostgREST.Admin\n  ( runAdmin\n  ) where\n\nimport qualified Data.Aeson                as JSON\nimport qualified Netwo"
  },
  {
    "path": "src/PostgREST/ApiRequest/Payload.hs",
    "chars": 5491,
    "preview": "-- |\n-- Module      : PostgREST.ApiRequest.Payload\n-- Description : Parser for PostgREST Request Body\n--\n-- This module "
  },
  {
    "path": "src/PostgREST/ApiRequest/Preferences.hs",
    "chars": 10959,
    "preview": "-- |\n-- Module: PostgREST.ApiRequest.Preferences\n-- Description: Track client preferences to be employed when processing"
  },
  {
    "path": "src/PostgREST/ApiRequest/QueryParams.hs",
    "chars": 35135,
    "preview": "-- |\n-- Module      : PostgREST.ApiRequest.QueryParams\n-- Description : Parser for PostgREST Query parameters\n--\n-- This"
  },
  {
    "path": "src/PostgREST/ApiRequest/Types.hs",
    "chars": 6662,
    "preview": "{-# LANGUAGE DuplicateRecordFields #-}\nmodule PostgREST.ApiRequest.Types\n  ( AggregateFunction(..)\n  , Alias\n  , Cast\n  "
  },
  {
    "path": "src/PostgREST/ApiRequest.hs",
    "chars": 10263,
    "preview": "{-|\nModule      : PostgREST.Request.ApiRequest\nDescription : PostgREST functions to translate HTTP request to a domain t"
  },
  {
    "path": "src/PostgREST/App.hs",
    "chars": 12225,
    "preview": "{-|\nModule      : PostgREST.App\nDescription : PostgREST main application\n\nThis module is in charge of mapping HTTP reque"
  },
  {
    "path": "src/PostgREST/AppState.hs",
    "chars": 17394,
    "preview": "{-# LANGUAGE LambdaCase      #-}\n{-# LANGUAGE NamedFieldPuns  #-}\n{-# LANGUAGE RecordWildCards #-}\n\nmodule PostgREST.App"
  },
  {
    "path": "src/PostgREST/Auth/Jwt.hs",
    "chars": 5486,
    "preview": "{-|\nModule      : PostgREST.Auth.Jwt\nDescription : PostgREST JWT support functions.\n\nThis module provides functions to d"
  },
  {
    "path": "src/PostgREST/Auth/JwtCache.hs",
    "chars": 4676,
    "preview": "{-|\nModule      : PostgREST.Auth.JwtCache\nDescription : PostgREST JWT validation results Cache.\n\nThis module provides fu"
  },
  {
    "path": "src/PostgREST/Auth/Types.hs",
    "chars": 388,
    "preview": "module PostgREST.Auth.Types\n  ( AuthResult (..) )\n  where\n\nimport qualified Data.Aeson        as JSON\nimport qualified D"
  },
  {
    "path": "src/PostgREST/Auth.hs",
    "chars": 2841,
    "preview": "{-# LANGUAGE RecordWildCards #-}\n{-|\nModule      : PostgREST.Auth\nDescription : PostgREST authentication functions.\n\nThi"
  },
  {
    "path": "src/PostgREST/CLI.hs",
    "chars": 4575,
    "preview": "{-# LANGUAGE NamedFieldPuns  #-}\n{-# LANGUAGE RecordWildCards #-}\nmodule PostgREST.CLI\n  ( main\n  , CLI (..)\n  , Command"
  },
  {
    "path": "src/PostgREST/Cache/Sieve.hs",
    "chars": 8657,
    "preview": "{-|\nModule      : PostgREST.Cache.Sieve\nDescription : PostgREST cache implementation based on Sieve algorithm.\n\nThis mod"
  },
  {
    "path": "src/PostgREST/Client.hs",
    "chars": 4240,
    "preview": "{-|\nModule      : PostgREST.Client\nDescription : PostgREST HTTP client\n-}\n{-# LANGUAGE NamedFieldPuns #-}\nmodule PostgRE"
  },
  {
    "path": "src/PostgREST/Config/Database.hs",
    "chars": 7280,
    "preview": "{-# LANGUAGE QuasiQuotes #-}\n\nmodule PostgREST.Config.Database\n  ( pgVersionStatement\n  , queryDbSettings\n  , queryPgVer"
  },
  {
    "path": "src/PostgREST/Config/JSPath.hs",
    "chars": 5351,
    "preview": "{-# OPTIONS_GHC -Wno-unused-do-bind #-}\n{-# LANGUAGE LambdaCase #-}\nmodule PostgREST.Config.JSPath\n  ( JSPath\n  , JSPath"
  },
  {
    "path": "src/PostgREST/Config/PgVersion.hs",
    "chars": 930,
    "preview": "{-# LANGUAGE DeriveAnyClass #-}\n{-# LANGUAGE DeriveGeneric  #-}\nmodule PostgREST.Config.PgVersion\n  ( PgVersion(..)\n  , "
  },
  {
    "path": "src/PostgREST/Config/Proxy.hs",
    "chars": 2045,
    "preview": "{-|\nModule      : PostgREST.Private.ProxyUri\nDescription : Proxy Uri validator\n-}\nmodule PostgREST.Config.Proxy\n  ( Prox"
  },
  {
    "path": "src/PostgREST/Config.hs",
    "chars": 35527,
    "preview": "{-|\nModule      : PostgREST.Config\nDescription : Manages PostgREST configuration type and parser.\n\n-}\n{-# LANGUAGE Flexi"
  },
  {
    "path": "src/PostgREST/Cors.hs",
    "chars": 1885,
    "preview": "{-|\nModule      : PostgREST.Cors\nDescription : Wai Middleware to set cors policy.\n-}\n\n{-# LANGUAGE TupleSections #-}\n\nmo"
  },
  {
    "path": "src/PostgREST/Error/Types.hs",
    "chars": 3342,
    "preview": "{-|\nModule      : PostgREST.Error.Types\nDescription : PostgREST Error Data Types\n-}\nmodule PostgREST.Error.Types\n  ( Api"
  },
  {
    "path": "src/PostgREST/Error.hs",
    "chars": 34761,
    "preview": "{-|\nModule      : PostgREST.Error\nDescription : PostgREST error HTTP responses\n-}\n{-# OPTIONS_GHC -fno-warn-orphans #-}\n"
  },
  {
    "path": "src/PostgREST/Listener.hs",
    "chars": 4540,
    "preview": "{-# LANGUAGE LambdaCase      #-}\n{-# LANGUAGE MultiWayIf      #-}\n{-# LANGUAGE RecordWildCards #-}\n\nmodule PostgREST.Lis"
  },
  {
    "path": "src/PostgREST/Logger.hs",
    "chars": 11485,
    "preview": "{-# LANGUAGE LambdaCase      #-}\n{-# LANGUAGE RecordWildCards #-}\n{-# LANGUAGE RecursiveDo     #-}\n{-|\nModule      : Pos"
  },
  {
    "path": "src/PostgREST/MainTx.hs",
    "chars": 12829,
    "preview": "{-# LANGUAGE NamedFieldPuns  #-}\n{-# LANGUAGE RecordWildCards #-}\n{-|\nModule      : PostgREST.MainTx\nDescription : Postg"
  },
  {
    "path": "src/PostgREST/MediaType.hs",
    "chars": 8803,
    "preview": "{-# LANGUAGE DeriveAnyClass        #-}\n{-# LANGUAGE DeriveGeneric         #-}\n{-# LANGUAGE DuplicateRecordFields #-}\n{-#"
  },
  {
    "path": "src/PostgREST/Metrics.hs",
    "chars": 3078,
    "preview": "{-# LANGUAGE RecordWildCards #-}\n{-|\nModule      : PostgREST.Logger\nDescription : Metrics based on the Observation modul"
  },
  {
    "path": "src/PostgREST/Network.hs",
    "chars": 2023,
    "preview": "module PostgREST.Network\n  ( resolveSocketToAddress\n  , escapeHostName\n  , isSpecialHostName\n  ) where\n\nimport          "
  },
  {
    "path": "src/PostgREST/Observation.hs",
    "chars": 2384,
    "preview": "{-|\nModule      : PostgREST.Observation\nDescription : This module holds an Observation type which is the core of Observa"
  },
  {
    "path": "src/PostgREST/Plan/CallPlan.hs",
    "chars": 2691,
    "preview": "{-# LANGUAGE NamedFieldPuns #-}\nmodule PostgREST.Plan.CallPlan\n  ( CallPlan(..)\n  , CallParams(..)\n  , CallArgs(..)\n  , "
  },
  {
    "path": "src/PostgREST/Plan/MutatePlan.hs",
    "chars": 1158,
    "preview": "module PostgREST.Plan.MutatePlan\n  ( MutatePlan(..)\n  )\nwhere\n\nimport qualified Data.ByteString.Lazy as LBS\n\nimport Post"
  },
  {
    "path": "src/PostgREST/Plan/Negotiate.hs",
    "chars": 4721,
    "preview": "{-|\nModule      : PostgREST.Plan.Negotiate\nDescription : PostgREST Content Negotiation\n\nThis module contains logic for c"
  },
  {
    "path": "src/PostgREST/Plan/ReadPlan.hs",
    "chars": 1741,
    "preview": "module PostgREST.Plan.ReadPlan\n  ( ReadPlanTree\n  , ReadPlan(..)\n  , JoinCondition(..)\n  , SpreadType(..)\n  ) where\n\nimp"
  },
  {
    "path": "src/PostgREST/Plan/Types.hs",
    "chars": 6425,
    "preview": "module PostgREST.Plan.Types\n  ( CoercibleField(..)\n  , CoercibleSelectField(..)\n  , unknownField\n  , CoercibleLogicTree("
  },
  {
    "path": "src/PostgREST/Plan.hs",
    "chars": 62829,
    "preview": "{-|\nModule      : PostgREST.Plan\nDescription : PostgREST Request Planner\n\nThis module is in charge of building an interm"
  },
  {
    "path": "src/PostgREST/Query/PreQuery.hs",
    "chars": 3589,
    "preview": "{-# LANGUAGE NamedFieldPuns  #-}\n{-# LANGUAGE RecordWildCards #-}\n{-|\nModule      : PostgREST.Query.PreQuery\nDescription"
  },
  {
    "path": "src/PostgREST/Query/QueryBuilder.hs",
    "chars": 14936,
    "preview": "{-# LANGUAGE DuplicateRecordFields #-}\n{-# LANGUAGE NamedFieldPuns        #-}\n{-# LANGUAGE RecordWildCards       #-}\n{-|"
  },
  {
    "path": "src/PostgREST/Query/SqlFragment.hs",
    "chars": 33825,
    "preview": "{-# LANGUAGE LambdaCase     #-}\n{-# LANGUAGE NamedFieldPuns #-}\n{-# LANGUAGE QuasiQuotes    #-}\n{-|\nModule      : PostgR"
  },
  {
    "path": "src/PostgREST/Query/Statements.hs",
    "chars": 4834,
    "preview": "{-# LANGUAGE NamedFieldPuns #-}\n{-|\nModule      : PostgREST.Query.Statements\nDescription : PostgREST main queries\n-}\nmod"
  },
  {
    "path": "src/PostgREST/Query.hs",
    "chars": 3159,
    "preview": "{-# LANGUAGE RecordWildCards #-}\n{-|\nModule      : PostgREST.Query\nDescription : PostgREST query building\n\nTODO: This mo"
  },
  {
    "path": "src/PostgREST/RangeQuery.hs",
    "chars": 3923,
    "preview": "{-|\nModule      : PostgREST.RangeQuery\nDescription : Logic regarding the `Range`/`Content-Range` headers and `limit`/`of"
  },
  {
    "path": "src/PostgREST/Response/GucHeader.hs",
    "chars": 813,
    "preview": "module PostgREST.Response.GucHeader\n  ( GucHeader\n  , unwrapGucHeader\n  ) where\n\nimport qualified Data.Aeson           a"
  },
  {
    "path": "src/PostgREST/Response/OpenAPI.hs",
    "chars": 18127,
    "preview": "{-|\nModule      : PostgREST.OpenAPI\nDescription : Generates the OpenAPI output\n-}\n{-# LANGUAGE LambdaCase      #-}\n{-# L"
  },
  {
    "path": "src/PostgREST/Response/Performance.hs",
    "chars": 1379,
    "preview": "module PostgREST.Response.Performance\n  ( ServerTiming (..)\n  , serverTimingHeader\n  )\nwhere\nimport qualified Data.ByteS"
  },
  {
    "path": "src/PostgREST/Response.hs",
    "chars": 14480,
    "preview": "{- |\n   Module      : PostgREST.Response\n   Description : Generate HTTP Response\n-}\n{-# LANGUAGE NamedFieldPuns  #-}\n{-#"
  },
  {
    "path": "src/PostgREST/SchemaCache/Identifiers.hs",
    "chars": 1964,
    "preview": "{-# LANGUAGE DeriveAnyClass #-}\n{-# LANGUAGE DeriveGeneric  #-}\n\nmodule PostgREST.SchemaCache.Identifiers\n  ( FieldName\n"
  },
  {
    "path": "src/PostgREST/SchemaCache/Relationship.hs",
    "chars": 2416,
    "preview": "{-# LANGUAGE DeriveAnyClass #-}\n{-# LANGUAGE DeriveGeneric  #-}\n\nmodule PostgREST.SchemaCache.Relationship\n  ( Cardinali"
  },
  {
    "path": "src/PostgREST/SchemaCache/Representations.hs",
    "chars": 1195,
    "preview": "{-# LANGUAGE DeriveAnyClass #-}\n{-# LANGUAGE DeriveGeneric  #-}\n\nmodule PostgREST.SchemaCache.Representations\n  ( DataRe"
  },
  {
    "path": "src/PostgREST/SchemaCache/Routine.hs",
    "chars": 5230,
    "preview": "{-# LANGUAGE DeriveAnyClass #-}\n{-# LANGUAGE DeriveGeneric  #-}\n\nmodule PostgREST.SchemaCache.Routine\n  ( PgType(..)\n  ,"
  },
  {
    "path": "src/PostgREST/SchemaCache/Table.hs",
    "chars": 1765,
    "preview": "{-# LANGUAGE DeriveAnyClass    #-}\n{-# LANGUAGE DeriveGeneric     #-}\n{-# LANGUAGE FlexibleInstances #-}\n\nmodule PostgRE"
  },
  {
    "path": "src/PostgREST/SchemaCache.hs",
    "chars": 49597,
    "preview": "{-|\nModule      : PostgREST.SchemaCache\nDescription : PostgREST schema cache\n\nThis module(used to be named DbStructure) "
  },
  {
    "path": "src/PostgREST/TimeIt.hs",
    "chars": 614,
    "preview": "module PostgREST.TimeIt\n  ( timeItT\n  ) where\n\nimport GHC.Clock\nimport Protolude\n\n{-\n - The signature is the same as htt"
  },
  {
    "path": "src/PostgREST/Unix.hs",
    "chars": 1830,
    "preview": "{-# LANGUAGE CPP #-}\n\nmodule PostgREST.Unix\n  ( installSignalHandlers\n  , createAndBindDomainSocket\n  ) where\n\n#ifndef m"
  },
  {
    "path": "src/PostgREST/Version.hs",
    "chars": 913,
    "preview": "{-# LANGUAGE CPP #-}\nmodule PostgREST.Version\n  ( docsVersion\n  , prettyVersion\n  ) where\n\nimport qualified Data.Text as"
  },
  {
    "path": "stack.yaml",
    "chars": 545,
    "preview": "resolver: lts-22.44 # 2025-05-02, GHC 9.6.7\n\nnix:\n  packages:\n    - libpq\n    - pkg-config\n    - zlib\n  # disable pure b"
  },
  {
    "path": "test/coverage.overlay",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "test/doc/Main.hs",
    "chars": 673,
    "preview": "module Main (main) where\n\nimport Test.DocTest (doctest)\n\nimport Protolude\n\n\nmain :: IO ()\nmain =\n  doctest\n    [ \"-XOver"
  },
  {
    "path": "test/io/__snapshots__/test_cli/test_schema_cache_snapshot[dbMediaHandlers].yaml",
    "chars": 405,
    "preview": "- - - tag: RelAnyElement\n    - tag: MTTextCSV\n  - - tag: BuiltinOvAggCsv\n    - tag: MTTextCSV\n\n- - - tag: RelAnyElement\n"
  },
  {
    "path": "test/io/__snapshots__/test_cli/test_schema_cache_snapshot[dbRelationships].yaml",
    "chars": 853,
    "preview": "- - - qiName: directors\n      qiSchema: public\n    - public\n  - - relCardinality:\n        relColumns:\n        - - id\n   "
  },
  {
    "path": "test/io/__snapshots__/test_cli/test_schema_cache_snapshot[dbRepresentations].yaml",
    "chars": 3,
    "preview": "[]\n"
  },
  {
    "path": "test/io/__snapshots__/test_cli/test_schema_cache_snapshot[dbRoutines].yaml",
    "chars": 14774,
    "preview": "- - qiName: rpc_with_two_hoisted\n    qiSchema: public\n  - - pdDescription: null\n      pdFuncSettings:\n      - - statemen"
  },
  {
    "path": "test/io/__snapshots__/test_cli/test_schema_cache_snapshot[dbTables].yaml",
    "chars": 4248,
    "preview": "- - qiName: authors_only\n    qiSchema: public\n  - tableColumns: {}\n    tableDeletable: true\n    tableDescription: null\n "
  },
  {
    "path": "test/io/__snapshots__/test_cli/test_schema_cache_snapshot[dbTimezones].yaml",
    "chars": 24184,
    "preview": "- Africa/Abidjan\n- Africa/Accra\n- Africa/Addis_Ababa\n- Africa/Algiers\n- Africa/Asmara\n- Africa/Asmera\n- Africa/Bamako\n- "
  },
  {
    "path": "test/io/config.py",
    "chars": 1084,
    "preview": "import os\nimport pathlib\nimport shutil\nimport uuid\nimport yaml\n\n\nBASEDIR = pathlib.Path(os.path.realpath(__file__)).pare"
  },
  {
    "path": "test/io/configs/aliases.config",
    "chars": 178,
    "preview": "db-schema = \"provided_through_alias\"\ndb-pool-timeout = 5\nmax-rows = 1000\npre-request = \"check_alias\"\nrole-claim-key = \"."
  }
]

// ... and 154 more files (download for full content)

About this extraction

This page contains the full source code of the PostgREST/postgrest GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 354 files (2.7 MB), approximately 715.4k tokens, and a symbol index with 853 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!