-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[BACKPORT 2.20][#23686] YSQL: Build relcache foreign key list from YB…
… catcache Summary: Original commit: 3e93354 / D37595 Today, when preloading is enabled (either `ysql_catalog_preload_additional_tables` or `ysql_catalog_preload_additional_table_list` is set), we preload the relcache, meaning that we load the relcache entry for every relation in one shot. When we do relcache preloading, we currently don't load foreign key lists—instead, we loading them on-demand. This means on a given connection, the first time each table with a foreign key is referenced, that connection has to fetch the foreign key list from the master leader. With this revision, we make two changes: (1) Modify `RelationGetFKeyList` so that it reads foreign keys from the Yugabyte-only `pg_constraint` catcache `YBCONSTRAINTRELIDTYPIDNAME`. Each time `RelationGetFKeyList` is invoked, it will do a `SearchCatCacheList` on this cache with the partial key `conrelid`. (2) Whenever we preload the `pg_constraint` cache, we also preload the list cache for the partial key `conrelid`. This has the effect that any calls to `RelationGetFKeyList` after preloading will be able to read from the cached list and will not have to go to master. (A lookup for a table created on a different connection after preloading will still need to go to master). Both of these changes are controlled by a new GUC `yb_enable_fkey_catcache` (+tserver gflag wrapper) that is on by default. Jira: DB-12593 Test Plan: ``` ./yb_build.sh --cxx-test pg_catalog_perf-test --gtest_filter "*ForeignKeyRelcachePreloadTest*" ``` Reviewers: myang Reviewed By: myang Subscribers: yql Differential Revision: https://phorge.dev.yugabyte.com/D38520
- Loading branch information
Showing
11 changed files
with
292 additions
and
11 deletions.
There are no files selected for viewing
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
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
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
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,3 +18,78 @@ EXPLAIN (COSTS OFF) INSERT INTO GH_22967 VALUES ((EXISTS(SELECT 1) in (SELECT tr | |
(6 rows) | ||
|
||
INSERT INTO GH_22967 VALUES ((EXISTS(SELECT 1) in (SELECT true))::INT4), (-10); | ||
-- Test that foreign key constraints are enforced | ||
CREATE TABLE customers ( | ||
customer_id SERIAL PRIMARY KEY, | ||
name VARCHAR(100) NOT NULL, | ||
email VARCHAR(100) UNIQUE NOT NULL | ||
); | ||
CREATE TABLE orders ( | ||
order_id SERIAL PRIMARY KEY, | ||
order_date DATE NOT NULL, | ||
amount DECIMAL(10, 2) NOT NULL, | ||
customer_id INTEGER NOT NULL, | ||
FOREIGN KEY (customer_id) REFERENCES customers(customer_id) | ||
); | ||
INSERT INTO customers (name, email) VALUES | ||
('Alice Johnson', '[email protected]'), | ||
('Bob Smith', '[email protected]'); | ||
INSERT INTO orders (order_date, amount, customer_id) VALUES | ||
('2023-10-01', 250.00, 1), | ||
('2023-10-02', 450.50, 2); | ||
-- Attempt to insert an order with a non-existent customer | ||
INSERT INTO orders (order_date, amount, customer_id) VALUES | ||
('2023-10-03', 300.00, 3); | ||
ERROR: insert or update on table "orders" violates foreign key constraint "orders_customer_id_fkey" | ||
DETAIL: Key (customer_id)=(3) is not present in table "customers". | ||
-- Attempt to delete a customer that still has orders | ||
DELETE FROM customers WHERE customer_id = 2; | ||
ERROR: update or delete on table "customers" violates foreign key constraint "orders_customer_id_fkey" on table "orders" | ||
DETAIL: Key (customer_id)=(2) is still referenced from table "orders". | ||
-- Test cascading deletes | ||
DROP TABLE orders; | ||
CREATE TABLE orders_cascade ( | ||
order_id SERIAL PRIMARY KEY, | ||
order_date DATE NOT NULL, | ||
amount DECIMAL(10, 2) NOT NULL, | ||
customer_id INTEGER NOT NULL, | ||
FOREIGN KEY (customer_id) REFERENCES customers(customer_id) ON DELETE CASCADE | ||
); | ||
INSERT INTO orders_cascade (order_date, amount, customer_id) VALUES | ||
('2023-10-01', 250.00, 1), | ||
('2023-10-02', 450.50, 2); | ||
DELETE FROM customers WHERE customer_id = 2; | ||
SELECT * FROM orders_cascade; | ||
order_id | order_date | amount | customer_id | ||
----------+------------+--------+------------- | ||
1 | 10-01-2023 | 250.00 | 1 | ||
(1 row) | ||
|
||
-- Test adding foreign key constraint using ALTER TABLE ADD CONSTRAINT | ||
CREATE TABLE customers_test ( | ||
customer_id SERIAL PRIMARY KEY, | ||
name VARCHAR(100) NOT NULL | ||
); | ||
CREATE TABLE orders_test ( | ||
order_id SERIAL PRIMARY KEY, | ||
customer_id INTEGER, | ||
name VARCHAR(100) NOT NULL | ||
); | ||
-- Add foreign key constraint using ALTER TABLE | ||
ALTER TABLE orders_test | ||
ADD CONSTRAINT fk_orders_customers | ||
FOREIGN KEY (customer_id) REFERENCES customers_test(customer_id); | ||
-- Insert valid data | ||
INSERT INTO customers_test (name) VALUES ('Customer 1'), ('Customer 2'); | ||
INSERT INTO orders_test (customer_id, name) VALUES (1, 'Order 1'), (2, 'Order 2'); | ||
-- Attempt to insert a child with a non-existent customer | ||
INSERT INTO orders_test (customer_id, name) VALUES (3, 'Order 3'); | ||
ERROR: insert or update on table "orders_test" violates foreign key constraint "fk_orders_customers" | ||
DETAIL: Key (customer_id)=(3) is not present in table "customers_test". | ||
-- Attempt to delete a customer that still has orders | ||
DELETE FROM customers_test WHERE customer_id = 2; | ||
ERROR: update or delete on table "customers_test" violates foreign key constraint "fk_orders_customers" on table "orders_test" | ||
DETAIL: Key (customer_id)=(2) is still referenced from table "orders_test". | ||
-- Test that invalidation of the foreign key cache works | ||
ALTER TABLE orders_test DROP CONSTRAINT fk_orders_customers; | ||
INSERT INTO orders_test (customer_id, name) VALUES (3, 'Order 3'); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,81 @@ | |
CREATE TABLE GH_22967 (k INT4 PRIMARY KEY); | ||
EXPLAIN (COSTS OFF) INSERT INTO GH_22967 VALUES ((EXISTS(SELECT 1) in (SELECT true))::INT4), (-10); | ||
INSERT INTO GH_22967 VALUES ((EXISTS(SELECT 1) in (SELECT true))::INT4), (-10); | ||
|
||
|
||
-- Test that foreign key constraints are enforced | ||
CREATE TABLE customers ( | ||
customer_id SERIAL PRIMARY KEY, | ||
name VARCHAR(100) NOT NULL, | ||
email VARCHAR(100) UNIQUE NOT NULL | ||
); | ||
|
||
CREATE TABLE orders ( | ||
order_id SERIAL PRIMARY KEY, | ||
order_date DATE NOT NULL, | ||
amount DECIMAL(10, 2) NOT NULL, | ||
customer_id INTEGER NOT NULL, | ||
FOREIGN KEY (customer_id) REFERENCES customers(customer_id) | ||
); | ||
|
||
INSERT INTO customers (name, email) VALUES | ||
('Alice Johnson', '[email protected]'), | ||
('Bob Smith', '[email protected]'); | ||
|
||
INSERT INTO orders (order_date, amount, customer_id) VALUES | ||
('2023-10-01', 250.00, 1), | ||
('2023-10-02', 450.50, 2); | ||
|
||
-- Attempt to insert an order with a non-existent customer | ||
INSERT INTO orders (order_date, amount, customer_id) VALUES | ||
('2023-10-03', 300.00, 3); | ||
|
||
-- Attempt to delete a customer that still has orders | ||
DELETE FROM customers WHERE customer_id = 2; | ||
|
||
-- Test cascading deletes | ||
DROP TABLE orders; | ||
CREATE TABLE orders_cascade ( | ||
order_id SERIAL PRIMARY KEY, | ||
order_date DATE NOT NULL, | ||
amount DECIMAL(10, 2) NOT NULL, | ||
customer_id INTEGER NOT NULL, | ||
FOREIGN KEY (customer_id) REFERENCES customers(customer_id) ON DELETE CASCADE | ||
); | ||
INSERT INTO orders_cascade (order_date, amount, customer_id) VALUES | ||
('2023-10-01', 250.00, 1), | ||
('2023-10-02', 450.50, 2); | ||
DELETE FROM customers WHERE customer_id = 2; | ||
SELECT * FROM orders_cascade; | ||
|
||
|
||
-- Test adding foreign key constraint using ALTER TABLE ADD CONSTRAINT | ||
CREATE TABLE customers_test ( | ||
customer_id SERIAL PRIMARY KEY, | ||
name VARCHAR(100) NOT NULL | ||
); | ||
|
||
CREATE TABLE orders_test ( | ||
order_id SERIAL PRIMARY KEY, | ||
customer_id INTEGER, | ||
name VARCHAR(100) NOT NULL | ||
); | ||
|
||
-- Add foreign key constraint using ALTER TABLE | ||
ALTER TABLE orders_test | ||
ADD CONSTRAINT fk_orders_customers | ||
FOREIGN KEY (customer_id) REFERENCES customers_test(customer_id); | ||
|
||
-- Insert valid data | ||
INSERT INTO customers_test (name) VALUES ('Customer 1'), ('Customer 2'); | ||
INSERT INTO orders_test (customer_id, name) VALUES (1, 'Order 1'), (2, 'Order 2'); | ||
|
||
-- Attempt to insert a child with a non-existent customer | ||
INSERT INTO orders_test (customer_id, name) VALUES (3, 'Order 3'); | ||
|
||
-- Attempt to delete a customer that still has orders | ||
DELETE FROM customers_test WHERE customer_id = 2; | ||
|
||
-- Test that invalidation of the foreign key cache works | ||
ALTER TABLE orders_test DROP CONSTRAINT fk_orders_customers; | ||
INSERT INTO orders_test (customer_id, name) VALUES (3, 'Order 3'); |
Oops, something went wrong.