-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SPIKE: Automatically insert records in address_history table #1
Comments
SELECT column_name, data_type, character_maximum_length
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_catalog = 'cs_guide_dev' AND table_name = 'drinks'
|
Searched for: "postgres create table based on another table" CREATE TABLE old_table_name (
id serial,
my_data text,
primary key (id)
);
CREATE TABLE new_table_name (
new_col1 integer,
new_col2 text,
like old_table_name including all
); Adaptation: CREATE TABLE address (
id serial,
address text,
city text,
postcode text,
primary key (id)
);
CREATE TABLE IF NOT EXISTS address_history (
_id serial,
inserted_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
like address
primary key (_id)
); This works for creating the table if it does not already exist. |
Get list of tables in database: SELECT * FROM INFORMATION_SCHEMA.tables
WHERE table_catalog = 'cs_guide_dev' Or restricting the columns to just the ones we care about: SELECT table_catalog, table_schema, table_name
FROM information_schema.tables
WHERE table_catalog = 'cs_guide_dev'
AND table_schema = 'public'
|
Trying to assign the result of this query to a variable. name := (
SELECT table_name
FROM information_schema.tables
WHERE table_catalog = 'cs_guide_dev'
AND table_schema = 'public'
);
raise notice 'Tables: %', name; Sadly that results in an error:
Tried debugging it for a few minutes and got nothing ...
Still fails ... 😞 Need to figure out how to assign a variable in Postgres ... |
@nelsonic Take a look at this answer. Loops through the results of a select query |
DO $$
BEGIN
FOR counter IN 1..5 LOOP
RAISE NOTICE 'Counter: %', counter;
END LOOP;
END; $$ Output:
DO $$
DECLARE
tables RECORD;
BEGIN
FOR tables IN
(SELECT table_name
FROM information_schema.tables
WHERE table_catalog = 'cs_guide_dev'
AND table_schema = 'public')
LOOP
RAISE NOTICE 'Table: %', tables.table_name;
END LOOP;
END; $$
|
DO $$
DECLARE
tables RECORD;
table_name TEXT;
new_table TEXT;
BEGIN
FOR tables IN
(SELECT t.table_name
FROM information_schema.tables t
WHERE t.table_catalog = 'hits_dev'
AND t.table_schema = 'public')
LOOP
table_name := tables.table_name;
new_table := table_name || '_history';
RAISE NOTICE 'Table: %, %', table_name, new_table;
END LOOP;
END; $$ That works and outputs the following:
Now we want to add the CREATE statement: CREATE TABLE IF NOT EXISTS new_table (
_id serial,
inserted_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
like table_name
); |
DO $$
DECLARE
tables RECORD;
table_name TEXT;
new_table TEXT;
BEGIN
FOR tables IN
(SELECT t.table_name
FROM information_schema.tables t
WHERE t.table_catalog = 'app_dev'
AND t.table_schema = 'public'
AND t.table_name not like '%_history'
AND t.table_name not like 'schema_migrations'
)
LOOP
table_name := tables.table_name;
new_table := table_name || '_history';
EXECUTE format('CREATE TABLE IF NOT EXISTS %I (_id serial, like %I)', new_table, table_name);
END LOOP;
END; $$ |
Make the database name a variable: DO $$
DECLARE
db_name TEXT := 'hits_dev';
tables RECORD;
table_name TEXT;
new_table TEXT;
BEGIN
FOR tables IN
(SELECT t.table_name
FROM information_schema.tables t
WHERE t.table_catalog = format('%I', db_name)
AND t.table_schema = 'public'
AND t.table_name not like '%_history'
AND t.table_name not like 'schema_migrations'
)
LOOP
table_name := tables.table_name;
new_table := table_name || '_history';
EXECUTE format('CREATE TABLE IF NOT EXISTS %I (_id serial, like %I)', new_table, table_name);
END LOOP;
END; $$ |
Make it a function which can be invoked with a CREATE OR REPLACE FUNCTION create_history(db_name TEXT)
RETURNS boolean
AS $func$
DECLARE
tables RECORD;
table_name TEXT;
new_table TEXT;
BEGIN
FOR tables IN
(SELECT t.table_name
FROM information_schema.tables t
WHERE t.table_catalog = format('%I', db_name)
AND t.table_schema = 'public'
AND t.table_name not like '%_history'
AND t.table_name not like 'schema_migrations'
)
LOOP
table_name := tables.table_name;
new_table := table_name || '_history';
EXECUTE format('CREATE TABLE IF NOT EXISTS %I (_id serial, like %I)', new_table, table_name);
END LOOP;
RETURN true; -- boolean!
END; $func$
LANGUAGE plpgsql;
We probably don't need this to be a function, but I wanted to check if it was possible. 👍 |
NEXT: Create the Trigger to insert into
|
NEXT: Put It All Together! 💥See: #2 |
EXECUTE format('CREATE TABLE IF NOT EXISTS %I
(_id serial PRIMARY KEY, like %I)', new_table, table_name); |
The objective of this quest is to run a script in any project that uses PostgreSQL
that will:
_history
table existsbefore
starting a Phoenix App_history
table for eachprimary
table in an existing database.address
>>address_history
where all the fields are mirroredprimary
table to the_history
table Mirror changes (new columns) made in the primary table to the _history table #3primary
table into the_history
table.3 & 5 are related.
This quest is similar to dwyl/ecto-postgres-pubsub-spike#1
But the key distinction is that the previous spike had:
https://github.com/dwyl/ecto-postgres-pubsub-spike/blob/master/lib/app/accounts/address_history.ex
https://github.com/dwyl/ecto-postgres-pubsub-spike/blob/274e77f483eda222ef9c0c7794cb5fd262a9d79e/lib/app/listener.ex#L25
Relevant SO question:
https://stackoverflow.com/questions/38954139/implementing-history-of-postgresql-table
The text was updated successfully, but these errors were encountered: