Line data Source code
1 : %{ 2 : /*------------------------------------------------------------------------- 3 : * 4 : * syncrep_gram.y - Parser for synchronous_standby_names 5 : * 6 : * Portions Copyright (c) 1996-2025, 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 136 : *syncrep_parse_result_p = $1; 63 : (void) yynerrs; /* suppress compiler warning */ 64 : } 65 : ; 66 : 67 : standby_config: 68 100 : standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_PRIORITY); } 69 24 : | NUM '(' standby_list ')' { $$ = create_syncrep_config($1, $3, SYNC_REP_PRIORITY); } 70 8 : | ANY NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_QUORUM); } 71 4 : | FIRST NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_PRIORITY); } 72 : ; 73 : 74 : standby_list: 75 136 : standby_name { $$ = list_make1($1); } 76 60 : | standby_list ',' standby_name { $$ = lappend($1, $3); } 77 : ; 78 : 79 : standby_name: 80 196 : NAME { $$ = $1; } 81 0 : | NUM { $$ = $1; } 82 : ; 83 : %% 84 : 85 : static SyncRepConfigData * 86 136 : 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 136 : size = offsetof(SyncRepConfigData, member_names); 95 332 : foreach(lc, members) 96 : { 97 196 : char *standby_name = (char *) lfirst(lc); 98 : 99 196 : size += strlen(standby_name) + 1; 100 : } 101 : 102 : /* And transform the data into flat representation */ 103 136 : config = (SyncRepConfigData *) palloc(size); 104 : 105 136 : config->config_size = size; 106 136 : config->num_sync = atoi(num_sync); 107 136 : config->syncrep_method = syncrep_method; 108 136 : config->nmembers = list_length(members); 109 136 : ptr = config->member_names; 110 332 : foreach(lc, members) 111 : { 112 196 : char *standby_name = (char *) lfirst(lc); 113 : 114 196 : strcpy(ptr, standby_name); 115 196 : ptr += strlen(standby_name) + 1; 116 : } 117 : 118 136 : return config; 119 : }