aboutsummaryrefslogtreecommitdiff
path: root/memos/WM-097.txt
blob: 9e3526870a367d0a85d2ef3d532a4ce75e8c7fb1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
Document: WM-097                                                 P. Webb
Category: Tutorial                                            2026-06-22

                    How to migrate from Gel to Disc

Abstract

   The hardest part is getting your data out of Gel in a useable format,
   the rest is easy (but mind your links on the way in, warning near
   the end).

Body

   Dumping your Gel database to a format other databases can read
   requires arcane knowledge but don't fret, I've uncovered the
   incantations to free your data!

   Perform this full backup, for peace of mind.

   ```sh
   gel dump --all --format=dir gel-export
   ```

   You should see something like:

   ```
   Connecting to Gel instance 'INSTANCE' at localhost:PORT...
   Starting dump for database `'DATABASE'`...
     Finished dump for `'DATABASE'`. Total size: 181.67 KiB
   ```

   This will create `gel-export` in your current directory. Take note of
   the instance and database names and the port as you'll need these
   later. Next, grab the password to your database:

   ```sh
   gel instance credentials --insecure-dsn -I INSTANCE
   ```

   You should see something like:

   ```
   gel:///DATABASE?port=PORT&password=PASSWORD&tls_ca_file=%3C...%3E&tls_security=no_host_verification
   ```

   Now we can set some variables to make the last bits pseudo-legible.
   `sslmode=require` because Gel refuses plaintext connections, and
   without it `psql` fails with a misleading auth error before the real
   "TLS required" one.

   ```sh
   DSN="postgresql://edgedb@localhost:PORT/DATABASE?sslmode=require"
   ```

   ```sh
   export PGPASSWORD="PASSWORD"
   ```

   Gel's binary dump is useless to anything but Gel, so to get tabular
   data out we go through its SQL adapter. List the tables into a `.tsv`
   first, without any escaping that could mangle the identifiers:

   ```sh
   psql "$DSN" -At -F $'\t' -c "
     SELECT table_schema, table_name
     FROM information_schema.tables
     WHERE table_schema NOT IN ('information_schema', 'pg_catalog')
   " > gel-export/tables.tsv
   ```

   Create our final export directory:

   ```sh
   mkdir gel-export/data
   ```

   Finally, we render our `.csv`s:

   ```sh
   while IFS=$'\t' read -r schema table; do
     out="${schema}_${table}"
     psql "$DSN" --csv -c "SELECT * FROM \"$schema\".\"$table\"" > "gel-export/data/$out.csv"
   done < gel-export/tables.tsv
   ```

   ---

   A quick note on what's in those CSVs, because it bites at import
   time (and it bit me)!

   Gel maps each object type to a table with `id` and `__type__`
   columns, single properties as plain columns, and (what got me) single
   LINKS as `<link>_id` UUID columns (your `owner` link becomes an
   `owner_id` column holding the target's id).

   Multi links and multi properties aren't in these tables at all; they
   live in their own `source`/`target` tables and import as
   separate files.

   ---

   I'll assume you installed Disc[1] already. Great! You'll need to get
   it setup with your schema. Run that migration!

   ```sh
   disc migrate
   ```

   Next, we'll point Disc at your fresh collection of `.csv`s:

   ```sh
   disc db import ./gel-export/data
   ```

   This SHOULD work; it didn't for me because…

   ```
   ✗ Import failed (transaction rolled back): duplicate key value violates unique constraint "log_pkey"
   ```

   …and that's irrelevant to me. Ignoring conflicts like this is okay.

   ```sh
   disc db import ./gel-export/data --on-conflict skip
   ```

   ---

   You'll get an import manifest of what was processed and skipped.
   Remember those `<link>_id` columns? Disc resolves them into your
   single links, but anything it can't map surfaces here as a warning.
   Confirm your links got set and that no non-empty column was
   quietly discarded.

   A previous version of Disc silently dropped every `<link>_id` column
   and because I'm dogfooding this, I found the issue and fixed. This is
   bleeding edge folks!

   ---

   Run `disc serve` and navigate to your database's `/ui` and you should
   see populated objects in the Data tab.

   Voila! Now all you gotta do is update your codebase…unfortunately,
   you've gotta handle that yourself. 🕸️

References

   [1] <https://disc.sh>