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