Project

General

Profile

Snippets » History » Version 78

Alexander Watzinger, 2024-05-28 11:43

1 78
{{toc}}
2
3
Below are some database related code snippets used in development.
4
5
h1. Replace the database with a backup
6
7
It is possible (for users with the role admin or manager) to make SQL dumps via the backend anytime: admin -> data -> SQL export. Also, every time the database_upgrade.py script, which is used at an upgrade to a new OpenAtlas version, is called before doing database changes. These backups are located at *files/export* and because the date of creation is included in the filename it is easy to see when they were made. Of course it is good practice to store these SQL backups on another machine too, e.g. in case of a hard disk failure, but this is outside the scope of OpenAtlas.
8
9
In case these backups are needed, lets say for example an import went wrong, the workflow on a Debian machine would be as follows. The commands are executed as *postgres* user and it is assumed the database and user are called **openatlas**.
10
11
* Delete the current database
12
<pre><code class="shell">dropdb openatlas</code></pre>
13
14
* Create a new, empty database with the owner openaltas
15
<pre><code class="shell">createdb openatlas -O openatlas</code></pre>
16
17
* Import the (unpacked) backup into the new database
18
<pre><code class="shell">psql openatlas < path/to/the/unpacked/backup.sql</code></pre>
19
20
h1. Set files with licenses to public
21
22
<pre><code class="sql">
23
-- Define the list of IDs of License types
24
WITH ids AS (
25
    SELECT unnest(array[20158, 12939, 211353, 18135, 128538, 12940, 116287, 12937, 196373, 12938]) AS id
26
),
27
28
-- Select the entity IDs that are connected through the model.link table
29
connected_entities AS (
30
    SELECT DISTINCT e.id AS entity_id
31
    FROM model.entity e
32
    JOIN model.link l ON e.id = l.domain_id OR e.id = l.range_id
33
    WHERE l.domain_id IN (SELECT id FROM ids)
34
       OR l.range_id IN (SELECT id FROM ids)
35
)
36
37
-- Upsert into model.file_info table
38
INSERT INTO model.file_info (entity_id, public)
39
SELECT ce.entity_id, 'true'
40
FROM connected_entities ce
41
ON CONFLICT (entity_id) 
42
DO UPDATE SET public = EXCLUDED.public;
43
</code></pre>
44
45
46
h1. Export
47
48
h2. Database Structure
49
50
Export the database structure from the test database (used to avoid specialties in production databases) into install/1_structure.sql
51
52
<pre>
53
pg_dump -sc --if-exists -n model -n gis -n log -n web -n import openatlas_test > install/1_structure.sql
54
</pre>
55
56
h2. Model Data
57
58
<pre>
59
pg_dump openatlas --rows-per-insert 10000 -a -t model.cidoc_class -t model.cidoc_class_i18n -t model.cidoc_class_inheritance -t model.property -t model.property_i18n -t model.property_inheritance > install/2_data_model.sql
60
</pre> 
61
62
h2. Single Schema
63
64
<pre>
65
pg_dump -n web openatlas > /tmp/openatlas_web.sql
66
pg_dump -n model openatlas > /tmp/openatlas_web.sql
67
</pre>
68
69
h2. Windows import
70
71
There are mainly two ways of restoring a PostgreSQL database on Windows. For clarification of the commands and options, please read the "pg_dump":https://www.postgresql.org/docs/15/app-pgdump.html and "pg_restore":https://www.postgresql.org/docs/15/app-pgrestore.html documentation.
72
73
h3. Custom Format
74
75
Export on Debian server as @postgres@ user with following command:
76
<pre><code class="shell">
77
pg_dump -Fc openatlas > openatlas.dump
78
</code></pre>
79
80
This dump file can be used with pgAdmin4 to restore the database or with the following command in PowerShell (git bash doesn't work). Please adjust variables for your need:
81
<pre><code class="shell">
82
pg_restore.exe --host "localhost" --port "5432" --username "openatlas" --dbname "openatlas" --clean --verbose "path to dump file"
83
</code></pre>
84
85
h3. Plain text file (.sql) 
86
87
Export on Debian server as @postgres@ user with following command:
88
<pre><code class="shell">
89
pg_dump --attribute-inserts openatlas > openatlas.sql
90
</code></pre>
91
In the pgAdmin4 tool, select the corresponding database, run the _query tool_ and select the _open file_ option.
92
Load the provided dump file and execute (F5) it.
93
This method can be quite slow and if the database has a large size (over ~10 MB) loading the file in pgAdmin4 will be a challenge.
94
Also, the "psql":https://www.postgresql.org/docs/15/app-psql.html tool can be used.
95
96
h1. Reset Demo
97
98
<pre>
99
/var/lib/postgresql/reset_demo.sh
100
</pre>
101
102
h1. Add update trigger for modified field
103
104
Replace *schema.table* below accordingly and execute:
105
<pre>
106
CREATE TRIGGER update_modified BEFORE UPDATE ON schema.table FOR EACH ROW EXECUTE PROCEDURE model.update_modified();
107
</pre>
108
109
h1. Data clean up
110
111
h2. Find used but missing places
112
113
e.g. after a case study separation (not sure if this statement is now showing really missing or just needed locations)
114
115
<pre><code class="sql">
116
SELECT e.id, e.name, e.system_type FROM model.entity e
117
WHERE e.class_code = 'E53' AND e.system_type = 'place location' AND e.id IN (
118
   SELECT r.id FROM model.link lr JOIN model.entity r ON lr.range_id = r.id AND lr.property_code IN ('P74', 'OA8', 'OA9', 'P7'))
119
   AND e.id NOT IN (SELECT range_id FROM model.link WHERE property_code = 'P53');
120
</code></pre>
121
122
h2. Delete orphaned locations
123
124
<pre><code class="sql">
125
DELETE FROM model.entity WHERE id IN (
126
    SELECT id FROM model.entity WHERE system_type = 'place location' AND id NOT IN (
127
        SELECT e.id FROM model.entity e JOIN model.link l ON e.id = l.range_id AND l.property_code = 'P53' 
128
        WHERE e.class_code = 'E53' AND e.system_type = 'place location'));
129
</code></pre>
130
131
h2. Recursive Events
132
133
To get all child events of a given event the SQL below (replace ROOT_EVENT_ID at bottom). It works but is slow and could be improved.
134
135
<pre><code class="sql">
136
WITH RECURSIVE tree AS (
137
  SELECT e.id, ARRAY[]::INTEGER[] AS ancestors
138
  FROM model.entity e
139
  WHERE (SELECT s.id FROM model.entity s JOIN model.link l ON s.id = l.range_id AND l.domain_id = e.id AND l.property_id = (SELECT id FROM model.property WHERE code = 'P117')) IS NULL 
140
  UNION ALL 
141
  SELECT e.id, tree.ancestors || 
142
    (SELECT s.id FROM model.entity s JOIN model.link l ON s.id = l.range_id AND l.domain_id = e.id AND l.property_id = (SELECT id FROM model.property WHERE code = 'P117'))
143
  FROM model.entity e, tree
144
  WHERE (SELECT s.id FROM model.entity s JOIN model.link l ON s.id = l.range_id AND l.domain_id = e.id AND l.property_id = (SELECT id FROM model.property WHERE code = 'P117')) = tree.id
145
)
146
SELECT * FROM tree WHERE ROOT_EVENT_ID = ANY(tree.ancestors);
147
148
</code></pre>