Project

General

Profile

Snippets » History » Version 79

Alexander Watzinger, 2024-09-11 15:17

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. Export
21
22
h2. Database Structure
23
24
Export the database structure from the test database (used to avoid specialties in production databases) into install/1_structure.sql
25
26
<pre>
27
pg_dump -sc --if-exists -n model -n gis -n log -n web -n import openatlas_test > install/1_structure.sql
28
</pre>
29
30
h2. Model Data
31
32
<pre>
33
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
34
</pre> 
35
36
h2. Single Schema
37
38
<pre>
39
pg_dump -n web openatlas > /tmp/openatlas_web.sql
40
pg_dump -n model openatlas > /tmp/openatlas_web.sql
41
</pre>
42
43
h2. Windows import
44
45
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.
46
47
h3. Custom Format
48
49
Export on Debian server as @postgres@ user with following command:
50
<pre><code class="shell">
51
pg_dump -Fc openatlas > openatlas.dump
52
</code></pre>
53
54
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:
55
<pre><code class="shell">
56
pg_restore.exe --host "localhost" --port "5432" --username "openatlas" --dbname "openatlas" --clean --verbose "path to dump file"
57
</code></pre>
58
59
h3. Plain text file (.sql) 
60
61
Export on Debian server as @postgres@ user with following command:
62
<pre><code class="shell">
63
pg_dump --attribute-inserts openatlas > openatlas.sql
64
</code></pre>
65
In the pgAdmin4 tool, select the corresponding database, run the _query tool_ and select the _open file_ option.
66
Load the provided dump file and execute (F5) it.
67
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.
68
Also, the "psql":https://www.postgresql.org/docs/15/app-psql.html tool can be used.
69
70
h1. Reset Demo
71
72
<pre>
73
/var/lib/postgresql/reset_demo.sh
74
</pre>
75
76
h1. Add update trigger for modified field
77
78
Replace *schema.table* below accordingly and execute:
79
<pre>
80
CREATE TRIGGER update_modified BEFORE UPDATE ON schema.table FOR EACH ROW EXECUTE PROCEDURE model.update_modified();
81
</pre>
82 79 Alexander Watzinger
83
h1. Set files with licenses to public
84
85
<pre><code class="sql">
86
-- Define the list of IDs of License types
87
WITH ids AS (
88
    SELECT unnest(array[20158, 12939, 211353, 18135, 128538, 12940, 116287, 12937, 196373, 12938]) AS id
89
),
90
91
-- Select the entity IDs that are connected through the model.link table
92
connected_entities AS (
93
    SELECT DISTINCT e.id AS entity_id
94
    FROM model.entity e
95
    JOIN model.link l ON e.id = l.domain_id OR e.id = l.range_id
96
    WHERE l.domain_id IN (SELECT id FROM ids)
97
       OR l.range_id IN (SELECT id FROM ids)
98
)
99
100
-- Upsert into model.file_info table
101
INSERT INTO model.file_info (entity_id, public)
102
SELECT ce.entity_id, 'true'
103
FROM connected_entities ce
104
ON CONFLICT (entity_id) 
105
DO UPDATE SET public = EXCLUDED.public;
106
</code></pre>
107 78
108
h1. Data clean up
109
110
h2. Find used but missing places
111
112
e.g. after a case study separation (not sure if this statement is now showing really missing or just needed locations)
113
114
<pre><code class="sql">
115
SELECT e.id, e.name, e.system_type FROM model.entity e
116
WHERE e.class_code = 'E53' AND e.system_type = 'place location' AND e.id IN (
117
   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'))
118
   AND e.id NOT IN (SELECT range_id FROM model.link WHERE property_code = 'P53');
119
</code></pre>
120
121
h2. Delete orphaned locations
122
123
<pre><code class="sql">
124
DELETE FROM model.entity WHERE id IN (
125
    SELECT id FROM model.entity WHERE system_type = 'place location' AND id NOT IN (
126
        SELECT e.id FROM model.entity e JOIN model.link l ON e.id = l.range_id AND l.property_code = 'P53' 
127
        WHERE e.class_code = 'E53' AND e.system_type = 'place location'));
128
</code></pre>
129
130
h2. Recursive Events
131
132
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.
133
134
<pre><code class="sql">
135
WITH RECURSIVE tree AS (
136
  SELECT e.id, ARRAY[]::INTEGER[] AS ancestors
137
  FROM model.entity e
138
  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 
139
  UNION ALL 
140
  SELECT e.id, tree.ancestors || 
141
    (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'))
142
  FROM model.entity e, tree
143
  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
144
)
145
SELECT * FROM tree WHERE ROOT_EVENT_ID = ANY(tree.ancestors);
146
147
</code></pre>