SET citus.shard_replication_factor to 1;
SET citus.next_shard_id TO 60000;
SET citus.next_placement_id TO 60000;
SET citus.shard_count TO 4;
create schema test_tableam;
set search_path to test_tableam;
SELECT public.run_command_on_coordinator_and_workers($Q$
	SET citus.enable_ddl_propagation TO off;
	CREATE FUNCTION fake_am_handler(internal)
	RETURNS table_am_handler
	AS 'citus'
	LANGUAGE C;
	CREATE ACCESS METHOD fake_am TYPE TABLE HANDLER fake_am_handler;
$Q$);
 run_command_on_coordinator_and_workers
---------------------------------------------------------------------

(1 row)

-- Since Citus assumes access methods are part of the extension, make fake_am
-- owned manually to be able to pass checks on Citus while distributing tables.
ALTER EXTENSION citus ADD ACCESS METHOD fake_am;
--
-- Hash distributed table using a non-default table access method
--
create table test_hash_dist(id int, val int) using fake_am;
insert into test_hash_dist values (1, 1);
WARNING:  fake_tuple_insert
select create_distributed_table('test_hash_dist','id', colocate_with := 'none');
WARNING:  fake_scan_getnextslot
CONTEXT:  SQL statement "SELECT TRUE FROM test_tableam.test_hash_dist LIMIT 1"
WARNING:  fake_scan_getnextslot
NOTICE:  Copying data from local table...
WARNING:  fake_scan_getnextslot
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_tableam.test_hash_dist$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

select * from test_hash_dist;
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
 id | val
---------------------------------------------------------------------
  1 |   1
(1 row)

insert into test_hash_dist values (1, 1);
WARNING:  fake_tuple_insert
DETAIL:  from localhost:xxxxx
-- we should error on following, since this AM is append only
SET client_min_messages TO ERROR;
delete from test_hash_dist where id=1;
ERROR:  fake_tuple_delete not implemented
CONTEXT:  while executing command on localhost:xxxxx
update test_hash_dist set val=2 where id=2;
RESET client_min_messages;
-- ddl events should include "USING fake_am"
SELECT * FROM master_get_table_ddl_events('test_hash_dist');
                           master_get_table_ddl_events
---------------------------------------------------------------------
 CREATE TABLE test_tableam.test_hash_dist (id integer, val integer) USING fake_am
 ALTER TABLE test_tableam.test_hash_dist OWNER TO postgres
(2 rows)

--
-- Reference table using a non-default table access method
--
create table test_ref(a int) using fake_am;
insert into test_ref values (1);
WARNING:  fake_tuple_insert
select create_reference_table('test_ref');
WARNING:  fake_scan_getnextslot
CONTEXT:  SQL statement "SELECT TRUE FROM test_tableam.test_ref LIMIT 1"
WARNING:  fake_scan_getnextslot
NOTICE:  Copying data from local table...
WARNING:  fake_scan_getnextslot
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_tableam.test_ref$$)
 create_reference_table
---------------------------------------------------------------------

(1 row)

select * from test_ref;
WARNING:  fake_scan_getnextslot
WARNING:  fake_scan_getnextslot
 a
---------------------------------------------------------------------
 1
(1 row)

insert into test_ref values (1);
WARNING:  fake_tuple_insert
DETAIL:  from localhost:xxxxx
WARNING:  fake_tuple_insert
DETAIL:  from localhost:xxxxx
WARNING:  fake_tuple_insert
-- we should error on following, since this AM is append only
SET client_min_messages TO ERROR;
delete from test_ref;
ERROR:  fake_tuple_delete not implemented
CONTEXT:  while executing command on localhost:xxxxx
update test_ref set a=2;
ERROR:  fake_fetch_row_version not implemented
CONTEXT:  while executing command on localhost:xxxxx
RESET client_min_messages;
-- ddl events should include "USING fake_am"
SELECT * FROM master_get_table_ddl_events('test_ref');
                 master_get_table_ddl_events
---------------------------------------------------------------------
 CREATE TABLE test_tableam.test_ref (a integer) USING fake_am
 ALTER TABLE test_tableam.test_ref OWNER TO postgres
(2 rows)

--
-- Range partitioned table using a non-default table access method
--
CREATE TABLE test_range_dist(id int, val int) using fake_am;
SELECT create_distributed_table('test_range_dist', 'id', 'range');
WARNING:  fake_scan_getnextslot
CONTEXT:  SQL statement "SELECT TRUE FROM test_tableam.test_range_dist LIMIT 1"
WARNING:  fake_scan_getnextslot
CONTEXT:  SQL statement "SELECT TRUE FROM test_tableam.test_range_dist LIMIT 1"
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CALL public.create_range_partitioned_shards('test_range_dist', '{"0","25"}','{"24","49"}');
select * from test_range_dist;
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
 id | val
---------------------------------------------------------------------
(0 rows)

insert into test_range_dist values (1, 1);
WARNING:  fake_tuple_insert
DETAIL:  from localhost:xxxxx
COPY test_range_dist FROM PROGRAM 'echo 0, 0 && echo 1, -1 && echo 2, 4 && echo 3, 9' WITH CSV;
COPY test_range_dist FROM PROGRAM 'echo 25, 16 && echo 26, 1 && echo 27, 4 && echo 7, 9' WITH CSV;
-- ddl events should include "USING fake_am"
SELECT * FROM master_get_table_ddl_events('test_range_dist');
                            master_get_table_ddl_events
---------------------------------------------------------------------
 CREATE TABLE test_tableam.test_range_dist (id integer, val integer) USING fake_am
 ALTER TABLE test_tableam.test_range_dist OWNER TO postgres
(2 rows)

--
-- Test copy_copy_shard_placement with a fake_am table
--
select a.shardid, a.nodeport
FROM pg_dist_shard b, pg_dist_shard_placement a
WHERE a.shardid=b.shardid AND logicalrelid = 'test_hash_dist'::regclass::oid
ORDER BY a.shardid, nodeport;
 shardid | nodeport
---------------------------------------------------------------------
   60000 |    57637
   60001 |    57638
   60002 |    57637
   60003 |    57638
(4 rows)

-- Change repmodel to allow copy_copy_shard_placement
UPDATE pg_dist_partition SET repmodel='c' WHERE logicalrelid = 'test_hash_dist'::regclass;
SELECT citus_copy_shard_placement(
           get_shard_id_for_distribution_column('test_hash_dist', '1'),
           'localhost', :worker_1_port,
           'localhost', :worker_2_port,
		   transfer_mode := 'block_writes');
 citus_copy_shard_placement
---------------------------------------------------------------------

(1 row)

select a.shardid, a.nodeport
FROM pg_dist_shard b, pg_dist_shard_placement a
WHERE a.shardid=b.shardid AND logicalrelid = 'test_hash_dist'::regclass::oid
ORDER BY a.shardid, nodeport;
 shardid | nodeport
---------------------------------------------------------------------
   60000 |    57637
   60000 |    57638
   60001 |    57638
   60002 |    57637
   60003 |    57638
(5 rows)

-- verify that data was copied correctly
\c - - - :worker_1_port
select * from test_tableam.test_hash_dist_60000 ORDER BY id;
WARNING:  fake_scan_getnextslot
WARNING:  fake_scan_getnextslot
WARNING:  fake_scan_getnextslot
 id | val
---------------------------------------------------------------------
  1 |   1
  1 |   1
(2 rows)

\c - - - :worker_2_port
select * from test_tableam.test_hash_dist_60000 ORDER BY id;
WARNING:  fake_scan_getnextslot
WARNING:  fake_scan_getnextslot
WARNING:  fake_scan_getnextslot
 id | val
---------------------------------------------------------------------
  1 |   1
  1 |   1
(2 rows)

\c - - - :master_port
set search_path to test_tableam;
--
-- Test that partitioned tables work correctly with a fake_am table
--
-- parent using default am, one of children using fake_am
CREATE TABLE test_partitioned(id int, p int, val int)
PARTITION BY RANGE (p);
CREATE TABLE test_partitioned_p1 PARTITION OF test_partitioned
	FOR VALUES FROM (1) TO (10);
CREATE TABLE test_partitioned_p2 PARTITION OF test_partitioned
	FOR VALUES FROM (11) TO (20) USING fake_am;
INSERT INTO test_partitioned VALUES (1, 5, -1), (2, 15, -2);
WARNING:  fake_tuple_insert
SELECT create_distributed_table('test_partitioned', 'id');
NOTICE:  Copying data from local table...
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_tableam.test_partitioned_p1$$)
WARNING:  fake_scan_getnextslot
CONTEXT:  SQL statement "SELECT TRUE FROM test_tableam.test_partitioned_p2 LIMIT 1"
WARNING:  fake_scan_getnextslot
NOTICE:  Copying data from local table...
WARNING:  fake_scan_getnextslot
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_tableam.test_partitioned_p2$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO test_partitioned VALUES (3, 6, -6), (4, 16, -4);
WARNING:  fake_tuple_insert
DETAIL:  from localhost:xxxxx
WARNING:  fake_tuple_insert
DETAIL:  from localhost:xxxxx
SELECT count(*) FROM test_partitioned;
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
WARNING:  fake_scan_getnextslot
DETAIL:  from localhost:xxxxx
 count
---------------------------------------------------------------------
     4
(1 row)

DROP TABLE test_partitioned;
\set VERBOSITY terse
ALTER EXTENSION citus DROP ACCESS METHOD fake_am;
NOTICE:  Citus does not propagate adding/dropping member objects
drop schema test_tableam cascade;
NOTICE:  drop cascades to 6 other objects
