1 /*
2  * This file and its contents are licensed under the Timescale License.
3  * Please see the included NOTICE for copyright information and
4  * LICENSE-TIMESCALE for a copy of the license.
5  */
6 
7 #include <postgres.h>
8 #include <fmgr.h>
9 
10 #include <export.h>
11 #include <remote/dist_commands.h>
12 #include <data_node.h>
13 #include <test_utils.h>
14 
15 TS_FUNCTION_INFO_V1(ts_invoke_distributed_commands);
16 TS_FUNCTION_INFO_V1(ts_invoke_faulty_distributed_command);
17 
18 #define LOG_PG_STATUS(RESULT, TARGET)                                                              \
19 	elog(INFO,                                                                                     \
20 		 "%s result: %s",                                                                          \
21 		 TARGET,                                                                                   \
22 		 PQresStatus(PQresultStatus(ts_dist_cmd_get_result_by_node_name(RESULT, TARGET))));
23 
24 Datum
ts_invoke_distributed_commands(PG_FUNCTION_ARGS)25 ts_invoke_distributed_commands(PG_FUNCTION_ARGS)
26 {
27 	List *data_nodes = data_node_get_node_name_list_with_aclcheck(ACL_USAGE, true);
28 	List *subset_nodes;
29 	DistCmdResult *results;
30 	PreparedDistCmd *prepped_cmd;
31 	const char *test_args[3] = { "1976-09-18 00:00:00-07", "47", "103.4" };
32 	ListCell *lc;
33 
34 	if (data_nodes == NIL)
35 		elog(ERROR, "no data nodes specified");
36 
37 	results = ts_dist_cmd_invoke_on_all_data_nodes(
38 		"CREATE TABLE public.disttable1(time timestamptz, device int, temp float);");
39 
40 	foreach (lc, data_nodes)
41 	{
42 		const char *node = lfirst(lc);
43 
44 		LOG_PG_STATUS(results, node);
45 	}
46 
47 	ts_dist_cmd_close_response(results);
48 
49 	/* Invoke on subset of nodes */
50 	subset_nodes = list_copy(data_nodes);
51 	subset_nodes = list_truncate(subset_nodes, list_length(data_nodes) - 1);
52 
53 	if (list_length(subset_nodes) == 0)
54 		elog(ERROR, "Too few nodes to execute test");
55 
56 	results = ts_dist_cmd_invoke_on_data_nodes("CREATE TABLE public.disttable2(time timestamptz, "
57 											   "device int, temp float);",
58 											   subset_nodes,
59 											   true);
60 	TestAssertTrue(ts_dist_cmd_get_result_by_node_name(results, llast(data_nodes)) == NULL);
61 
62 	foreach (lc, subset_nodes)
63 	{
64 		const char *node = lfirst(lc);
65 
66 		LOG_PG_STATUS(results, node);
67 	}
68 
69 	ts_dist_cmd_close_response(results);
70 
71 	prepped_cmd = ts_dist_cmd_prepare_command("INSERT INTO public.disttable1 VALUES ($1, $2, $3)",
72 											  3,
73 											  subset_nodes);
74 	results = ts_dist_cmd_invoke_prepared_command(prepped_cmd, test_args);
75 
76 	foreach (lc, subset_nodes)
77 	{
78 		const char *node = lfirst(lc);
79 
80 		LOG_PG_STATUS(results, node);
81 	}
82 
83 	ts_dist_cmd_close_prepared_command(prepped_cmd);
84 
85 	PG_RETURN_VOID();
86 }
87 
88 Datum
ts_invoke_faulty_distributed_command(PG_FUNCTION_ARGS)89 ts_invoke_faulty_distributed_command(PG_FUNCTION_ARGS)
90 {
91 	ts_dist_cmd_invoke_on_all_data_nodes(
92 		"INSERT INTO public.disttable2 VALUES (CURRENT_TIMESTAMP, 42, 72.5);");
93 	PG_RETURN_VOID();
94 }
95