# LogicTest: multiregion-9node-3region-3azs multiregion-9node-3region-3azs-no-los
# TODO(#75864): enable multiregion-9node-3region-3azs-tenant.

# Set the closed timestamp interval to be short to shorten the amount of time
# we need to wait for the system config to propagate.
statement ok
SET CLUSTER SETTING kv.closed_timestamp.side_transport_interval = '10ms';

statement ok
SET CLUSTER SETTING kv.closed_timestamp.target_duration = '10ms';

statement ok
SET CLUSTER SETTING kv.rangefeed.closed_timestamp_refresh_interval = '10ms';

statement ok
CREATE DATABASE multi_region_test_db PRIMARY REGION "ca-central-1" REGIONS "ap-southeast-2", "us-east-1";

statement ok
USE multi_region_test_db

statement ok
CREATE TABLE parent (
  id INT,
  crdb_region crdb_internal_region NOT VISIBLE NOT NULL AS (CASE WHEN id BETWEEN 0 AND 99 THEN 'ap-southeast-2':::crdb_internal_region WHEN id BETWEEN 100 AND 199 THEN 'us-east-1':::crdb_internal_region ELSE 'ca-central-1':::crdb_internal_region END) STORED,
  PRIMARY KEY (id)
) LOCALITY REGIONAL BY ROW

statement ok
CREATE TABLE child (
  id INT,
  crdb_region crdb_internal_region NOT VISIBLE NOT NULL AS (CASE WHEN id BETWEEN 0 AND 99 THEN 'ap-southeast-2':::crdb_internal_region WHEN id BETWEEN 100 AND 199 THEN 'us-east-1':::crdb_internal_region ELSE 'ca-central-1':::crdb_internal_region END) STORED,
  p_id INT REFERENCES parent (id),
  PRIMARY KEY (id)
) LOCALITY REGIONAL BY ROW

# A foreign key check only needs to search a single region for each insert row
# if the region column is a computed column.
query T retry
EXPLAIN INSERT INTO child (id, p_id) VALUES (1, 10), (2, 150)
----
distribution: local
vectorized: true
·
• root
│
├── • insert
│   │ into: child(id, crdb_region, p_id)
│   │
│   └── • buffer
│       │ label: buffer 1
│       │
│       └── • render
│           │
│           └── • render
│               │
│               └── • values
│                     size: 2 columns, 2 rows
│
└── • constraint-check
    │
    └── • error if rows
        │
        └── • lookup join (anti)
            │ table: parent@parent_pkey
            │ equality: (crdb_region_eq, p_id) = (crdb_region, id)
            │ equality cols are key
            │
            └── • render
                │
                └── • scan buffer
                      estimated row count: 2
                      label: buffer 1


# NB: This doesn't include the foreign key reference to warehouse since we
# don't need the warehouse table for this test.
# NB: The crdb_region columns have been changed from computed columns to columns
# with default values since a foreign key check with a computed region column
# would only require a lookup in a single region.
statement ok
CREATE TABLE district (
        d_id INT8 NOT NULL,
        d_w_id INT8 NOT NULL,
        d_name VARCHAR(10) NOT NULL,
        d_street_1 VARCHAR(20) NOT NULL,
        d_street_2 VARCHAR(20) NOT NULL,
        d_city VARCHAR(20) NOT NULL,
        d_state CHAR(2) NOT NULL,
        d_zip CHAR(9) NOT NULL,
        d_tax DECIMAL(4,4) NOT NULL,
        d_ytd DECIMAL(12,2) NOT NULL,
        d_next_o_id INT8 NOT NULL,
        crdb_region crdb_internal_region NOT VISIBLE NOT NULL DEFAULT gateway_region()::crdb_internal_region,
        CONSTRAINT "primary" PRIMARY KEY (d_w_id ASC, d_id ASC),
        FAMILY "primary" (d_id, d_w_id, d_name, d_street_1, d_street_2, d_city, d_state, d_zip, d_tax, d_ytd, d_next_o_id, crdb_region)
) LOCALITY REGIONAL BY ROW

statement ok
CREATE TABLE customer (
        c_id INT8 NOT NULL,
        c_d_id INT8 NOT NULL,
        c_w_id INT8 NOT NULL,
        c_first VARCHAR(16) NOT NULL,
        c_middle CHAR(2) NOT NULL,
        c_last VARCHAR(16) NOT NULL,
        c_street_1 VARCHAR(20) NOT NULL,
        c_street_2 VARCHAR(20) NOT NULL,
        c_city VARCHAR(20) NOT NULL,
        c_state CHAR(2) NOT NULL,
        c_zip CHAR(9) NOT NULL,
        c_phone CHAR(16) NOT NULL,
        c_since TIMESTAMP NOT NULL,
        c_credit CHAR(2) NOT NULL,
        c_credit_lim DECIMAL(12,2) NOT NULL,
        c_discount DECIMAL(4,4) NOT NULL,
        c_balance DECIMAL(12,2) NOT NULL,
        c_ytd_payment DECIMAL(12,2) NOT NULL,
        c_payment_cnt INT8 NOT NULL,
        c_delivery_cnt INT8 NOT NULL,
        c_data VARCHAR(500) NOT NULL,
        crdb_region crdb_internal_region NOT VISIBLE NOT NULL DEFAULT gateway_region()::crdb_internal_region,
        CONSTRAINT "primary" PRIMARY KEY (c_w_id ASC, c_d_id ASC, c_id ASC),
        CONSTRAINT fk_c_w_id_ref_district FOREIGN KEY (c_w_id, c_d_id) REFERENCES district(d_w_id, d_id) NOT VALID,
        INDEX customer_idx (c_w_id ASC, c_d_id ASC, c_last ASC, c_first ASC),
        FAMILY "primary" (c_id, c_d_id, c_w_id, c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_since, c_credit, c_credit_lim, c_discount, c_balance, c_ytd_payment, c_payment_cnt, c_delivery_cnt, c_data, crdb_region)
) LOCALITY REGIONAL BY ROW

statement ok
CREATE TABLE history (
        rowid UUID NOT NULL DEFAULT gen_random_uuid(),
        h_c_id INT8 NOT NULL,
        h_c_d_id INT8 NOT NULL,
        h_c_w_id INT8 NOT NULL,
        h_d_id INT8 NOT NULL,
        h_w_id INT8 NOT NULL,
        h_date TIMESTAMP NULL,
        h_amount DECIMAL(6,2) NULL,
        h_data VARCHAR(24) NULL,
        crdb_region crdb_internal_region NOT VISIBLE NOT NULL DEFAULT gateway_region()::crdb_internal_region,
        CONSTRAINT "primary" PRIMARY KEY (h_w_id ASC, rowid ASC),
        CONSTRAINT fk_h_c_w_id_ref_customer FOREIGN KEY (h_c_w_id, h_c_d_id, h_c_id) REFERENCES customer(c_w_id, c_d_id, c_id) NOT VALID,
        CONSTRAINT fk_h_w_id_ref_district FOREIGN KEY (h_w_id, h_d_id) REFERENCES district(d_w_id, d_id) NOT VALID,
        FAMILY "primary" (rowid, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date, h_amount, h_data, crdb_region)
) LOCALITY REGIONAL BY ROW

statement ok
ALTER TABLE district INJECT STATISTICS '[
    {
        "columns": [
            "d_w_id"
        ],
        "created_at": "2021-04-13 19:54:56.008454",
        "distinct_count": 5004,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 50000
    },
    {
        "columns": [
            "d_id"
        ],
        "created_at": "2021-04-13 19:54:56.008454",
        "distinct_count": 10,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 50000
    }
]'

statement ok
ALTER TABLE customer INJECT STATISTICS '[
    {
        "columns": [
            "c_d_id"
        ],
        "created_at": "2021-04-13 20:35:46.476858",
        "distinct_count": 10,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    },
    {
        "columns": [
            "c_w_id"
        ],
        "created_at": "2021-04-13 20:35:46.476858",
        "distinct_count": 4998,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    },
    {
        "columns": [
            "c_id"
        ],
        "created_at": "2021-04-13 20:35:46.476858",
        "distinct_count": 2999,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    }
]'

statement ok
ALTER TABLE history INJECT STATISTICS '[
    {
        "columns": [
            "h_w_id"
        ],
        "created_at": "2021-04-13 20:58:06.757925",
        "distinct_count": 4998,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    },
    {
        "columns": [
            "h_c_id"
        ],
        "created_at": "2021-04-13 20:58:06.757925",
        "distinct_count": 2999,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    },
    {
        "columns": [
            "h_c_d_id"
        ],
        "created_at": "2021-04-13 20:58:06.757925",
        "distinct_count": 10,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    },
    {
        "columns": [
            "h_c_w_id"
        ],
        "created_at": "2021-04-13 20:58:06.757925",
        "distinct_count": 4998,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    },
    {
        "columns": [
            "h_d_id"
        ],
        "created_at": "2021-04-13 20:58:06.757925",
        "distinct_count": 10,
        "name": "__auto__",
        "null_count": 0,
        "row_count": 150000000
    }
]'

# Regression test for #63735. Ensure that we choose locality optimized anti
# joins for the foreign key checks.
skipif config multiregion-9node-3region-3azs-no-los
query T retry
EXPLAIN INSERT
INTO
  history (h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_amount, h_date, h_data)
VALUES
  (2057, 4, 3, 4, 3, 2100.9, '2021-04-15 15:22:14', '9    zmssaF9m')
----
distribution: local
vectorized: true
·
• root
│
├── • insert
│   │ into: history(rowid, h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id, h_date, h_amount, h_data, crdb_region)
│   │
│   └── • buffer
│       │ label: buffer 1
│       │
│       └── • values
│             size: 11 columns, 1 row
│
├── • constraint-check
│   │
│   └── • error if rows
│       │
│       └── • lookup join (anti)
│           │ estimated row count: 0
│           │ table: customer@primary
│           │ equality cols are key
│           │ lookup condition: (((crdb_region IN ('ca-central-1', 'us-east-1')) AND (column3 = c_w_id)) AND (column2 = c_d_id)) AND (column1 = c_id)
│           │
│           └── • lookup join (anti)
│               │ estimated row count: 1
│               │ table: customer@primary
│               │ equality cols are key
│               │ lookup condition: (((crdb_region = 'ap-southeast-2') AND (column3 = c_w_id)) AND (column2 = c_d_id)) AND (column1 = c_id)
│               │
│               └── • scan buffer
│                     estimated row count: 1
│                     label: buffer 1
│
└── • constraint-check
    │
    └── • error if rows
        │
        └── • lookup join (anti)
            │ estimated row count: 0
            │ table: district@primary
            │ equality cols are key
            │ lookup condition: ((crdb_region IN ('ca-central-1', 'us-east-1')) AND (column5 = d_w_id)) AND (column4 = d_id)
            │
            └── • lookup join (anti)
                │ estimated row count: 1
                │ table: district@primary
                │ equality cols are key
                │ lookup condition: ((crdb_region = 'ap-southeast-2') AND (column5 = d_w_id)) AND (column4 = d_id)
                │
                └── • scan buffer
                      estimated row count: 1
                      label: buffer 1

# Regression test for #62269. Ensure that locality optimized search results in
# a local plan, even when there is a lookup join or an inverted join.
statement ok
CREATE TABLE promos (
  promo_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  discount DECIMAL NOT NULL,
  info JSON,
  INVERTED INDEX (info),
  FAMILY (promo_id, discount, info)
) LOCALITY GLOBAL;
CREATE TABLE orders (
  order_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  price    DECIMAL NOT NULL,
  promo_id UUID REFERENCES promos,
  info JSON,
  FAMILY (order_id, price, promo_id, info)
) LOCALITY REGIONAL BY ROW

statement ok
INSERT INTO promos VALUES ('7fe2dce4-ecac-4d12-87b6-e1c1f837d835', 50, '{"some": "info"}');
INSERT INTO orders
  VALUES ('94e4b847-8f2f-4ac5-83f1-641d6e3df727', 100, '7fe2dce4-ecac-4d12-87b6-e1c1f837d835', '{"some": "info"}')

skipif config multiregion-9node-3region-3azs-no-los
query T nodeidx=3
USE multi_region_test_db; EXPLAIN (DISTSQL) SELECT
    order_id, promo_id, price AS price_without_promo, price * discount AS price_with_promo
FROM
    orders JOIN promos USING (promo_id)
WHERE
    order_id = '94e4b847-8f2f-4ac5-83f1-641d6e3df727'
----
distribution: local
vectorized: true
·
• render
│
└── • lookup join
    │ table: promos@promos_pkey
    │ equality: (promo_id) = (promo_id)
    │ equality cols are key
    │
    └── • union all
        │ limit: 1
        │
        ├── • scan
        │     missing stats
        │     table: orders@orders_pkey
        │     spans: [/'ca-central-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727' - /'ca-central-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727']
        │
        └── • scan
              missing stats
              table: orders@orders_pkey
              spans: [/'ap-southeast-2'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727' - /'ap-southeast-2'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727'] [/'us-east-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727' - /'us-east-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727']
·
Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJysk2tP2zwUx98_n8I6b7goVXODlkhIQdCHFZXC2k6bNFdViE_AI7Uz2xFFqK_22fa9JieUXkTRQIvU-Hb69_n9T84T6J85RND5dt076fbJ7ll3OBp-7u2RYafXOR0RqRiqCWcOKZScyucZT5GcDOvJ5IGbO1maSRWwON0njOtUlsKsB9ZR5P_B1WWtrcnFVbdfq2vyZdjtn5PdxV175OunzqDzkgU5JjtHIYY37bDVaGd-1giT9KDRDjKvcRh67BADlrX81g44ICTDfjJFDdF3CGHsQKFkilpLZbeeqoAum0HkOsBFURq7PXYglQohegLDTY4QwSi5yXGACUPVdMEBhibheSVbE8T1MCnu8REcOJV5ORU6WvOOp7i0EBwYFokNaVKIKTQpUDo7CimdoX3dtM8pnbWz5sXvX5TOMo9ROvOYOLaL1g6FpksSwYhHpLlDBeO5A7I0SwRtkluEyFth7p5B5M6dj2F7_x7bArofQt-K62_geltxl5QaFU9yUooqa2RroOP5K770ZUMWTX_dkR6fckO8ram5G6n576nEheTiuRDB-rV118T1sChET8r7siA_JBdEiojEwWp1lm28aFBwYICCoYpI7DkkDhwS-_a3Hx9sBQo2gIL3AA1QF1Jo3DD776xreLYqyG6xrqSWpUrxWsm0iq2XV5VQtcFQm_rUrxddUR159gaFyfTlU1lV8j6q5G4q-W8qBWtK7qqSv6kUvKkUbldyrWNZLh9sE0bgPj-NV16LB-wfklttyza8kw-V7OixsKZnSa7RgcvkHs_QoJpywbXhKURGlTif__cnAAD__8jUE1E=

skipif config multiregion-9node-3region-3azs-no-los
query T nodeidx=3
USE multi_region_test_db; EXPLAIN (DISTSQL) SELECT
    order_id, promos.promo_id, price AS price_without_promo, price * discount AS price_with_promo
FROM
    orders JOIN promos ON promos.info @> orders.info
WHERE
    order_id = '94e4b847-8f2f-4ac5-83f1-641d6e3df727'
----
distribution: local
vectorized: true
·
• render
│
└── • lookup join
    │ table: promos@promos_pkey
    │ equality: (promo_id) = (promo_id)
    │ equality cols are key
    │ pred: info @> info
    │
    └── • inverted join
        │ table: promos@promos_info_idx
        │
        └── • union all
            │ limit: 1
            │
            ├── • scan
            │     missing stats
            │     table: orders@orders_pkey
            │     spans: [/'ca-central-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727' - /'ca-central-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727']
            │
            └── • scan
                  missing stats
                  table: orders@orders_pkey
                  spans: [/'ap-southeast-2'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727' - /'ap-southeast-2'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727'] [/'us-east-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727' - /'us-east-1'/'94e4b847-8f2f-4ac5-83f1-641d6e3df727']
·
Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyslN1u2zYUx-_3FMS5yVbQtT5jV0ABFo23OXDtzg6wAVNgKOJRwsUmNZJaVAS-2rPtvQZKzoeFyluCCrAokod__n_kOb4H8-cGEpj89nn2YTon359NVxerX2Y_kNVkNvl4QZTmqNeCU1JqtVXmbdPsB0SO5MOq_VjfCXujKrtuAh5m3xAuTK4qaQ8D2yjy43Lxqd3CkPPFdL7fhCwevt4KWSjC0srzQtxHtmO__jxZTh7tkffk5F2E0dU4Gg3GRVAMoiyPB-Ow8Aenkc9PMeTFKBidAAWpOM6zLRpIfocILimUWuVojNJu6L4JmPIaEo-CkGVl3fAlhVxphOQerLAbhAQusqsNLjHjqIceUOBoM7FpZFunrG3W5S1-AQof1abaSpMcHKrIkRJHBBRWZeamhymwFIYppGn9LkrTGt3ravxTmtbjYnj-z99pWhc-T9Pa5_K964xOUhh6JJOc-ETZG9RwuaOgKvtk39jsGiHxn_FOzyDxdvR1yP63RXZw3quwe1GDDqrfi_pEaFCLbEMq2ThGfgB5ufvKmczVQJXD4PA0ZmIrLPF7rXkda8FLbmEq_0JtkZ8rIVEPw8Ot28phbbN257wWvAb6uGxSl5qw-LGsWPj8pp4KfH9Fi8omhPmUBZSFlEW9TGGHKXwJk2PZJ1Z0jGefWDOlbquS_KGEJEomhLlFizlho__EevhH6gOMKTulbNSLGXUwo5dgtskSHxIuUXLUjQfCIkpY4H5vWNzrIe54iF_iYYmmVNJgJ7X_X6IOfFcDyK-xrRujKp3jZ63yJrbtLhqhZoCjse1s0Hamspny3Q4as-1jYT5X8l-r5HWVgqNK4YGS91wp6CqFR5WifqWwqxQdVYr7laKuUnxU6bRfyXO3WGzU3VpwSMDbP4OvvB4ecAuya-NSaXWj7hrZiy-lS4Qi2xik8Cm7xTO0qLdCCmNFDonVFe523_0bAAD__51rvcs=

# Regression test for #74890. Code should not panic due to distribution already
# provided by input.
statement ok nodeidx=3
USE multi_region_test_db; CREATE TABLE t74890 AS
SELECT generate_series(1, 5) AS g

query I nodeidx=3
USE multi_region_test_db; SELECT g FROM t74890 ORDER BY g
----
1
2
3
4
5

# Regression test for #85043. Distribute enforcer should not prevent the
# optimizer from planning auto-commit.
statement ok
CREATE DATABASE one_region_test_db PRIMARY REGION "ca-central-1";
USE one_region_test_db;
CREATE TABLE t85043 (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  ts TIMESTAMP
);

query T
EXPLAIN UPDATE t85043 SET ts = '2022-08-01 18:07:07' WHERE id = 'ab020c49-ba5e-4800-8000-00000000014e'
----
distribution: local
vectorized: true
·
• update
│ table: t85043
│ set: ts
│ auto commit
│
└── • render
    │
    └── • scan
          missing stats
          table: t85043@t85043_pkey
          spans: [/'ab020c49-ba5e-4800-8000-00000000014e' - /'ab020c49-ba5e-4800-8000-00000000014e']
          locking strength: for update

# Regression test for #85288. Distribute enforcer should not prevent the
# optimizer from using bounded staleness.
statement ok
CREATE TABLE t85288 (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  ts TIMESTAMP
);

statement ok
select ts FROM t85288 AS OF SYSTEM TIME with_max_staleness('1h') WHERE
 id = '00000000-0000-4000-8000-000000000000';
