1 /*
2  * This file and its contents are licensed under the Apache License 2.0.
3  * Please see the included NOTICE for copyright information and
4  * LICENSE-APACHE for a copy of the license.
5  */
6 #include <postgres.h>
7 #include <utils/guc.h>
8 #include <miscadmin.h>
9 
10 #include "guc.h"
11 #include "license_guc.h"
12 #include "config.h"
13 #include "hypertable_cache.h"
14 #include "telemetry/telemetry.h"
15 
16 typedef enum TelemetryLevel
17 {
18 	TELEMETRY_OFF,
19 	TELEMETRY_BASIC,
20 } TelemetryLevel;
21 
22 /* Define which level means on. We use this object to have at least one object
23  * of type TelemetryLevel in the code, otherwise pgindent won't work for the
24  * type */
25 static const TelemetryLevel on_level = TELEMETRY_BASIC;
26 
27 bool
ts_telemetry_on()28 ts_telemetry_on()
29 {
30 	return ts_guc_telemetry_level == on_level;
31 }
32 
33 static const struct config_enum_entry telemetry_level_options[] = {
34 	{ "off", TELEMETRY_OFF, false }, { "basic", TELEMETRY_BASIC, false }, { NULL, 0, false }
35 };
36 
37 static const struct config_enum_entry remote_data_fetchers[] = {
38 	{ "rowbyrow", RowByRowFetcherType, false },
39 	{ "cursor", CursorFetcherType, false },
40 	{ NULL, 0, false }
41 };
42 
43 bool ts_guc_enable_optimizations = true;
44 bool ts_guc_restoring = false;
45 bool ts_guc_enable_constraint_aware_append = true;
46 bool ts_guc_enable_ordered_append = true;
47 bool ts_guc_enable_chunk_append = true;
48 bool ts_guc_enable_parallel_chunk_append = true;
49 bool ts_guc_enable_runtime_exclusion = true;
50 bool ts_guc_enable_constraint_exclusion = true;
51 bool ts_guc_enable_qual_propagation = true;
52 bool ts_guc_enable_cagg_reorder_groupby = true;
53 TSDLLEXPORT bool ts_guc_enable_transparent_decompression = true;
54 bool ts_guc_enable_per_data_node_queries = true;
55 bool ts_guc_enable_async_append = true;
56 TSDLLEXPORT bool ts_guc_enable_skip_scan = true;
57 int ts_guc_max_open_chunks_per_insert = 10;
58 int ts_guc_max_cached_chunks_per_hypertable = 10;
59 int ts_guc_telemetry_level = TELEMETRY_DEFAULT;
60 
61 TSDLLEXPORT char *ts_guc_license = TS_LICENSE_DEFAULT;
62 char *ts_last_tune_time = NULL;
63 char *ts_last_tune_version = NULL;
64 char *ts_telemetry_cloud = NULL;
65 TSDLLEXPORT bool ts_guc_enable_2pc;
66 TSDLLEXPORT int ts_guc_max_insert_batch_size = 1000;
67 TSDLLEXPORT bool ts_guc_enable_connection_binary_data;
68 TSDLLEXPORT bool ts_guc_enable_client_ddl_on_data_nodes = false;
69 TSDLLEXPORT char *ts_guc_ssl_dir = NULL;
70 TSDLLEXPORT char *ts_guc_passfile = NULL;
71 TSDLLEXPORT bool ts_guc_enable_remote_explain = false;
72 TSDLLEXPORT DataFetcherType ts_guc_remote_data_fetcher = RowByRowFetcherType;
73 
74 #ifdef TS_DEBUG
75 bool ts_shutdown_bgw = false;
76 char *ts_current_timestamp_mock = "";
77 #endif
78 
79 static void
assign_max_cached_chunks_per_hypertable_hook(int newval,void * extra)80 assign_max_cached_chunks_per_hypertable_hook(int newval, void *extra)
81 {
82 	/* invalidate the hypertable cache to reset */
83 	ts_hypertable_cache_invalidate_callback();
84 }
85 
86 void
_guc_init(void)87 _guc_init(void)
88 {
89 	/* Main database to connect to. */
90 	DefineCustomBoolVariable("timescaledb.enable_optimizations",
91 							 "Enable TimescaleDB query optimizations",
92 							 NULL,
93 							 &ts_guc_enable_optimizations,
94 							 true,
95 							 PGC_USERSET,
96 							 0,
97 							 NULL,
98 							 NULL,
99 							 NULL);
100 
101 	DefineCustomBoolVariable("timescaledb.restoring",
102 							 "Install timescale in restoring mode",
103 							 "Used for running pg_restore",
104 							 &ts_guc_restoring,
105 							 false,
106 							 PGC_SUSET,
107 							 0,
108 							 NULL,
109 							 NULL,
110 							 NULL);
111 
112 	DefineCustomBoolVariable("timescaledb.enable_constraint_aware_append",
113 							 "Enable constraint-aware append scans",
114 							 "Enable constraint exclusion at execution time",
115 							 &ts_guc_enable_constraint_aware_append,
116 							 true,
117 							 PGC_USERSET,
118 							 0,
119 							 NULL,
120 							 NULL,
121 							 NULL);
122 
123 	DefineCustomBoolVariable("timescaledb.enable_ordered_append",
124 							 "Enable ordered append scans",
125 							 "Enable ordered append optimization for queries that are ordered by "
126 							 "the time dimension",
127 							 &ts_guc_enable_ordered_append,
128 							 true,
129 							 PGC_USERSET,
130 							 0,
131 							 NULL,
132 							 NULL,
133 							 NULL);
134 
135 	DefineCustomBoolVariable("timescaledb.enable_chunk_append",
136 							 "Enable chunk append node",
137 							 "Enable using chunk append node",
138 							 &ts_guc_enable_chunk_append,
139 							 true,
140 							 PGC_USERSET,
141 							 0,
142 							 NULL,
143 							 NULL,
144 							 NULL);
145 
146 	DefineCustomBoolVariable("timescaledb.enable_parallel_chunk_append",
147 							 "Enable parallel chunk append node",
148 							 "Enable using parallel aware chunk append node",
149 							 &ts_guc_enable_parallel_chunk_append,
150 							 true,
151 							 PGC_USERSET,
152 							 0,
153 							 NULL,
154 							 NULL,
155 							 NULL);
156 
157 	DefineCustomBoolVariable("timescaledb.enable_runtime_exclusion",
158 							 "Enable runtime chunk exclusion",
159 							 "Enable runtime chunk exclusion in ChunkAppend node",
160 							 &ts_guc_enable_runtime_exclusion,
161 							 true,
162 							 PGC_USERSET,
163 							 0,
164 							 NULL,
165 							 NULL,
166 							 NULL);
167 
168 	DefineCustomBoolVariable("timescaledb.enable_constraint_exclusion",
169 							 "Enable constraint exclusion",
170 							 "Enable planner constraint exclusion",
171 							 &ts_guc_enable_constraint_exclusion,
172 							 true,
173 							 PGC_USERSET,
174 							 0,
175 							 NULL,
176 							 NULL,
177 							 NULL);
178 
179 	DefineCustomBoolVariable("timescaledb.enable_qual_propagation",
180 							 "Enable qualifier propagation",
181 							 "Enable propagation of qualifiers in JOINs",
182 							 &ts_guc_enable_qual_propagation,
183 							 true,
184 							 PGC_USERSET,
185 							 0,
186 							 NULL,
187 							 NULL,
188 							 NULL);
189 
190 	DefineCustomBoolVariable("timescaledb.enable_transparent_decompression",
191 							 "Enable transparent decompression",
192 							 "Enable transparent decompression when querying hypertable",
193 							 &ts_guc_enable_transparent_decompression,
194 							 true,
195 							 PGC_USERSET,
196 							 0,
197 							 NULL,
198 							 NULL,
199 							 NULL);
200 
201 	DefineCustomBoolVariable("timescaledb.enable_skipscan",
202 							 "Enable SkipScan",
203 							 "Enable SkipScan for DISTINCT queries",
204 							 &ts_guc_enable_skip_scan,
205 							 true,
206 							 PGC_USERSET,
207 							 0,
208 							 NULL,
209 							 NULL,
210 							 NULL);
211 
212 	DefineCustomBoolVariable("timescaledb.enable_cagg_reorder_groupby",
213 							 "Enable group by reordering",
214 							 "Enable group by clause reordering for continuous aggregates",
215 							 &ts_guc_enable_cagg_reorder_groupby,
216 							 true,
217 							 PGC_USERSET,
218 							 0,
219 							 NULL,
220 							 NULL,
221 							 NULL);
222 
223 	DefineCustomBoolVariable("timescaledb.enable_2pc",
224 							 "Enable two-phase commit",
225 							 "Enable two-phase commit on distributed hypertables",
226 							 &ts_guc_enable_2pc,
227 							 true,
228 							 PGC_USERSET,
229 							 0,
230 							 NULL,
231 							 NULL,
232 							 NULL);
233 
234 	DefineCustomBoolVariable("timescaledb.enable_per_data_node_queries",
235 							 "Enable the per data node query optimization for hypertables",
236 							 "Enable the optimization that combines different chunks belonging to "
237 							 "the same hypertable into a single query per data_node",
238 							 &ts_guc_enable_per_data_node_queries,
239 							 true,
240 							 PGC_USERSET,
241 							 0,
242 							 NULL,
243 							 NULL,
244 							 NULL);
245 
246 	DefineCustomIntVariable("timescaledb.max_insert_batch_size",
247 							"The max number of tuples to batch before sending to a data node",
248 							"When acting as a access node, TimescaleDB splits batches of "
249 							"inserted tuples across multiple data nodes. It will batch up to the "
250 							"configured batch size tuples per data node before flushing. "
251 							"Setting this to 0 disables batching, reverting to tuple-by-tuple "
252 							"inserts",
253 							&ts_guc_max_insert_batch_size,
254 							1000,
255 							0,
256 							65536,
257 							PGC_USERSET,
258 							0,
259 							NULL,
260 							NULL,
261 							NULL);
262 
263 	DefineCustomBoolVariable("timescaledb.enable_connection_binary_data",
264 							 "Enable binary format for connection",
265 							 "Enable binary format for data exchanged between nodes in the cluster",
266 							 &ts_guc_enable_connection_binary_data,
267 							 true,
268 							 PGC_USERSET,
269 							 0,
270 							 NULL,
271 							 NULL,
272 							 NULL);
273 
274 	DefineCustomBoolVariable("timescaledb.enable_client_ddl_on_data_nodes",
275 							 "Enable DDL operations on data nodes by a client",
276 							 "Do not restrict execution of DDL operations only by access node",
277 							 &ts_guc_enable_client_ddl_on_data_nodes,
278 							 false,
279 							 PGC_USERSET,
280 							 0,
281 							 NULL,
282 							 NULL,
283 							 NULL);
284 
285 	DefineCustomBoolVariable("timescaledb.enable_async_append",
286 							 "Enable async query execution on data nodes",
287 							 "Enable optimization that runs remote queries asynchronously"
288 							 "across data nodes",
289 							 &ts_guc_enable_async_append,
290 							 true,
291 							 PGC_USERSET,
292 							 0,
293 							 NULL,
294 							 NULL,
295 							 NULL);
296 
297 	DefineCustomBoolVariable("timescaledb.enable_remote_explain",
298 							 "Show explain from remote nodes when using VERBOSE flag",
299 							 "Enable getting and showing EXPLAIN output from remote nodes",
300 							 &ts_guc_enable_remote_explain,
301 							 false,
302 							 PGC_USERSET,
303 							 0,
304 							 NULL,
305 							 NULL,
306 							 NULL);
307 
308 	DefineCustomEnumVariable("timescaledb.remote_data_fetcher",
309 							 "Set remote data fetcher type",
310 							 "Pick data fetcher type based on type of queries you plan to run "
311 							 "(rowbyrow or cursor)",
312 							 (int *) &ts_guc_remote_data_fetcher,
313 							 CursorFetcherType,
314 							 remote_data_fetchers,
315 							 PGC_USERSET,
316 							 0,
317 							 NULL,
318 							 NULL,
319 							 NULL);
320 
321 	DefineCustomStringVariable("timescaledb.ssl_dir",
322 							   "TimescaleDB user certificate directory",
323 							   "Determines a path which is used to search user certificates and "
324 							   "private keys",
325 							   &ts_guc_ssl_dir,
326 							   NULL,
327 							   PGC_SIGHUP,
328 							   0,
329 							   NULL,
330 							   NULL,
331 							   NULL);
332 
333 	DefineCustomStringVariable("timescaledb.passfile",
334 							   "TimescaleDB password file path",
335 							   "Specifies the name of the file used to store passwords used for "
336 							   "data node connections",
337 							   &ts_guc_passfile,
338 							   NULL,
339 							   PGC_SIGHUP,
340 							   0,
341 							   NULL,
342 							   NULL,
343 							   NULL);
344 
345 	DefineCustomIntVariable("timescaledb.max_open_chunks_per_insert",
346 							"Maximum open chunks per insert",
347 							"Maximum number of open chunk tables per insert",
348 							&ts_guc_max_open_chunks_per_insert,
349 							Min(work_mem * INT64CONST(1024) / INT64CONST(25000),
350 								PG_INT16_MAX), /* Measurements via
351 												* `MemoryContextStats(TopMemoryContext)`
352 												* show chunk insert
353 												* state memory context
354 												* takes up ~25K bytes
355 												* (work_mem is in
356 												* kbytes) */
357 							0,
358 							PG_INT16_MAX,
359 							PGC_USERSET,
360 							0,
361 							NULL,
362 							NULL,
363 							NULL);
364 
365 	DefineCustomIntVariable("timescaledb.max_cached_chunks_per_hypertable",
366 							"Maximum cached chunks",
367 							"Maximum number of chunks stored in the cache",
368 							&ts_guc_max_cached_chunks_per_hypertable,
369 							100,
370 							0,
371 							65536,
372 							PGC_USERSET,
373 							0,
374 							NULL,
375 							assign_max_cached_chunks_per_hypertable_hook,
376 							NULL);
377 	DefineCustomEnumVariable("timescaledb.telemetry_level",
378 							 "Telemetry settings level",
379 							 "Level used to determine which telemetry to send",
380 							 &ts_guc_telemetry_level,
381 							 TELEMETRY_DEFAULT,
382 							 telemetry_level_options,
383 							 PGC_USERSET,
384 							 0,
385 							 NULL,
386 							 NULL,
387 							 NULL);
388 
389 	DefineCustomStringVariable(/* name= */ "timescaledb.license",
390 							   /* short_dec= */ "TimescaleDB license type",
391 							   /* long_dec= */ "Determines which features are enabled",
392 							   /* valueAddr= */ &ts_guc_license,
393 							   /* bootValue= */ TS_LICENSE_DEFAULT,
394 							   /* context= */ PGC_SUSET,
395 							   /* flags= */ 0,
396 							   /* check_hook= */ ts_license_guc_check_hook,
397 							   /* assign_hook= */ ts_license_guc_assign_hook,
398 							   /* show_hook= */ NULL);
399 
400 	DefineCustomStringVariable(/* name= */ "timescaledb.last_tuned",
401 							   /* short_dec= */ "last tune run",
402 							   /* long_dec= */ "records last time timescaledb-tune ran",
403 							   /* valueAddr= */ &ts_last_tune_time,
404 							   /* bootValue= */ NULL,
405 							   /* context= */ PGC_SIGHUP,
406 							   /* flags= */ 0,
407 							   /* check_hook= */ NULL,
408 							   /* assign_hook= */ NULL,
409 							   /* show_hook= */ NULL);
410 
411 	DefineCustomStringVariable(/* name= */ "timescaledb.last_tuned_version",
412 							   /* short_dec= */ "version of timescaledb-tune",
413 							   /* long_dec= */ "version of timescaledb-tune used to tune",
414 							   /* valueAddr= */ &ts_last_tune_version,
415 							   /* bootValue= */ NULL,
416 							   /* context= */ PGC_SIGHUP,
417 							   /* flags= */ 0,
418 							   /* check_hook= */ NULL,
419 							   /* assign_hook= */ NULL,
420 							   /* show_hook= */ NULL);
421 
422 	DefineCustomStringVariable(/* name= */ "timescaledb_telemetry.cloud",
423 							   /* short_dec= */ "cloud provider",
424 							   /* long_dec= */ "cloud provider used for this instance",
425 							   /* valueAddr= */ &ts_telemetry_cloud,
426 							   /* bootValue= */ NULL,
427 							   /* context= */ PGC_SIGHUP,
428 							   /* flags= */ 0,
429 							   /* check_hook= */ NULL,
430 							   /* assign_hook= */ NULL,
431 							   /* show_hook= */ NULL);
432 
433 #ifdef TS_DEBUG
434 	DefineCustomBoolVariable(/* name= */ "timescaledb.shutdown_bgw_scheduler",
435 							 /* short_dec= */ "immediately shutdown the bgw scheduler",
436 							 /* long_dec= */ "this is for debugging purposes",
437 							 /* valueAddr= */ &ts_shutdown_bgw,
438 							 /* bootValue= */ false,
439 							 /* context= */ PGC_SIGHUP,
440 							 /* flags= */ 0,
441 							 /* check_hook= */ NULL,
442 							 /* assign_hook= */ NULL,
443 							 /* show_hook= */ NULL);
444 
445 	DefineCustomStringVariable(/* name= */ "timescaledb.current_timestamp_mock",
446 							   /* short_dec= */ "set the current timestamp",
447 							   /* long_dec= */ "this is for debugging purposes",
448 							   /* valueAddr= */ &ts_current_timestamp_mock,
449 							   /* bootValue= */ NULL,
450 							   /* context= */ PGC_USERSET,
451 							   /* flags= */ 0,
452 							   /* check_hook= */ NULL,
453 							   /* assign_hook= */ NULL,
454 							   /* show_hook= */ NULL);
455 #endif
456 }
457 
458 void
_guc_fini(void)459 _guc_fini(void)
460 {
461 }
462