Age Owner TLA Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * syncrep_gram.y - Parser for synchronous_standby_names
5 : *
6 : * Portions Copyright (c) 1996-2023, 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 : /* Result of parsing is returned in one of these two variables */
21 : SyncRepConfigData *syncrep_parse_result;
22 : char *syncrep_parse_error_msg;
23 :
24 : static SyncRepConfigData *create_syncrep_config(const char *num_sync,
25 : List *members, uint8 syncrep_method);
26 :
27 : /*
28 : * Bison doesn't allocate anything that needs to live across parser calls,
29 : * so we can easily have it use palloc instead of malloc. This prevents
30 : * memory leaks if we error out during parsing.
31 : */
32 : #define YYMALLOC palloc
33 : #define YYFREE pfree
34 :
35 : %}
36 :
37 : %expect 0
38 : %name-prefix="syncrep_yy"
39 :
40 : %union
41 : {
42 : char *str;
43 : List *list;
44 : SyncRepConfigData *config;
45 : }
46 :
47 : %token <str> NAME NUM JUNK ANY FIRST
48 :
49 : %type <config> result standby_config
50 : %type <list> standby_list
51 : %type <str> standby_name
52 :
53 : %start result
54 :
2559 fujii 55 ECB : %%
56 : result:
2559 fujii 57 GIC 67 : standby_config { syncrep_parse_result = $1; }
58 : ;
2538 tgl 59 ECB :
2559 fujii 60 : standby_config:
2302 fujii 61 CBC 49 : standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_PRIORITY); }
62 12 : | NUM '(' standby_list ')' { $$ = create_syncrep_config($1, $3, SYNC_REP_PRIORITY); }
2302 fujii 63 GIC 4 : | ANY NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_QUORUM); }
64 2 : | FIRST NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_PRIORITY); }
65 : ;
2538 tgl 66 ECB :
2559 fujii 67 : standby_list:
2538 tgl 68 GIC 67 : standby_name { $$ = list_make1($1); }
69 30 : | standby_list ',' standby_name { $$ = lappend($1, $3); }
70 : ;
2538 tgl 71 ECB :
2559 fujii 72 EUB : standby_name:
2538 tgl 73 GIC 97 : NAME { $$ = $1; }
2538 tgl 74 UIC 0 : | NUM { $$ = $1; }
75 : ;
76 : %%
2559 fujii 77 ECB :
78 : static SyncRepConfigData *
2302 fujii 79 GIC 67 : create_syncrep_config(const char *num_sync, List *members, uint8 syncrep_method)
80 : {
81 : SyncRepConfigData *config;
82 : int size;
83 : ListCell *lc;
84 : char *ptr;
2559 fujii 85 ECB :
2538 tgl 86 : /* Compute space needed for flat representation */
2538 tgl 87 GIC 67 : size = offsetof(SyncRepConfigData, member_names);
2538 tgl 88 CBC 164 : foreach(lc, members)
89 : {
90 97 : char *standby_name = (char *) lfirst(lc);
91 :
2538 tgl 92 GIC 97 : size += strlen(standby_name) + 1;
93 : }
2538 tgl 94 ECB :
95 : /* And transform the data into flat representation */
2538 tgl 96 CBC 67 : config = (SyncRepConfigData *) palloc(size);
2538 tgl 97 ECB :
2538 tgl 98 CBC 67 : config->config_size = size;
2559 fujii 99 67 : config->num_sync = atoi(num_sync);
2302 100 67 : config->syncrep_method = syncrep_method;
2538 tgl 101 67 : config->nmembers = list_length(members);
2538 tgl 102 GIC 67 : ptr = config->member_names;
2538 tgl 103 CBC 164 : foreach(lc, members)
104 : {
105 97 : char *standby_name = (char *) lfirst(lc);
2538 tgl 106 ECB :
2538 tgl 107 GIC 97 : strcpy(ptr, standby_name);
108 97 : ptr += strlen(standby_name) + 1;
2538 tgl 109 ECB : }
110 :
2559 fujii 111 GIC 67 : return config;
112 : }
|