From 048daf81d1871b52fb9e9266393335ed9c875d13 Mon Sep 17 00:00:00 2001 From: Marion Schleifer Date: Tue, 6 Oct 2020 18:04:58 +0200 Subject: [PATCH] docs: add postgres reference section to docs (close #4440) (#4471) https://github.com/hasura/graphql-engine/pull/4471 --- CHANGELOG.md | 1 + docs/graphql/core/guides/index.rst | 1 + .../core/guides/postgres/constraints.rst | 122 ++++++++++++++++++ .../core/guides/postgres/functions.rst | 56 ++++++++ docs/graphql/core/guides/postgres/index.rst | 57 ++++++++ docs/graphql/core/guides/postgres/indexes.rst | 48 +++++++ .../graphql/core/guides/postgres/triggers.rst | 89 +++++++++++++ docs/graphql/core/guides/postgres/views.rst | 108 ++++++++++++++++ docs/graphql/core/queries/performance.rst | 2 + docs/graphql/core/schema/custom-functions.rst | 2 + docs/graphql/core/schema/data-validations.rst | 4 + 11 files changed, 490 insertions(+) create mode 100644 docs/graphql/core/guides/postgres/constraints.rst create mode 100644 docs/graphql/core/guides/postgres/functions.rst create mode 100644 docs/graphql/core/guides/postgres/index.rst create mode 100644 docs/graphql/core/guides/postgres/indexes.rst create mode 100644 docs/graphql/core/guides/postgres/triggers.rst create mode 100644 docs/graphql/core/guides/postgres/views.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index de1d46777d07e..ee4aec1a32fa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ This release contains the [PDV refactor (#4111)](https://github.com/hasura/graph - console: add `<3 hasura` section to view updates and notifications from Hasura (#5070) - cli: add missing global flags for seeds command (#5565) - docs: add docs page on networking with docker (close #4346) (#4811) +- docs: add postgres concepts page to docs (close #4440) (#4471) ## `v1.3.2` diff --git a/docs/graphql/core/guides/index.rst b/docs/graphql/core/guides/index.rst index 0f455cfc48ef1..d9ddc5c7fdc87 100644 --- a/docs/graphql/core/guides/index.rst +++ b/docs/graphql/core/guides/index.rst @@ -17,6 +17,7 @@ Guides / Tutorials / Resources :titlesonly: Data modelling guides + Postgres concepts Docker networking Sample apps & boilerplates Integration/migration tutorials diff --git a/docs/graphql/core/guides/postgres/constraints.rst b/docs/graphql/core/guides/postgres/constraints.rst new file mode 100644 index 0000000000000..26422dc082fce --- /dev/null +++ b/docs/graphql/core/guides/postgres/constraints.rst @@ -0,0 +1,122 @@ +.. meta:: + :description: Use Postgres constraints with Hasura + :keywords: hasura, docs, postgres, constraints + +.. _postgres_constraints: + +Postgres constraints +==================== + +.. contents:: Table of contents + :backlinks: none + :depth: 2 + :local: + +Introduction +------------ + +`Postgres constraints `__ are used to define rules for columns in a database table. They ensure that +no invalid data is entered into the database. + +.. note:: + + For more detailed information on Postgres constraints, please refer to the `Postgres documentation `__. + +Postgres constraints +-------------------- + +There are different types of constraints that can be used with Postgres. + +Primary key constraints +^^^^^^^^^^^^^^^^^^^^^^^ + +A ``PRIMARY KEY`` is used to identify each row of a table uniquely. + +**Identify the author's id as the primary key of the authors table:** + +.. code-block:: sql + :emphasize-lines: 2 + + CREATE TABLE authors( + id INT PRIMARY KEY, + name TEXT NOT NULL + ); + +Foreign key constraints +^^^^^^^^^^^^^^^^^^^^^^^ + +A foreign key constraint specifies that the values in a column must match the values appearing in a row of another table. +Foreign key constraints are used to create relationships between tables. + +**Define the author_id in the articles table as a foreign key to the id column in the authors table:** + +.. code-block:: sql + :emphasize-lines: 11 + + CREATE TABLE authors( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + email TEXT UNIQUE + ); + + CREATE TABLE articles( + id SERIAL PRIMARY KEY, + title TEXT NOT NULL, + author_id INTEGER, + FOREIGN KEY (author_id) REFERENCES authors (id) + ); + +Not-null constraints +^^^^^^^^^^^^^^^^^^^^ + +A not-null constraint allows you to specify that a column's value cannot be ``null``. + +**Validate that an author's name cannot be null:** + +.. code-block:: sql + :emphasize-lines: 2-3 + + CREATE TABLE authors( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL + ); + +Unique constraints +^^^^^^^^^^^^^^^^^^ + +Unique constraints prevent database entries with a duplicate value of the respective column. + +**Validate that an author's email is unique:** + +.. code-block:: sql + :emphasize-lines: 4 + + CREATE TABLE authors( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + email TEXT UNIQUE + ); + +Check constraints +^^^^^^^^^^^^^^^^^ + +Check constraints allow you to specify a ``Boolean`` expression for one or several columns. +This Boolean expression must be satisfied (equal to ``true``) by the column value for the object to be inserted. + +**Validate that an author's rating is between 1 and 10:** + +.. code-block:: sql + :emphasize-lines: 4 + + CREATE TABLE authors( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + rating INT NOT NULL CHECK(rating > 0 AND rating <= 10) + ); + +Postgres constraints & Hasura +----------------------------- + +Most Postgres constraints (primary key, foreign key, not-null and unique constraints) can be added to Hasura natively when :ref:`creating tables `. + +Postgres check constraints can be used as a form of data validation in Hasura and can be added :ref:`as described here `. diff --git a/docs/graphql/core/guides/postgres/functions.rst b/docs/graphql/core/guides/postgres/functions.rst new file mode 100644 index 0000000000000..67c3e1e77b32f --- /dev/null +++ b/docs/graphql/core/guides/postgres/functions.rst @@ -0,0 +1,56 @@ +.. meta:: + :description: Use Postgres functions with Hasura + :keywords: hasura, docs, postgres, functions + +.. _postgres_functions: + +Postgres functions +================== + +.. contents:: Table of contents + :backlinks: none + :depth: 1 + :local: + +Introduction +------------ + +`Postgres functions `__ allow you to customize your database schema by defining a set of operations that can include several statements such as declarations, assignments and conditional workflows. +Postgres functions are similar to views but allow more procedural computations and can take arguments. + +.. note:: + + For more information on Postgres functions, please refer to the `Postgres documentation `__. + +Examples +-------- + +**Searching articles** + +We can create the following function that we can call later to search articles based on the input text argument ``search``. + +.. code-block:: plpgsql + + CREATE FUNCTION search_articles(search text) + RETURNS SETOF article AS $$ + SELECT * + FROM article + WHERE + title ilike ('%' || search || '%') + OR content ilike ('%' || search || '%') + $$ LANGUAGE sql STABLE; + +Let's break this function apart: + +- Function name: ``search_articles`` +- Parameters: there is one parameter where ``search`` is the name and ``text`` is the type +- Return type: ``SETOF article`` +- Function body: Block from ``SELECT`` until the end of the ``WHERE`` clause +- Language: The response is returned in the ``sql`` language + +Postgres functions & Hasura +--------------------------- + +Postgres functions can be exposed in Hasura's GraphQL schema as a top-level field or as a computed field for a table. They are typically used for performing custom business logic in the database. + +Refer to :ref:`Custom SQL functions ` and :ref:`Computed fields ` for more use cases and for instructions on how to create and expose Postgres functions in Hasura. diff --git a/docs/graphql/core/guides/postgres/index.rst b/docs/graphql/core/guides/postgres/index.rst new file mode 100644 index 0000000000000..a6f7030844b34 --- /dev/null +++ b/docs/graphql/core/guides/postgres/index.rst @@ -0,0 +1,57 @@ +.. meta:: + :description: Useful Postgres concepts for Hasura + :keywords: hasura, docs, postgres + +.. _postgres_concepts: + +Postgres concepts +================= + +.. contents:: Table of contents + :backlinks: none + :depth: 2 + :local: + +Introduction +------------ + +This page introduces Postgres including benefits and caveats, and it links to sections relevant to extending your GraphQL API by using Postgres features. + +About Postgres +-------------- + +`Postgres (or PostgreSQL) `__ is a general-purpose object-relational database management system that uses and extends the SQL language. +Postgres is free and open source and has been developed continuously over the last 30 years. Postgres strives to be reliable, robust and performant. + +Postgres supports advanced data types and advanced performance optimization, features that are otherwise only available in expensive commercial database systems. + +Benefits of Postgres +-------------------- + +The following are benefits of Postgres compared to other database management systems: + +- Postgres can be maintained easily because of its stability. The total cost of ownership is therefore low. +- Postgres is designed to be extensible i.e. you can add custom functions using different programming languages. +- You can define your own data types, index types etc. +- If you need any support, an `active community `__ is available to help. + +Postgres features +----------------- + +The following are some Postgres features that can be used to manage your data and extend your Hasura GraphQL API: + +- :ref:`Constraints ` +- :ref:`Views ` +- :ref:`Functions ` +- :ref:`Triggers ` +- :ref:`Indexes ` + +.. toctree:: + :maxdepth: 1 + :hidden: + + Constraints + Views + Functions + Triggers + Indexes diff --git a/docs/graphql/core/guides/postgres/indexes.rst b/docs/graphql/core/guides/postgres/indexes.rst new file mode 100644 index 0000000000000..f73caf93dc317 --- /dev/null +++ b/docs/graphql/core/guides/postgres/indexes.rst @@ -0,0 +1,48 @@ +.. meta:: + :description: Use Postgres indexes with Hasura + :keywords: hasura, docs, postgres, indexes + +.. _postgres_indexes: + +Postgres indexes +================ + +.. contents:: Table of contents + :backlinks: none + :depth: 1 + :local: + +Introduction +------------ + +`Postgres indexes `__ are a way of increasing query performance +based on columns that are queried frequently. The concept is similar to the one of an index in a book. +It helps accessing the data you're looking for more quickly by maintaining additional metadata. + +.. note:: + + Learn more about indexes in the `Postgres documentation `__. + +Example +------- + +**Create an index on the column name in the table authors:** + +Let's say the database receives a large number of requests of authors being queried by their name, for example: + +.. code-block:: sql + + SELECT * FROM authors WHERE name = 'J.K. Rowling'; + +We can now create an index on the ``name`` column of the ``authors`` table: + +.. code-block:: sql + + CREATE INDEX author_name_index ON authors (name); + +Since the database is now able to look up the result of these queries more quickly, the performance of these queries will increase significantly. + +Postgres indexes & Hasura +------------------------- + +Indexes can be used to optimize query performance in Hasura. :ref:`Refer to this page ` for information about query performance and how to add Postgres indexes to Hasura. diff --git a/docs/graphql/core/guides/postgres/triggers.rst b/docs/graphql/core/guides/postgres/triggers.rst new file mode 100644 index 0000000000000..16a7e5996b8d9 --- /dev/null +++ b/docs/graphql/core/guides/postgres/triggers.rst @@ -0,0 +1,89 @@ +.. meta:: + :description: Use Postgres triggers with Hasura + :keywords: hasura, docs, postgres, triggers + +.. _postgres_triggers: + +Postgres triggers +================= + +.. contents:: Table of contents + :backlinks: none + :depth: 1 + :local: + +Introduction +------------ + +`Postgres triggers `__ are used to invoke previously defined Postgres functions *before* or *after* a specific database event (e.g. ``INSERT``) occurs. + +.. note:: + + For more information on Postgres triggers, please refer to the `Postgres documentation `__. + +Examples +-------- + +**Trigger a Postgres function before an article is inserted or updated:** + +Let's say we want to check if an author is active before a corresponding article can be inserted or updated. +We can do so with the following Postgres function: + +.. code-block:: plpgsql + + CREATE FUNCTION check_author_active() + RETURNS trigger AS $BODY$ + DECLARE active_author BOOLEAN; + BEGIN + SELECT author.is_active INTO active_author FROM "authors" author WHERE author.id = NEW."author_id"; + IF active_author != TRUE THEN + RAISE EXCEPTION 'Author must be active'; + END IF; + RETURN NEW; + END; + $BODY$ LANGUAGE plpgsql; + +Now we want to have this function executed whenever a new article is about to be inserted or updated. +We can create a Postgres trigger as follows: + +.. code-block:: plpgsql + + CREATE TRIGGER insert_article BEFORE INSERT OR UPDATE ON "articles" FOR EACH ROW EXECUTE PROCEDURE check_author_active(); + +If someone now tries to insert an article for an author that is not active, the following error will be thrown: + +.. code-block:: plpgsql + + unexpected : Author must be active + +**Refresh a materialized view when an author gets inserted:** + +Let's say we want to refresh a materialized view whenever a new author is inserted. + +The following Postgres function refreshes a materialized view: + +.. code-block:: plpgsql + + CREATE FUNCTION refresh_materialized_view() + RETURNS trigger AS $BODY$ + BEGIN + REFRESH MATERIALIZED VIEW popular_active_authors; + RETURN NULL; + END; + $BODY$ LANGUAGE plpgsql; + +Now, to make sure this function gets called whenever a new author is inserted, we can create the following Postgres trigger: + +.. code-block:: plpgsql + + CREATE TRIGGER update_materialized_view AFTER INSERT ON "authors" FOR EACH ROW EXECUTE PROCEDURE refresh_materialized_view(); + +Postgres triggers & Hasura +-------------------------- + +Postgres triggers can be used to perform business logic such as data validation and can be added :ref:`as described here `. + +.. note:: + + Hasura also has :ref:`event triggers ` that can be used to invoke external HTTP APIs for executing custom business logic on + database events. diff --git a/docs/graphql/core/guides/postgres/views.rst b/docs/graphql/core/guides/postgres/views.rst new file mode 100644 index 0000000000000..f45c76db3e722 --- /dev/null +++ b/docs/graphql/core/guides/postgres/views.rst @@ -0,0 +1,108 @@ +.. meta:: + :description: Use Postgres views with Hasura + :keywords: hasura, docs, postgres, views + +.. _postgres_views: + +Postgres views +============== + +.. contents:: Table of contents + :backlinks: none + :depth: 1 + :local: + +Introduction +------------ + +A `Postgres view `__ is a virtual table in Postgres. It represents the result of a query to one or more underlying tables in Postgres. +Views are used to simplify complex queries since these queries are defined once in the view, and can then be directly queried via the same. + +.. note:: + + Please refer to the Postgres documentation for more details on `standard views `__ and `materialized views `__. + +Standard views +-------------- + +`Standard views `__ represent the result of a query without actually storing data. + +Examples +******** + +**View with authors whose rating is larger than 6:** + +.. code-block:: sql + + CREATE VIEW popular_authors AS + SELECT name, rating + FROM authors + WHERE rating > 6; + +The created view can now be queried as follows: + +.. code-block:: sql + + SELECT name, rating from popular_authors; + +**View with authors ordered by their rating:** + +.. code-block:: sql + + CREATE VIEW authors_ordered_by_rating AS + SELECT name, rating + FROM authors + ORDER BY rating; + +The created view can now be queried as follows: + +.. code-block:: sql + + SELECT name, rating from authors_ordered_by_rating; + +Materialized views +------------------ + +Compared to the standard view described above, `materialized views `__ **do** store data physically in the database. +Materialized views are used if data from complex queries needs to be accessed quickly. + +Example +******* + +.. _pg_materialized_view_example: + +**Materialized view with authors whose rating is larger than 6 and who are active, ordered by rating:** + +.. code-block:: sql + + CREATE MATERIALIZED VIEW popular_active_authors AS + SELECT name, rating + FROM authors + WHERE rating > 6 AND is_active = TRUE + ORDER BY rating; + +The created materialized view can now be queried as follows: + +.. code-block:: sql + + SELECT name, rating from popular_active_authors; + +Refreshing materialized views +***************************** + +Materialized views don't always have the most recent data. +Since the result of a query is stored in a materialized view like in a cache, you need to make sure to refresh it periodically: + +.. code-block:: sql + + REFRESH MATERIALIZED VIEW popular_active_authors; + +Materialized views can be refreshed when their underlying source data changes using :ref:`Postgres triggers `. + + +Postgres views & Hasura +----------------------- + +After creating a view, you can expose it over your GraphQL API and query it like a normal table. + +See :ref:`this page ` for more info on how to create and expose views in Hasura. diff --git a/docs/graphql/core/queries/performance.rst b/docs/graphql/core/queries/performance.rst index 36d89fb45746d..bf93a660ca221 100644 --- a/docs/graphql/core/queries/performance.rst +++ b/docs/graphql/core/queries/performance.rst @@ -186,6 +186,8 @@ If the ``!`` is not added and the variable is nullable, the generated query will Hasura is fast even for queries which cannot have a reusable plan. This should concern you only if you face a high volume of traffic (thousands of requests per second). +.. _data_validation_pg_indexes: + Using PG indexes ^^^^^^^^^^^^^^^^ diff --git a/docs/graphql/core/schema/custom-functions.rst b/docs/graphql/core/schema/custom-functions.rst index b567add40521b..78821b447e968 100644 --- a/docs/graphql/core/schema/custom-functions.rst +++ b/docs/graphql/core/schema/custom-functions.rst @@ -37,6 +37,8 @@ Currently, only functions which satisfy the following constraints can be exposed - **Return type**: MUST be ``SETOF `` - **Argument modes**: ONLY ``IN`` +.. _create_and_expose_sql_functions: + Creating & exposing SQL functions --------------------------------- diff --git a/docs/graphql/core/schema/data-validations.rst b/docs/graphql/core/schema/data-validations.rst index dd71d87627aa5..7c012323b1af6 100644 --- a/docs/graphql/core/schema/data-validations.rst +++ b/docs/graphql/core/schema/data-validations.rst @@ -34,6 +34,8 @@ validation logic and the layer where you would like to add it. These solutions are explained in some more detail below. +.. _data_validations_check_constraints: + Using Postgres check constraints -------------------------------- @@ -85,6 +87,8 @@ error is thrown: Learn more about `Postgres check constraints `__. +.. _data_validations_pg_triggers: + Using Postgres triggers -----------------------