# This test ensures that table, database and cluster backups properly
# backup and restore an IMPORT INTO of an empty table (foo) and a non empty table (foofoo).
#
# On a fully upgraded cluster: the table should get rolled back to its pre-import state after RESTORE
# On an unfinalized cluster: a backed up import should not get restored


new-cluster name=s1
----


exec-sql
CREATE DATABASE d;
USE d;
CREATE TABLE foo (i INT PRIMARY KEY, s STRING);
CREATE TABLE foofoo (i INT PRIMARY KEY, s STRING);
INSERT INTO foofoo VALUES (10, 'x0');
CREATE TABLE baz (i INT PRIMARY KEY, s STRING);
INSERT INTO baz VALUES (1, 'x'),(2,'y'),(3,'z');
----


exec-sql
SET CLUSTER SETTING jobs.debug.pausepoints = 'import.after_ingest';
----


exec-sql
EXPORT INTO CSV 'nodelocal://1/export1/' FROM SELECT * FROM baz WHERE i = 1;
----
NOTICE: EXPORT is not the recommended way to move data out of CockroachDB and may be deprecated in the future. Please consider exporting data with changefeeds instead: https://www.cockroachlabs.com/docs/stable/export-data-with-changefeeds

# Pause the import job, in order to back up the importing data.
import expect-pausepoint tag=a
IMPORT INTO foo (i,s) CSV DATA ('nodelocal://1/export1/export*-n*.0.csv')
----
job paused at pausepoint


import expect-pausepoint tag=aa
IMPORT INTO foofoo (i,s) CSV DATA ('nodelocal://1/export1/export*-n*.0.csv')
----
job paused at pausepoint


# Ensure table, database, and cluster full backups capture importing rows.
exec-sql
BACKUP INTO 'nodelocal://1/cluster/' WITH revision_history;
----


exec-sql
BACKUP DATABASE d INTO 'nodelocal://1/database/' WITH revision_history;
----

exec-sql
BACKUP TABLE d.* INTO 'nodelocal://1/table/' WITH revision_history;
----

# Ensure incremental backups do NOT re-capture the importing rows while the tables are offline
exec-sql
BACKUP INTO LATEST IN 'nodelocal://1/cluster/' WITH revision_history;
----

exec-sql
BACKUP DATABASE d INTO LATEST IN 'nodelocal://1/database/' WITH revision_history;
----


exec-sql
BACKUP TABLE d.* INTO LATEST IN 'nodelocal://1/table/' WITH revision_history;
----


save-cluster-ts tag=t0
----

exec-sql
SET CLUSTER SETTING jobs.debug.pausepoints = '';
----


# Resume the job so the next set of incremental backups observes that tables are back online
job resume=a
----

job resume=aa
----

job tag=a wait-for-state=succeeded
----


job tag=aa wait-for-state=succeeded
----


# NOTE: currently the backups below re-capture the _2_ versions of each imported key:
#  1: the original data that was already captured in the previous backup because BACKUP currently
#     re-backs up the whole span once the table goes back online. This will change.
#  2. when the import job resumes, the data is re-ingested, hence a second version of the imported
#     data gets ingested into the backing up cluster, and consequently, the incremental backup.
#     This occurs because when a restore job resumes after all data was initially ingested, the last
#     check pointed restore span entry (i.e. in the mu.requestsCompleted object) gets re-ingested.
#     -- in this case, there's only one span in the restore job, so all data gets re-ingested.


exec-sql
BACKUP INTO LATEST IN 'nodelocal://1/cluster/' WITH revision_history;
----


exec-sql
BACKUP DATABASE d INTO LATEST IN 'nodelocal://1/database/' WITH revision_history;
----


exec-sql
BACKUP TABLE d.* INTO LATEST IN 'nodelocal://1/table/' WITH revision_history;
----


# In all backup chains, the following rows get captured:
# - Full backup: the original data + data from in-progress import (1 row in foo, 2 in foofoo)
# - First incremental backup: nothing, no new data was ingested and the table is still offline
# - Second incremental backup (2 row in foo, 3 in foofoo):
#   - a full backup of the importing data because the tables returned online (1 row in foo, 2 in foofoo)
#   - and duplicates of the importing data (1 row in foo, 1 in foofoo) because of import job
#     checkpointing behavior. See note above.

query-sql
SELECT
  database_name, object_name, object_type, rows, backup_type
FROM
  [SHOW BACKUP FROM LATEST IN 'nodelocal://1/cluster/']
WHERE
  object_name = 'foo' or object_name = 'foofoo'
ORDER BY
  start_time, database_name;
----
d foo table 1 full
d foofoo table 2 full
d foo table 0 incremental
d foofoo table 0 incremental
d foo table 1 incremental
d foofoo table 1 incremental

query-sql
SELECT
  database_name, object_name, object_type, rows, backup_type
FROM
  [SHOW BACKUP FROM LATEST IN 'nodelocal://1/database/']
WHERE
  object_name = 'foo' or object_name = 'foofoo'
ORDER BY
  start_time, database_name;
----
d foo table 1 full
d foofoo table 2 full
d foo table 0 incremental
d foofoo table 0 incremental
d foo table 1 incremental
d foofoo table 1 incremental


query-sql
SELECT
  database_name, object_name, object_type, rows, backup_type
FROM
  [SHOW BACKUP FROM LATEST IN 'nodelocal://1/table/']
WHERE
  object_name = 'foo' or object_name = 'foofoo'
ORDER BY
  start_time, database_name;
----
d foo table 1 full
d foofoo table 2 full
d foo table 0 incremental
d foofoo table 0 incremental
d foo table 1 incremental
d foofoo table 1 incremental


# Ensure all the RESTOREs contain foo (no data) and foofoo (1 row) as of system time t0
new-cluster name=s2 share-io-dir=s1 allow-implicit-access
----


restore aost=t0
RESTORE FROM LATEST IN 'nodelocal://1/cluster/' AS OF SYSTEM TIME t0;
----


query-sql
SELECT * FROM d.foo;
----


query-sql
SELECT * FROM d.foofoo;
----
10 x0


exec-sql
DROP DATABASE d;
----


restore aost=t0
RESTORE DATABASE d FROM LATEST IN 'nodelocal://1/database/' AS OF SYSTEM TIME t0;
----

query-sql
SELECT * FROM d.foo;
----


query-sql
SELECT * FROM d.foofoo;
----
10 x0


exec-sql
DROP TABLE d.foo;
DROP TABLE d.foofoo;
DROP TABLE d.baz;
----


restore aost=t0
RESTORE TABLE d.* FROM LATEST IN 'nodelocal://1/table/' AS OF SYSTEM TIME t0 WITH into_db='d';
----


query-sql
SELECT * FROM d.foo;
----


query-sql
SELECT * FROM d.foofoo;
----
10 x0


# Ensure the imported data exists as of latest time
new-cluster name=s3 share-io-dir=s1 allow-implicit-access
----


exec-sql
RESTORE FROM LATEST IN 'nodelocal://1/cluster/';
----


query-sql
SELECT * FROM d.foo;
----
1 x


query-sql
SELECT * FROM d.foofoo;
----
1 x
10 x0


exec-sql
DROP DATABASE d;
----


exec-sql
RESTORE DATABASE d FROM LATEST IN 'nodelocal://1/database/';
----


query-sql
SELECT * FROM d.foo;
----
1 x


query-sql
SELECT * FROM d.foofoo;
----
1 x
10 x0


exec-sql
DROP TABLE d.foo;
DROP TABLE d.foofoo;
DROP TABLE d.baz;
----


exec-sql
RESTORE TABLE d.* FROM LATEST IN 'nodelocal://1/table/' WITH into_db= d;
----


query-sql
SELECT * FROM d.foo;
----
1 x


query-sql
SELECT * FROM d.foofoo;
----
1 x
10 x0
