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