Skip to content

Commit 36aa040

Browse files
committed
feat: support tags
1 parent 641295e commit 36aa040

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed

readme.md

+56-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ The implementation uses [plv8](https://github.com/plv8/plv8) to run JavaScript i
99
- [Usage](#usage)
1010
- [Tracking history](#tracking-history)
1111
- [Deletions](#deletions)
12-
- [Configuraton](#configuraton)
12+
- [Options](#options)
13+
- [Commit messages](#commit-messages)
14+
- [Log depth](#log-depth)
15+
- [Tags](#tags)
1316
- [Restoring previous versions](#restoring-previous-versions)
1417
- [Caveat](#caveat)
1518
- [Implementation](#implementation)
@@ -281,7 +284,9 @@ where identifier->>'id' = '1'
281284

282285
In this example, `deleted_history` is generic enough that it could be the "history" table for several other relations, since it uses columns `schemaname` and `tablename`, and `identifier` as the flexible `JSONB` data type to allow for different types of primary key. This avoids the overhead of needing a new `_history` table for every relation created - all the data, including history, is captured in the `git` column. The `identifier` column is only used for lookups.
283286

284-
### Configuraton
287+
### Options
288+
289+
#### Commit messages
285290

286291
You can pass a custom commit message and author by pre-loading the `git` property with `commit` details, which can include a commit message and user info:
287292

@@ -327,6 +332,8 @@ where id = 2
327332
}
328333
```
329334

335+
#### Log depth
336+
330337
`git_log` also accepts a `depth` parameter to limit the amount of history that is fetched:
331338

332339
```sql
@@ -380,6 +387,27 @@ where id = 2
380387

381388
By setting `depth := 1`, only the most recent change is returned.
382389

390+
#### Tags
391+
392+
You can pass `tags` to the git object. The below example uses a convention of tagging with the day, month, and year so it will later be easy to restore to previous versions:
393+
394+
```sql
395+
insert into test_table(id, text, git)
396+
values (3, 'item 3 xmas day value', '{ "git": { "tags": ["2000-12-25", "2000-12", "2000"] } }');
397+
398+
update test_table
399+
set
400+
text = 'item 3 boxing day value',
401+
git = '{ "tags": ["2000-12-26", "2000-12", "2000"] }'
402+
where id = 3;
403+
404+
update test_table
405+
set
406+
text = 'item 3 new year value',
407+
git = '{ "tags": ["2001-01-01", "2001-01", "2001"] }'
408+
where id = 3;
409+
```
410+
383411
### Restoring previous versions
384412

385413
`git_resolve` gives you a json representation of a prior version of a row, which can be used for backup and restore. The first argument is a `git` json value, the second value is a valid git ref string.
@@ -426,7 +454,32 @@ returning id, text
426454
}
427455
```
428456

429-
Or a similar technique can restore a deleted item:
457+
If you used `tags` as described above, you can take advantage of them to restore to a known-good state easily:
458+
459+
```sql
460+
update test_table set (id, text) =
461+
(
462+
select id, text
463+
from json_populate_record(
464+
null::test_table, (
465+
select git_resolve(git, '2000-12')
466+
from test_table
467+
where id = 3
468+
)
469+
)
470+
)
471+
where id = 3
472+
returning id, text
473+
```
474+
475+
```json
476+
{
477+
"id": 3,
478+
"text": "item 3 boxing day value"
479+
}
480+
```
481+
482+
A similar technique can restore a deleted item:
430483

431484
```sql
432485
insert into test_table

src/git.ts

+7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ export const rowToRepo = ({OLD, NEW, ...pg}: PG_Vars) => {
5353
author: {name: 'pguser', email: '[email protected]', ...NEW?.[repoColumn]?.commit?.author},
5454
}),
5555
)
56+
.then(commit =>
57+
SyncPromise.all(
58+
(NEW?.git?.tags || []).map((tag: string) => {
59+
return git.tag({...repo, ref: tag, object: commit})
60+
}),
61+
),
62+
)
5663
})
5764
.then(() => {
5865
const files: Record<string, number[]> = {}

src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as git from './git'
2+
import {plog} from './pg-log'
23
import {SyncPromise} from './sync-promise'
34

45
export {SyncPromise} from './sync-promise'
@@ -14,6 +15,7 @@ export * from './git'
1415
*/
1516
export const git_call_sync = (name: keyof typeof git, args: any[]) => {
1617
Object.assign(Promise, SyncPromise)
18+
Object.assign(console, {log: plog})
1719
const operation: (...args: any[]) => Promise<any> = git[name]
1820
let result
1921
operation(...args).then(r => (result = r))

test/walkthrough.test.ts

+52-2
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,9 @@ test('walkthrough', async () => {
279279

280280
// In this example, `deleted_history` is generic enough that it could be the "history" table for several other relations, since it uses columns `schemaname` and `tablename`, and `identifier` as the flexible `JSONB` data type to allow for different types of primary key. This avoids the overhead of needing a new `_history` table for every relation created - all the data, including history, is captured in the `git` column. The `identifier` column is only used for lookups.
281281

282-
// ### Configuraton
282+
// ### Options
283+
284+
// #### Commit messages
283285

284286
// You can pass a custom commit message and author by pre-loading the `git` property with `commit` details, which can include a commit message and user info:
285287

@@ -325,6 +327,8 @@ test('walkthrough', async () => {
325327
}
326328
`)
327329

330+
// #### Log depth
331+
328332
// `git_log` also accepts a `depth` parameter to limit the amount of history that is fetched:
329333

330334
await client.query(sql`
@@ -378,6 +382,27 @@ test('walkthrough', async () => {
378382

379383
// By setting `depth := 1`, only the most recent change is returned.
380384

385+
// #### Tags
386+
387+
// You can pass `tags` to the git object. The below example uses a convention of tagging with the day, month, and year so it will later be easy to restore to previous versions:
388+
389+
await client.query(sql`
390+
insert into test_table(id, text, git)
391+
values (3, 'item 3 xmas day value', '{ "git": { "tags": ["2000-12-25", "2000-12", "2000"] } }');
392+
393+
update test_table
394+
set
395+
text = 'item 3 boxing day value',
396+
git = '{ "tags": ["2000-12-26", "2000-12", "2000"] }'
397+
where id = 3;
398+
399+
update test_table
400+
set
401+
text = 'item 3 new year value',
402+
git = '{ "tags": ["2001-01-01", "2001-01", "2001"] }'
403+
where id = 3;
404+
`)
405+
381406
// ### Restoring previous versions
382407

383408
// `git_resolve` gives you a json representation of a prior version of a row, which can be used for backup and restore. The first argument is a `git` json value, the second value is a valid git ref string.
@@ -424,7 +449,32 @@ test('walkthrough', async () => {
424449
}
425450
`)
426451

427-
// Or a similar technique can restore a deleted item:
452+
// If you used `tags` as described above, you can take advantage of them to restore to a known-good state easily:
453+
454+
result = await client.one(sql`
455+
update test_table set (id, text) =
456+
(
457+
select id, text
458+
from json_populate_record(
459+
null::test_table, (
460+
select git_resolve(git, '2000-12')
461+
from test_table
462+
where id = 3
463+
)
464+
)
465+
)
466+
where id = 3
467+
returning id, text
468+
`)
469+
470+
expect(result).toMatchInlineSnapshot(`
471+
{
472+
"id": 3,
473+
"text": "item 3 boxing day value"
474+
}
475+
`)
476+
477+
// A similar technique can restore a deleted item:
428478

429479
result = await client.one(sql`
430480
insert into test_table

0 commit comments

Comments
 (0)