PostgreSQL and Hibernate: On DELETE CASCADE not working - postgresql

I have a named native query which looks so:
#NamedNativeQuery(name = "deleteRecipes", query = "DELETE FROM RECIPE WHERE rcp_acc_identifier IN (?1)")
These are the important parts of the recipe table:
Table "public.recipe"
Column | Type | Modifiers
-------------------------+-----------------------------+---------------------------------------------------------
rcp_pf_id_photodata | bigint |
rcp_pf_id_thumbnaildata | bigint |
Indexes:
"fk_rcp_pf_id_photodata_idx" btree (rcp_pf_id_photodata)
"fk_rcp_pf_id_thumbnaildata_idx" btree (rcp_pf_id_thumbnaildata)
Foreign-key constraints:
"fk_rcp_pf_id_photodata" FOREIGN KEY (rcp_pf_id_photodata) REFERENCES persistable_file(pf_id) ON DELETE CASCADE
"fk_rcp_pf_id_thumbnaildata" FOREIGN KEY (rcp_pf_id_thumbnaildata) REFERENCES persistable_file(pf_id) ON DELETE CASCADE
When I execute the query above, the recipes will be deleted but not the data from persistable_file. Why is this so?
Additional information: I didn't set the ON DELETE CASCADE while creating the database. I added it later by dropping both constraints from above at first and then I added the constraints again with the additional ON DELETE CASCADE directive. Is this maybe the problem why the data is not deleted?

Related

Query tool response pgAdmin

ALTER TABLE ONLY rental ADD CONSTRAINT rental_customer_id_fkey FOREIGN KEY (customer_id) REFERENCES customer(customer_id) ON UPDATE CASCADE ON DELETE RESTRICT;
ERROR: there is no unique constraint matching given keys for referenced table "customer"
ALTER TABLE ONLY customer ADD CONSTRAINT customer_store_id_fkey FOREIGN KEY (store_id) REFERENCES store(store_id) ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE ONLY film ADD CONSTRAINT film_language_id_fkey FOREIGN KEY (language_id) REFERENCES language(language_id) ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE ONLY inventory ADD CONSTRAINT inventory_store_id_fkey FOREIGN KEY (store_id) REFERENCES store(store_id) ON UPDATE CASCADE ON DELETE RESTRICT;
ERROR: insert or update on table "inventory" violates foreign key constraint
I get these messages when i use the query tool for a sql query of over 1300 lines of code. I'm still learning so any pointers will be helpful

How do I copy only 2 tables in Postgres and ignore foreign keys and constraints?

I need to copy 2 tables from production to development. They are the same except the production table has a bit more data in it. I tried pg_dump to dump from production and copy to development, but it complained about foreign key constraints. How do I turn off constraints temporarily? I don't want to copy the whole database because it's too much data, and I want to keep my test data and users.
ALTER TABLE
DROP INDEX
ERROR: cannot drop constraint foods_pkey on table foods because other objects depend on it
DETAIL: constraint fk_rails_7e399284de on table histories depends on index foods_pkey
constraint fk_rails_8d89280489 on table food_nutrients depends on index foods_pkey
Here are the two tables:
Table "public.foods"
Column | Type | Modifiers
------------------+-----------------------------+----------------------------------------------------
id | integer | not null default nextval('foods_id_seq'::regclass)
...
Indexes:
"foods_pkey" PRIMARY KEY, btree (id)
"index_foods_on_food_category_id" btree (food_category_id)
Foreign-key constraints:
"fk_rails_a28abb337f" FOREIGN KEY (food_category_id) REFERENCES food_categories(id)
Referenced by:
TABLE "histories" CONSTRAINT "fk_rails_7e399284de" FOREIGN KEY (food_id) REFERENCES foods(id)
TABLE "food_nutrients" CONSTRAINT "fk_rails_8d89280489" FOREIGN KEY (food_id) REFERENCES foods(id)
And
Table "public.food_categories"
Column | Type | Modifiers
------------+-----------------------------+--------------------------------------------------------------
id | integer | not null default nextval('food_categories_id_seq'::regclass)
...
Indexes:
"food_categories_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "foods" CONSTRAINT "fk_rails_a28abb337f" FOREIGN KEY (food_category_id) REFERENCES food_categories(id)
I also tried --disable-triggers but it didn't help.
You can first copy the "food_categories" table. After that you can copy the "foods" table.

Postgres table update taking 40 minutes, ultimately failing

I'm trying to update the value of a column in all rows in a table with about 1 million records.
First few times I ran the query it hung and after 20 minutes I cancelled the query. I ran it again with EXPLAIN ANALYZE, and after 40 minutes this was output:
=# explain analyze update documents set state = 'archived';
NOTICE: word is too long to be indexed
DETAIL: Words longer than 2047 characters are ignored.
ERROR: deadlock detected
DETAIL: Process 17080 waits for ShareLock on transaction 14275765; blocked by process 1530.
Process 1530 waits for ShareLock on transaction 14273749; blocked by process 17080.
HINT: See server log for query details.
Time: 2324900.382 ms
Here's the EXPLAIN output:
=# explain update documents set workflow_state = 'archived';
QUERY PLAN
----------------------------------------------------------------------------
Update on documents (cost=0.00..220673.50 rows=900750 width=1586)
-> Seq Scan on documents (cost=0.00..220673.50 rows=900750 width=1586)
Any idea what's going on?
Details:
PG version 9.3.7
Indexes:
"documents_pkey" PRIMARY KEY, btree (id)
"document_search_ix" gin (contents_search)
"document_user_id_recvd_ix" btree (user_id, bill_date DESC)
Foreign-key constraints:
"documents_biller_id_fkey" FOREIGN KEY (biller_id) REFERENCES billers(id) ON DELETE SET DEFAULT
"documents_billercred_id_fkey" FOREIGN KEY (billercred_id) REFERENCES billercreds(id) ON DELETE SET NULL
"documents_folder_id_fkey" FOREIGN KEY (folder_id) REFERENCES folders(id) ON DELETE CASCADE
"documents_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
"documents_vendor_id_fkey" FOREIGN KEY (vendor_id) REFERENCES vendors(id) ON DELETE SET NULL
Referenced by:
TABLE "document_billcom_actions" CONSTRAINT "document_billcom_actions_document_id_fkey" FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_box_actions" CONSTRAINT "document_box_actions_document_id_fkey" FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_email_forwarding_actions" CONSTRAINT "document_email_forwarding_actions_document_id_fkey" FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_qbo_actions" CONSTRAINT "document_qbo_actions_document_id_fkey" FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_xero_actions" CONSTRAINT "document_xero_actions_document_id_fkey" FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_xerofiles_actions" CONSTRAINT "document_xerofiles_actions_document_id_fkey" FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "documenttagmap" CONSTRAINT "documenttagmap_document_id_fkey" FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "synced_docs" CONSTRAINT "synced_docs_doc_id_fkey" FOREIGN KEY (doc_id) REFERENCES documents(id) ON DELETE CASCADE
Triggers:
document_search_update BEFORE INSERT OR UPDATE ON documents FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('contents_search', 'pg_catalog.english', 'contents', 'filename', 'account_name', 'account_number')
document_updated_at_t BEFORE UPDATE ON documents FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column()
documents_count BEFORE INSERT OR DELETE ON documents FOR EACH ROW EXECUTE PROCEDURE count_trig()
folder_document_count_trig BEFORE INSERT OR DELETE OR UPDATE ON documents FOR EACH ROW EXECUTE PROCEDURE update_folder_count()
tags_in_trash_document_count_trig BEFORE DELETE OR UPDATE ON documents FOR EACH ROW EXECUTE PROCEDURE update_tag_trash_count()

Change primary key in PostgreSQL table

I have users table in my PostgreSQL 9.3.6 database with two columns: id and another_id. The id is a primary key, the another_id is just another integer column with unique constraint.
There are other tables that reference users by primary key.
Here's the users table description:
Table "public.users"
Column | Type | Modifiers | Storage | Stats target | Description
----------------------+--------------------------------+----------------------------------------+---------+--------------+-------------
id | integer | not null | plain | |
another_id | integer | not null | plain | |
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"uniq_1483a5e93414710b" UNIQUE, btree (another_id)
Referenced by:
TABLE "foo_table" CONSTRAINT "fk_4affc6e5a76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
TABLE "bar_table" CONSTRAINT "fk_72936b1da76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
TABLE "baz_table" CONSTRAINT "fk_83adbaf0a76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
Here's foo_table description:
Table "public.foo_table"
Column | Type | Modifiers | Storage | Stats target | Description
--------------+--------------------------------+-----------------------------------------------+----------+--------------+-------------
id | integer | not null | plain | |
user_id | integer | | plain | |
Indexes:
"foo_table_pkey" PRIMARY KEY, btree (id)
"idx_e52ffdeea76ed395" btree (user_id)
Foreign-key constraints:
"fk_e52ffdeea76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
How do I replace primary key in PostgreSQL table from id column to another_id column and maintain data integrity?
I've spent some time and finally came up with a working solution.
I will publish it here for future reference.
Solution
First of all, you have three tables (foo_table, bar_table, baz_table) which are pointing to your users table by means of foreign keys (called user_id in all cases). You will need to replace the IDs stored in those columns from id to another_id. Here's how you can do it:
-- We are dropping the foreign key constraint on dependant table (in other case it will prevent us from updating the values)
ALTER TABLE foo_table DROP CONSTRAINT fk_e52ffdeea76ed395;
-- Then, we're swapping values in foreign key column from id to another_id
UPDATE foo_table T SET user_id = (SELECT another_id FROM users WHERE id = T.user_id);
-- And finally we're creating new foreign key constraint pointing to the another_id instead of id
ALTER TABLE foo_table ADD CONSTRAINT fk_e52ffdeea76ed395 FOREIGN KEY (user_id) REFERENCES users (another_id) ON DELETE CASCADE;
You will need to repeat the above queries for each dependent table.
After that, all dependent tables will point to your new another_id column.
In the end we will just need to replace the primary key:
-- 1. Dropping the original primary key
ALTER TABLE users DROP CONSTRAINT users_pkey
-- 2. Renaming existing index for another_id (optional)
ALTER INDEX uniq_1483a5e93414710b RENAME TO users_pkey
-- 3. Creating new primary key using existing index for another_id
ALTER TABLE users ADD PRIMARY KEY USING INDEX users_pkey
-- 4. Creating index for old id column (optional)
CREATE UNIQUE INDEX users_id ON users (id)
-- 5. You can drop the original sequence generator if you won't need it
DROP SEQUENCE users_id_seq
You can even drop the original id column if you want to.
I hope it will help someone.

Adding primary key changes column type

Our database currently doesn't define primary keys on any tables. All of the id columns are simply unique indexes. I'm dropping those indexes and replacing them with proper primary keys.
My problem: In Postgres 8.4.7, one table in particular changes the data type from bigint to integer when I add the primary key to the table.
I've got the following table definition:
psql=# \d events
Table "public.events"
Column | Type | Modifiers
-----------------------+--------------------------+-----------------------------------------------------
id | bigint | not null default nextval('events_id_seq'::regclass)
[more columns omitted]
Indexes:
"events_id_unique_pk" UNIQUE, btree (id)
Foreign-key constraints:
"events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
"events_event_configs_id_fk" FOREIGN KEY (event_config_id) REFERENCES event_configs(id)
"events_pdu_circuitbreaker_id_fk" FOREIGN KEY (pdu_circuitbreaker_id) REFERENCES pdu_circuitbreaker(id)
"events_pdu_id_fk" FOREIGN KEY (pdu_id) REFERENCES pdus(id) ON DELETE CASCADE
"events_pdu_outlet_id_fk" FOREIGN KEY (pdu_outlet_id) REFERENCES pdu_outlet(id)
"events_sensor_id_fk" FOREIGN KEY (sensor_id) REFERENCES sensors(id)
"events_user_id_fk" FOREIGN KEY (clearing_user_id) REFERENCES users(id)
Referenced by:
TABLE "events" CONSTRAINT "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
TABLE "event_params" CONSTRAINT "events_params_event_id_fk" FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
Triggers:
event_validate BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE event_validate()
This is what happens:
psql=# ALTER TABLE events ADD PRIMARY KEY (id);
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "events_pkey" for table "events"
ALTER TABLE
psql=# \d events
Table "public.events"
Column | Type | Modifiers
-----------------------+--------------------------+-----------------------------------------------------
id | integer | not null default nextval('events_id_seq'::regclass)
[more columns omitted]
Indexes:
"events_pkey" PRIMARY KEY, btree (id)
"events_id_unique_pk" UNIQUE, btree (id)
Foreign-key constraints:
"events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
"events_event_configs_id_fk" FOREIGN KEY (event_config_id) REFERENCES event_configs(id)
"events_pdu_circuitbreaker_id_fk" FOREIGN KEY (pdu_circuitbreaker_id) REFERENCES pdu_circuitbreaker(id)
"events_pdu_id_fk" FOREIGN KEY (pdu_id) REFERENCES pdus(id) ON DELETE CASCADE
"events_pdu_outlet_id_fk" FOREIGN KEY (pdu_outlet_id) REFERENCES pdu_outlet(id)
"events_sensor_id_fk" FOREIGN KEY (sensor_id) REFERENCES sensors(id)
"events_user_id_fk" FOREIGN KEY (clearing_user_id) REFERENCES users(id)
Referenced by:
TABLE "events" CONSTRAINT "events_clearing_event_ref_fk" FOREIGN KEY (clearing_event_id) REFERENCES events(id)
TABLE "event_params" CONSTRAINT "events_params_event_id_fk" FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
Triggers:
event_validate BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE event_validate()
I considered a few workarounds, but I'd really rather know why it's happening. There are a few other tables that also use bigint, so I don't want to just hack a solution in place.
This is scripted with Liquibase, but it happens directly in the Postgres console too.
Update
Two other points:
I can create a simple table with a bigint id and a unique index on id, add the primary key, and the column type stays the same.
All tables are empty at the time execution.
Could it have something to do with the constraints?
That's pretty interesting. I can't reproduce it with version 9.1.0 (yes, I should upgrade too!). But then I don't know precisely how the original table and sequence were created.
This page seems to allude to a similar automatic change of types between SERIAL and INTEGER: http://grover.open2space.com/content/migrate-data-postgresql-and-maintain-existing-primary-key
Could it be something like creating the table using SERIAL instead of BIGSERIAL, and then forcing the type to BIGINT? Something in between the sequence and primary key manipulations might have reset it.
I wasn't able to reproduce this the next day, even after reproducing it multiple times with witnesses the first time it occurred. I'm chalking it up to gremlins.