Edit SQL files
==============
You should be familiar with SQL and the `Open Contracting Data Standard `__. You don't need to know Python, as there's no need to touch Kingfisher Summarize's Python files, only its SQL files.
This how-to guide will walk you through the steps of editing SQL files (if you haven't already, please follow the :doc:`setup` guide):
#. Make your changes to the SQL files
#. :ref:`Review your changes`
#. :ref:`Update the documentation`
#. Run the tests, to make sure your changes were successful and didn't break anything else.
.. code-block:: bash
pytest
#. To merge your changes, :ref:`push your changes to GitHub and make a pull request`
Make changes
------------
Example: Add a column
~~~~~~~~~~~~~~~~~~~~~
We want to add the ``description`` values of the ``Tender`` and ``Award`` objects to the :ref:`tender_summary` and :ref:`awards_summary` views. (Note: This is already done.)
#. Find the SQL file to change.
- The ``tender_summary.sql`` file contains the ``CREATE VIEW tender_summary`` statement.
#. Find the SQL statement to change.
- The ``tender_summary`` view selects from the ``tender_summary_no_data`` table.
#. Add the ``description`` field to the ``SELECT`` clause for the ``tender_summary_no_data`` table.
- You can see the other OCDS fields in the statement. Add it alongside those.
.. code-block:: sql
CREATE TABLE tender_summary_no_data AS
SELECT
r.id,
r.release_type,
r.collection_id,
r.ocid,
r.release_id,
r.data_id,
tender ->> 'id' AS tender_id,
tender ->> 'title' AS tender_title,
tender ->> 'status' AS tender_status,
tender ->> 'description' AS tender_description, -- OUR ADDITION
...
#. Do the same for the table summarizing the ``Award`` object, by editing the ``SELECT`` clause for the ``awards_summary_no_data`` table in the ``awards_summary.sql`` file.
.. code-block:: sql
...
award ->> 'title' AS award_title,
award ->> 'status' AS award_status,
award ->> 'description' AS award_description, -- OUR ADDITION
...
Example: Add an aggregate
~~~~~~~~~~~~~~~~~~~~~~~~~
We want to add the number of ``Document`` objects (in total and for each ``documentType`` value) across all ``Planning`` objects to the :ref:`release_summary` view. (Note: This is already done.)
``tender_document_documenttype_counts`` and ``total_tender_documents`` columns already exist for ``Tender`` objects. We can follow their example to add ``planning_document_documenttype_counts`` and ``total_planning_documents`` columns.
This example demonstrates how temporary (``tmp_*``) tables are used to build final tables.
#. The ``tender_document_documenttype_counts`` term occurs in the ``agg_tender.sql`` file, which populates a ``tmp_tender_documents_aggregates`` table with that column. Following this template, we create this file:
.. code-block:: sql
CREATE TABLE tmp_planning_documents_aggregates AS
SELECT
id,
jsonb_object_agg(coalesce(documentType, ''), documentType_count) planning_document_documenttype_counts
FROM (
SELECT
id,
documentType,
count(*) documentType_count
FROM
planning_documents_summary
GROUP BY
id,
documentType) AS d
GROUP BY
id;
CREATE UNIQUE INDEX tmp_planning_documents_aggregates_id ON tmp_planning_documents_aggregates (id);
#. Next, the ``tmp_tender_documents_aggregates`` term occurs in the ``release_summary.sql`` file, which ``JOIN`` s the table into the ``release_summary_no_data`` table. Following this template, we add this clause in that file:
.. code-block:: sql
LEFT JOIN tmp_planning_documents_aggregates USING (id)
#. Next, the ``total_tender_documents`` term occurs in the ``release_summary.sql`` file, in a ``JOIN`` clause. Following this template, we add this clause in that file:
.. code-block:: sql
LEFT JOIN (
SELECT
id,
documents_count AS total_planning_documents
FROM
planning_summary) AS planning_summary USING (id)
#. Finally, drop the ``tmp_`` table in the ``sql/final/drop.sql`` file:
.. code-block:: sql
DROP TABLE tmp_planning_documents_aggregates;
.. note::
The order of the ``JOIN`` s controls the order of the columns in the table.
.. _review-changes:
Review changes
--------------
Review your changes by comparing to the initial summaries you created when :ref:`loading data`. Create new summaries:
.. code-block:: bash
./manage.py add 1 "Review new column" --name review_new_column
Then, check that the data is as you expect it to be. (If you're viewing the data in a PostgreSQL client, don't forget to refresh it.)
.. _add-docs:
Update documentation
--------------------
The tests won't pass if you don't document the new columns!
#. Edit the ``docs.sql`` file to add comments on the new columns:
- The comments should be in the same order as the corresponding columns in the tables. You can use other comments for similar columns as a template.
.. code-block:: none
-- For the "Add a column" example
...
COMMENT ON COLUMN %1$s.tender_id IS 'Value of the ``id`` field in the tender object';
COMMENT ON COLUMN %1$s.tender_title IS 'Value of the ``title`` field in the tender object';
COMMENT ON COLUMN %1$s.tender_status IS 'Value of the ``status`` field in the tender object';
COMMENT ON COLUMN %1$s.tender_description IS 'Value of the ``description`` field in the tender object'; -- OUR ADDITION
...
-- For the "Add an aggregate" example
COMMENT ON COLUMN %1$s.total_planning_documents IS 'Length of the ``planning/documents`` array';
COMMENT ON COLUMN %1$s.planning_document_documenttype_counts IS 'JSONB object in which each key is a unique ``documentType`` value and each value is its number of occurrences in the ``planning/documents`` array';
#. Run the :ref:`add` command (replacing ``COLLECTION_ID`` below):
.. code-block:: bash
./manage.py add COLLECTION_ID docs
#. Review your changes.
- In your PostgreSQL client, Look at relevant tables' schemas to check that new comments appear.
#. :ref:`Update the documentation files` (replacing ``NAME`` below):
.. code-block:: bash
./manage.py dev docs-table-ref NAME
.. _merge:
Merge your changes
------------------
If your changes are for your own use only, you're done!
If you want to share your changes with others:
#. Create a new branch in your git repository and commit your changes:
.. code-block:: bash
git checkout -b my-changes
git commit -a -m 'Add X column to Y table'
#. Push the changes to GitHub:
.. code-block:: bash
git push -u origin my-changes
#. Follow the link in the output to create a `pull request `__. The maintainers will assign your pull request for review, and merge it as appropriate.
To apply your changes to existing schema created by Kingfisher Summarize, see :ref:`upgrade-app`.