Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Add an example for PGRST_APP_SETTINGS_* #3804

Merged
merged 3 commits into from
Dec 1, 2024

Conversation

ceymard
Copy link
Contributor

@ceymard ceymard commented Nov 28, 2024

I had to figure stuff out and I thought it would be useful for everyone if I provided some more information

I had to figure stuff out and I thought it would be useful for everyone if I provided some more information
Copy link
Collaborator

@develop7 develop7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, definitely an improvement

@@ -191,6 +191,10 @@ app.settings.*

Arbitrary settings that can be used to pass in secret keys directly as strings, or via OS environment variables. For instance: :code:`app.settings.jwt_secret = "$(MYAPP_JWT_SECRET)"` will take :code:`MYAPP_JWT_SECRET` from the environment and make it available to PostgreSQL functions as :code:`current_setting('app.settings.jwt_secret')`.

When using the environment variable `PGRST_APP_SETTINGS_*` form, the remainder of the variable is used as the new name. Case is not important : :code:`PGRST_APP_SETTINGS_MY_ENV_VARIABLE=some_value` can be accessed in postgres as :code:`current_setting('app.settings.my_env_variable')`.

The :code:`current_setting` function has `an optional boolean second <https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET>`_ argument to avoid it from raising an error if the value was not defined. Default values to :code:`app.settings` can then easily be given by combining this argument with :code:`coalesce` : :code:`coalesce(current_setting('app.settings.my_custom_variable', true), 'default value')`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't always work. This is because GUCs have the strange effect that they are reset to an empty string in further transactions. This means coalesce(...) will work on the first request, but then maybe not later anymore.

You'd need something like this instead:

coalesce(nullif(current_setting('app.settings.my_custom_variable', true), ''), 'default value')

Additionally, I think this piece of advice is important for all other things that can be read via current_setting(...)... ah right, we already have a hint about that here: https://docs.postgrest.org/en/v12/references/transactions.html#request-headers-cookies-and-jwt-claims

So maybe don't talk specifically about current_setting here but link to the transactions page by saying "current_setting can be used with those app settings similar to how you can use it over there"?

Copy link
Member

@steve-chavez steve-chavez Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is quite important. I think we need to bring more attention to it. It occurs to me that we need to split the Transactions page and have a dedicated one on "Transaction-scoped settings" (maybe we should rename this as "Transactional settings" or "Transactional variables") and then have this note at the top-level.

@ceymard
Copy link
Contributor Author

ceymard commented Nov 28, 2024

@wolfgangwalther : I added a reference to the section you mentioned and edited the example to add nullif usage.

I believe that the example should stay : the motivation of this (very simple) PR was precisely to give the reader what I think the way they'll want to use it anyway. I did spend a good 30 minutes to 1 hour toying with the feature to "guess" how it worked, and even then I had no knowledge that the GUC was not reset in transactions - for which I thank you.

@@ -191,6 +191,10 @@ app.settings.*

Arbitrary settings that can be used to pass in secret keys directly as strings, or via OS environment variables. For instance: :code:`app.settings.jwt_secret = "$(MYAPP_JWT_SECRET)"` will take :code:`MYAPP_JWT_SECRET` from the environment and make it available to PostgreSQL functions as :code:`current_setting('app.settings.jwt_secret')`.

When using the environment variable `PGRST_APP_SETTINGS_*` form, the remainder of the variable is used as the new name. Case is not important : :code:`PGRST_APP_SETTINGS_MY_ENV_VARIABLE=some_value` can be accessed in postgres as :code:`current_setting('app.settings.my_env_variable')`.

The :code:`current_setting` function has `an optional boolean second <https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET>`_ argument to avoid it from raising an error if the value was not defined. Default values to :code:`app.settings` can then easily be given by combining this argument with :code:`coalesce` and :code:`nullif` : :code:`coalesce(nullif(current_setting('app.settings.my_custom_variable', true), ''), 'default value')`. The use of :code:`nullif` is necessary because if set in a transaction, the setting is sometimes not "rolled back" to :code:`null`. See also :ref:`this section <guc_req_headers_cookies_claims>` for more information on this behaviour.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to remove "easily" (related).

Suggested change
The :code:`current_setting` function has `an optional boolean second <https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET>`_ argument to avoid it from raising an error if the value was not defined. Default values to :code:`app.settings` can then easily be given by combining this argument with :code:`coalesce` and :code:`nullif` : :code:`coalesce(nullif(current_setting('app.settings.my_custom_variable', true), ''), 'default value')`. The use of :code:`nullif` is necessary because if set in a transaction, the setting is sometimes not "rolled back" to :code:`null`. See also :ref:`this section <guc_req_headers_cookies_claims>` for more information on this behaviour.
The :code:`current_setting` function has `an optional boolean second <https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-SET>`_ argument to avoid it from raising an error if the value was not defined. Default values to :code:`app.settings` can then be given by combining this argument with :code:`coalesce` and :code:`nullif` : :code:`coalesce(nullif(current_setting('app.settings.my_custom_variable', true), ''), 'default value')`. The use of :code:`nullif` is necessary because if set in a transaction, the setting is sometimes not "rolled back" to :code:`null`. See also :ref:`this section <guc_req_headers_cookies_claims>` for more information on this behaviour.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry I did another commit to remove easily, I'm not very familiar with github's capabilities

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, I can just squash the commits. Nice work!

@steve-chavez steve-chavez merged commit c5a9455 into PostgREST:main Dec 1, 2024
4 checks passed
@ceymard ceymard deleted the patch-1 branch December 1, 2024 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants