Last active
October 22, 2017 14:13
-
-
Save JoshCheek/e91fa717c14a16c04e9befb0cf5fe921 to your computer and use it in GitHub Desktop.
How to save a postgresql record into a backup table and restore it
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'pg' | |
# PG.connect(dbname: 'postgres').exec('create database josh_testing') | |
db = PG.connect(dbname: 'josh_testing').tap { |db| db.exec 'begin' } | |
# Make the db a little nicer to work with for our experiment | |
def db.exec(*) | |
super.to_a | |
end | |
db.exec <<~SQL | |
create extension hstore; | |
create table backups ( | |
col_values hstore | |
); | |
-- test it against a table with some sophisticated types | |
create type user_type as enum ('admin', 'moderator', 'user'); | |
create type login_device as (name varchar, loggedin_at timestamp); | |
create type hours as range (subtype = time); | |
create table users ( | |
id serial primary key, -- an autoincrementing value | |
name varchar, -- string | |
type user_type, -- enum | |
is_active bool, -- boolean | |
preferences hstore, -- hstore (this will be nested) | |
device login_device, -- composite type | |
oncall_hours hours -- a custom range | |
); | |
SQL | |
# create some users (but should work for an arbitrary table) | |
original = db.exec <<~SQL | |
insert into users (name, type, is_active, preferences, device, oncall_hours) | |
values ('Josh', 'admin', true, 'a=>b,c=>d', ('macbook', now()), hours('08:30 AM', '04:30 PM')), | |
('Sindy', 'moderator', false, '', null, null) | |
returning *; | |
SQL | |
# => [{"id"=>"1", | |
# "name"=>"Josh", | |
# "type"=>"admin", | |
# "is_active"=>"t", | |
# "preferences"=>"\"a\"=>\"b\", \"c\"=>\"d\"", | |
# "device"=>"(macbook,\"2017-10-22 09:13:10.504474\")", | |
# "oncall_hours"=>"[08:30:00,16:30:00)"}, | |
# {"id"=>"2", | |
# "name"=>"Sindy", | |
# "type"=>"moderator", | |
# "is_active"=>"f", | |
# "preferences"=>"", | |
# "device"=>nil, | |
# "oncall_hours"=>nil}] | |
# Back the users up | |
db.exec <<~SQL | |
insert into backups (col_values) | |
select hstore(users) | |
from users | |
returning *; | |
SQL | |
# => [{"col_values"=> | |
# "\"id\"=>\"1\", \"name\"=>\"Josh\", \"type\"=>\"admin\", \"device\"=>\"(macbook,\\\"2017-10-22 09:13:10.504474\\\")\", \"is_active\"=>\"t\", \"preferences\"=>\"\\\"a\\\"=>\\\"b\\\", \\\"c\\\"=>\\\"d\\\"\", \"oncall_hours\"=>\"[08:30:00,16:30:00)\""}, | |
# {"col_values"=> | |
# "\"id\"=>\"2\", \"name\"=>\"Sindy\", \"type\"=>\"moderator\", \"device\"=>NULL, \"is_active\"=>\"f\", \"preferences\"=>\"\", \"oncall_hours\"=>NULL"}] | |
# Delete the users | |
db.exec <<~SQL | |
delete from users; | |
select * from users; | |
SQL | |
# => [] | |
# Restore them from the backup | |
backed_up = db.exec <<~SQL | |
insert into users | |
select r.* | |
from backups, populate_record(null::users, col_values) as r; | |
select * from users; | |
SQL | |
# => [{"id"=>"1", | |
# "name"=>"Josh", | |
# "type"=>"admin", | |
# "is_active"=>"t", | |
# "preferences"=>"\"a\"=>\"b\", \"c\"=>\"d\"", | |
# "device"=>"(macbook,\"2017-10-22 09:13:10.504474\")", | |
# "oncall_hours"=>"[08:30:00,16:30:00)"}, | |
# {"id"=>"2", | |
# "name"=>"Sindy", | |
# "type"=>"moderator", | |
# "is_active"=>"f", | |
# "preferences"=>"", | |
# "device"=>nil, | |
# "oncall_hours"=>nil}] | |
# Do they match? | |
original == backed_up # => true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment