Line data Source code
1 : %{ 2 : /*------------------------------------------------------------------------- 3 : * 4 : * syncrep_gram.y - Parser for synchronous_standby_names 5 : * 6 : * Portions Copyright (c) 1996-2024, 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 : /* silence -Wmissing-variable-declarations */ 28 : extern int syncrep_yychar; 29 : extern int syncrep_yynerrs; 30 : 31 : /* 32 : * Bison doesn't allocate anything that needs to live across parser calls, 33 : * so we can easily have it use palloc instead of malloc. This prevents 34 : * memory leaks if we error out during parsing. 35 : */ 36 : #define YYMALLOC palloc 37 : #define YYFREE pfree 38 : 39 : %} 40 : 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 130 : standby_config { syncrep_parse_result = $1; } 62 : ; 63 : 64 : standby_config: 65 94 : standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_PRIORITY); } 66 24 : | NUM '(' standby_list ')' { $$ = create_syncrep_config($1, $3, SYNC_REP_PRIORITY); } 67 8 : | ANY NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_QUORUM); } 68 4 : | FIRST NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_PRIORITY); } 69 : ; 70 : 71 : standby_list: 72 130 : standby_name { $$ = list_make1($1); } 73 60 : | standby_list ',' standby_name { $$ = lappend($1, $3); } 74 : ; 75 : 76 : standby_name: 77 190 : NAME { $$ = $1; } 78 0 : | NUM { $$ = $1; } 79 : ; 80 : %% 81 : 82 : static SyncRepConfigData * 83 130 : create_syncrep_config(const char *num_sync, List *members, uint8 syncrep_method) 84 : { 85 : SyncRepConfigData *config; 86 : int size; 87 : ListCell *lc; 88 : char *ptr; 89 : 90 : /* Compute space needed for flat representation */ 91 130 : size = offsetof(SyncRepConfigData, member_names); 92 320 : foreach(lc, members) 93 : { 94 190 : char *standby_name = (char *) lfirst(lc); 95 : 96 190 : size += strlen(standby_name) + 1; 97 : } 98 : 99 : /* And transform the data into flat representation */ 100 130 : config = (SyncRepConfigData *) palloc(size); 101 : 102 130 : config->config_size = size; 103 130 : config->num_sync = atoi(num_sync); 104 130 : config->syncrep_method = syncrep_method; 105 130 : config->nmembers = list_length(members); 106 130 : ptr = config->member_names; 107 320 : foreach(lc, members) 108 : { 109 190 : char *standby_name = (char *) lfirst(lc); 110 : 111 190 : strcpy(ptr, standby_name); 112 190 : ptr += strlen(standby_name) + 1; 113 : } 114 : 115 130 : return config; 116 : }