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