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