PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
variables.c File Reference
#include "postgres_fe.h"
#include <math.h>
#include "common.h"
#include "common/logging.h"
#include "variables.h"
Include dependency graph for variables.c:

Go to the source code of this file.

Functions

static bool valid_variable_name (const char *name)
 
VariableSpace CreateVariableSpace (void)
 
const char * GetVariable (VariableSpace space, const char *name)
 
bool ParseVariableBool (const char *value, const char *name, bool *result)
 
bool ParseVariableNum (const char *value, const char *name, int *result)
 
bool ParseVariableDouble (const char *value, const char *name, double *result, double min, double max)
 
void PrintVariables (VariableSpace space)
 
bool SetVariable (VariableSpace space, const char *name, const char *value)
 
void SetVariableHooks (VariableSpace space, const char *name, VariableSubstituteHook shook, VariableAssignHook ahook)
 
bool VariableHasHook (VariableSpace space, const char *name)
 
bool SetVariableBool (VariableSpace space, const char *name)
 
bool DeleteVariable (VariableSpace space, const char *name)
 
void PsqlVarEnumError (const char *name, const char *value, const char *suggestions)
 

Function Documentation

◆ CreateVariableSpace()

VariableSpace CreateVariableSpace ( void  )

Definition at line 53 of file variables.c.

54{
55 struct _variable *ptr;
56
57 ptr = pg_malloc(sizeof *ptr);
58 ptr->name = NULL;
59 ptr->value = NULL;
60 ptr->substitute_hook = NULL;
61 ptr->assign_hook = NULL;
62 ptr->next = NULL;
63
64 return ptr;
65}
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
VariableSubstituteHook substitute_hook
Definition: variables.h:66
VariableAssignHook assign_hook
Definition: variables.h:67
struct _variable * next
Definition: variables.h:68
char * name
Definition: variables.h:64
char * value
Definition: variables.h:65

References _variable::assign_hook, _variable::name, _variable::next, pg_malloc(), _variable::substitute_hook, and _variable::value.

Referenced by EstablishVariableSpace().

◆ DeleteVariable()

bool DeleteVariable ( VariableSpace  space,
const char *  name 
)

Definition at line 474 of file variables.c.

475{
476 return SetVariable(space, name, NULL);
477}
bool SetVariable(VariableSpace space, const char *name, const char *value)
Definition: variables.c:281
const char * name

References name, and SetVariable().

Referenced by parse_psql_options().

◆ GetVariable()

const char * GetVariable ( VariableSpace  space,
const char *  name 
)

Definition at line 73 of file variables.c.

74{
75 struct _variable *current;
76
77 if (!space)
78 return NULL;
79
80 for (current = space->next; current; current = current->next)
81 {
82 int cmp = strcmp(current->name, name);
83
84 if (cmp == 0)
85 {
86 /* this is correct answer when value is NULL, too */
87 return current->value;
88 }
89 if (cmp > 0)
90 break; /* it's not there */
91 }
92
93 return NULL;
94}
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743

References cmp(), name, _variable::name, _variable::next, and _variable::value.

Referenced by get_prompt(), initializeInput(), and psql_get_variable().

◆ ParseVariableBool()

bool ParseVariableBool ( const char *  value,
const char *  name,
bool *  result 
)

Definition at line 109 of file variables.c.

110{
111 size_t len;
112 bool valid = true;
113
114 /* Treat "unset" as an empty string, which will lead to error below */
115 if (value == NULL)
116 value = "";
117
118 len = strlen(value);
119
120 if (len > 0 && pg_strncasecmp(value, "true", len) == 0)
121 *result = true;
122 else if (len > 0 && pg_strncasecmp(value, "false", len) == 0)
123 *result = false;
124 else if (len > 0 && pg_strncasecmp(value, "yes", len) == 0)
125 *result = true;
126 else if (len > 0 && pg_strncasecmp(value, "no", len) == 0)
127 *result = false;
128 /* 'o' is not unique enough */
129 else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
130 *result = true;
131 else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
132 *result = false;
133 else if (pg_strcasecmp(value, "1") == 0)
134 *result = true;
135 else if (pg_strcasecmp(value, "0") == 0)
136 *result = false;
137 else
138 {
139 /* string is not recognized; don't clobber *result */
140 if (name)
141 pg_log_error("unrecognized value \"%s\" for \"%s\": Boolean expected",
142 value, name);
143 valid = false;
144 }
145 return valid;
146}
static struct @165 value
#define pg_log_error(...)
Definition: logging.h:106
const void size_t len
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69

References len, name, pg_log_error, pg_strcasecmp(), pg_strncasecmp(), and value.

Referenced by autocommit_hook(), do_pset(), echo_hidden_hook(), exec_command_connect(), exec_command_timing(), hide_compression_hook(), hide_tableam_hook(), is_true_boolean_expression(), on_error_rollback_hook(), on_error_stop_hook(), quiet_hook(), show_all_results_hook(), singleline_hook(), and singlestep_hook().

◆ ParseVariableDouble()

bool ParseVariableDouble ( const char *  value,
const char *  name,
double *  result,
double  min,
double  max 
)

Definition at line 195 of file variables.c.

196{
197 char *end;
198 double dblval;
199
200 /*
201 * Empty-string input has historically been treated differently by strtod
202 * on various platforms, so handle that by specifically checking for it.
203 */
204 if ((value == NULL) || (*value == '\0'))
205 {
206 if (name)
207 pg_log_error("invalid input syntax for \"%s\"", name);
208 return false;
209 }
210
211 errno = 0;
212 dblval = strtod(value, &end);
213 if (errno == 0 && *end == '\0' && end != value)
214 {
215 if (dblval < min)
216 {
217 if (name)
218 pg_log_error("invalid value \"%s\" for \"%s\": must be greater than %.2f",
219 value, name, min);
220 return false;
221 }
222 else if (dblval > max)
223 {
224 if (name)
225 pg_log_error("invalid value \"%s\" for \"%s\": must be less than %.2f",
226 value, name, max);
227 }
228 *result = dblval;
229 return true;
230 }
231
232 /*
233 * Cater for platforms which treat values which aren't zero, but that are
234 * too close to zero to have full precision, by checking for zero or real
235 * out-of-range values.
236 */
237 else if ((errno == ERANGE) &&
238 (dblval == 0.0 || dblval >= HUGE_VAL || dblval <= -HUGE_VAL))
239 {
240 if (name)
241 pg_log_error("\"%s\" is out of range for \"%s\"", value, name);
242 return false;
243 }
244 else
245 {
246 if (name)
247 pg_log_error("invalid value \"%s\" for \"%s\"", value, name);
248 return false;
249 }
250}

References name, pg_log_error, and value.

Referenced by watch_interval_hook().

◆ ParseVariableNum()

bool ParseVariableNum ( const char *  value,
const char *  name,
int *  result 
)

Definition at line 158 of file variables.c.

159{
160 char *end;
161 long numval;
162
163 /* Treat "unset" as an empty string, which will lead to error below */
164 if (value == NULL)
165 value = "";
166
167 errno = 0;
168 numval = strtol(value, &end, 0);
169 if (errno == 0 && *end == '\0' && end != value && numval == (int) numval)
170 {
171 *result = (int) numval;
172 return true;
173 }
174 else
175 {
176 /* string is not recognized; don't clobber *result */
177 if (name)
178 pg_log_error("invalid value \"%s\" for \"%s\": integer expected",
179 value, name);
180 return false;
181 }
182}

References name, pg_log_error, and value.

Referenced by do_pset(), fetch_count_hook(), histsize_hook(), ignoreeof_hook(), and ignoreeof_substitute_hook().

◆ PrintVariables()

void PrintVariables ( VariableSpace  space)

Definition at line 256 of file variables.c.

257{
258 struct _variable *ptr;
259
260 if (!space)
261 return;
262
263 for (ptr = space->next; ptr; ptr = ptr->next)
264 {
265 if (ptr->value)
266 printf("%s = '%s'\n", ptr->name, ptr->value);
267 if (cancel_pressed)
268 break;
269 }
270}
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
#define printf(...)
Definition: port.h:245

References cancel_pressed, _variable::name, _variable::next, printf, and _variable::value.

Referenced by exec_command_set().

◆ PsqlVarEnumError()

void PsqlVarEnumError ( const char *  name,
const char *  value,
const char *  suggestions 
)

Definition at line 486 of file variables.c.

487{
488 pg_log_error("unrecognized value \"%s\" for \"%s\"\n"
489 "Available values are: %s.",
490 value, name, suggestions);
491}

References name, pg_log_error, and value.

Referenced by comp_keyword_case_hook(), do_pset(), echo_hidden_hook(), echo_hook(), histcontrol_hook(), on_error_rollback_hook(), show_context_hook(), and verbosity_hook().

◆ SetVariable()

bool SetVariable ( VariableSpace  space,
const char *  name,
const char *  value 
)

Definition at line 281 of file variables.c.

282{
283 struct _variable *current,
284 *previous;
285
286 if (!space || !name)
287 return false;
288
290 {
291 /* Deletion of non-existent variable is not an error */
292 if (!value)
293 return true;
294 pg_log_error("invalid variable name: \"%s\"", name);
295 return false;
296 }
297
298 for (previous = space, current = space->next;
299 current;
300 previous = current, current = current->next)
301 {
302 int cmp = strcmp(current->name, name);
303
304 if (cmp == 0)
305 {
306 /*
307 * Found entry, so update, unless assign hook returns false.
308 *
309 * We must duplicate the passed value to start with. This
310 * simplifies the API for substitute hooks. Moreover, some assign
311 * hooks assume that the passed value has the same lifespan as the
312 * variable. Having to free the string again on failure is a
313 * small price to pay for keeping these APIs simple.
314 */
315 char *new_value = value ? pg_strdup(value) : NULL;
316 bool confirmed;
317
318 if (current->substitute_hook)
319 new_value = current->substitute_hook(new_value);
320
321 if (current->assign_hook)
322 confirmed = current->assign_hook(new_value);
323 else
324 confirmed = true;
325
326 if (confirmed)
327 {
328 pg_free(current->value);
329 current->value = new_value;
330
331 /*
332 * If we deleted the value, and there are no hooks to
333 * remember, we can discard the variable altogether.
334 */
335 if (new_value == NULL &&
336 current->substitute_hook == NULL &&
337 current->assign_hook == NULL)
338 {
339 previous->next = current->next;
340 free(current->name);
341 free(current);
342 }
343 }
344 else
345 pg_free(new_value); /* current->value is left unchanged */
346
347 return confirmed;
348 }
349 if (cmp > 0)
350 break; /* it's not there */
351 }
352
353 /* not present, make new entry ... unless we were asked to delete */
354 if (value)
355 {
356 current = pg_malloc(sizeof *current);
357 current->name = pg_strdup(name);
358 current->value = pg_strdup(value);
359 current->substitute_hook = NULL;
360 current->assign_hook = NULL;
361 current->next = previous->next;
362 previous->next = current;
363 }
364 return true;
365}
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define free(a)
Definition: header.h:65
static bool valid_variable_name(const char *name)
Definition: variables.c:24

References _variable::assign_hook, cmp(), free, name, _variable::name, _variable::next, pg_free(), pg_log_error, pg_malloc(), pg_strdup(), _variable::substitute_hook, valid_variable_name(), _variable::value, and value.

Referenced by DeleteVariable(), do_lo_import(), exec_command_encoding(), exec_command_getenv(), exec_command_prompt(), exec_command_set(), exec_command_unset(), ExecQueryAndProcessResults(), main(), parse_psql_options(), PrintQueryStatus(), SendQuery(), SetPipelineVariables(), SetResultVariables(), SetShellResultVariables(), SetVariableBool(), StoreQueryTuple(), SyncVariables(), and UnsyncVariables().

◆ SetVariableBool()

bool SetVariableBool ( VariableSpace  space,
const char *  name 
)

Definition at line 462 of file variables.c.

463{
464 return SetVariable(space, name, "on");
465}

References name, and SetVariable().

Referenced by main(), and parse_psql_options().

◆ SetVariableHooks()

void SetVariableHooks ( VariableSpace  space,
const char *  name,
VariableSubstituteHook  shook,
VariableAssignHook  ahook 
)

Definition at line 384 of file variables.c.

387{
388 struct _variable *current,
389 *previous;
390
391 if (!space || !name)
392 return;
393
395 return;
396
397 for (previous = space, current = space->next;
398 current;
399 previous = current, current = current->next)
400 {
401 int cmp = strcmp(current->name, name);
402
403 if (cmp == 0)
404 {
405 /* found entry, so update */
406 current->substitute_hook = shook;
407 current->assign_hook = ahook;
408 if (shook)
409 current->value = (*shook) (current->value);
410 if (ahook)
411 (void) (*ahook) (current->value);
412 return;
413 }
414 if (cmp > 0)
415 break; /* it's not there */
416 }
417
418 /* not present, make new entry */
419 current = pg_malloc(sizeof *current);
420 current->name = pg_strdup(name);
421 current->value = NULL;
422 current->substitute_hook = shook;
423 current->assign_hook = ahook;
424 current->next = previous->next;
425 previous->next = current;
426 if (shook)
427 current->value = (*shook) (current->value);
428 if (ahook)
429 (void) (*ahook) (current->value);
430}

References _variable::assign_hook, cmp(), name, _variable::name, _variable::next, pg_malloc(), pg_strdup(), _variable::substitute_hook, valid_variable_name(), and _variable::value.

Referenced by EstablishVariableSpace().

◆ valid_variable_name()

static bool valid_variable_name ( const char *  name)
static

Definition at line 24 of file variables.c.

25{
26 const unsigned char *ptr = (const unsigned char *) name;
27
28 /* Mustn't be zero-length */
29 if (*ptr == '\0')
30 return false;
31
32 while (*ptr)
33 {
34 if (IS_HIGHBIT_SET(*ptr) ||
35 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
36 "_0123456789", *ptr) != NULL)
37 ptr++;
38 else
39 return false;
40 }
41
42 return true;
43}
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1126

References IS_HIGHBIT_SET, and name.

Referenced by SetVariable(), and SetVariableHooks().

◆ VariableHasHook()

bool VariableHasHook ( VariableSpace  space,
const char *  name 
)

Definition at line 437 of file variables.c.

438{
439 struct _variable *current;
440
441 Assert(space);
442 Assert(name);
443
444 for (current = space->next; current; current = current->next)
445 {
446 int cmp = strcmp(current->name, name);
447
448 if (cmp == 0)
449 return (current->substitute_hook != NULL ||
450 current->assign_hook != NULL);
451 if (cmp > 0)
452 break; /* it's not there */
453 }
454
455 return false;
456}
Assert(PointerIsAligned(start, uint64))

References Assert(), _variable::assign_hook, cmp(), name, _variable::name, _variable::next, and _variable::substitute_hook.

Referenced by StoreQueryTuple().