Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * syncrep_gram.y - Parser for synchronous_standby_names
5 : *
6 : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/replication/syncrep_gram.y
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "nodes/pg_list.h"
18 : #include "replication/syncrep.h"
19 :
20 : #include "syncrep_gram.h"
21 :
22 : static SyncRepConfigData *create_syncrep_config(const char *num_sync,
23 : List *members, uint8 syncrep_method);
24 :
25 : /*
26 : * Bison doesn't allocate anything that needs to live across parser calls,
27 : * so we can easily have it use palloc instead of malloc. This prevents
28 : * memory leaks if we error out during parsing.
29 : */
30 : #define YYMALLOC palloc
31 : #define YYFREE pfree
32 :
33 : %}
34 :
35 : %parse-param {SyncRepConfigData **syncrep_parse_result_p}
36 : %parse-param {char **syncrep_parse_error_msg_p}
37 : %parse-param {yyscan_t yyscanner}
38 : %lex-param {char **syncrep_parse_error_msg_p}
39 : %lex-param {yyscan_t yyscanner}
40 : %pure-parser
41 : %expect 0
42 : %name-prefix="syncrep_yy"
43 :
44 : %union
45 : {
46 : char *str;
47 : List *list;
48 : SyncRepConfigData *config;
49 : }
50 :
51 : %token <str> NAME NUM JUNK ANY FIRST
52 :
53 : %type <config> result standby_config
54 : %type <list> standby_list
55 : %type <str> standby_name
56 :
57 : %start result
58 :
59 : %%
60 : result:
61 : standby_config {
62 76 : *syncrep_parse_result_p = $1;
63 : (void) yynerrs; /* suppress compiler warning */
64 : }
65 : ;
66 :
67 : standby_config:
68 58 : standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_PRIORITY); }
69 12 : | NUM '(' standby_list ')' { $$ = create_syncrep_config($1, $3, SYNC_REP_PRIORITY); }
70 4 : | ANY NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_QUORUM); }
71 2 : | FIRST NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_PRIORITY); }
72 : ;
73 :
74 : standby_list:
75 76 : standby_name { $$ = list_make1($1); }
76 30 : | standby_list ',' standby_name { $$ = lappend($1, $3); }
77 : ;
78 :
79 : standby_name:
80 106 : NAME { $$ = $1; }
81 0 : | NUM { $$ = $1; }
82 : ;
83 : %%
84 :
85 : static SyncRepConfigData *
86 76 : create_syncrep_config(const char *num_sync, List *members, uint8 syncrep_method)
87 : {
88 : SyncRepConfigData *config;
89 : int size;
90 : ListCell *lc;
91 : char *ptr;
92 :
93 : /* Compute space needed for flat representation */
94 76 : size = offsetof(SyncRepConfigData, member_names);
95 182 : foreach(lc, members)
96 : {
97 106 : char *standby_name = (char *) lfirst(lc);
98 :
99 106 : size += strlen(standby_name) + 1;
100 : }
101 :
102 : /* And transform the data into flat representation */
103 76 : config = (SyncRepConfigData *) palloc(size);
104 :
105 76 : config->config_size = size;
106 76 : config->num_sync = atoi(num_sync);
107 76 : config->syncrep_method = syncrep_method;
108 76 : config->nmembers = list_length(members);
109 76 : ptr = config->member_names;
110 182 : foreach(lc, members)
111 : {
112 106 : char *standby_name = (char *) lfirst(lc);
113 :
114 106 : strcpy(ptr, standby_name);
115 106 : ptr += strlen(standby_name) + 1;
116 : }
117 :
118 76 : return config;
119 : }
|