Line data Source code
1 : %{ 2 : /*------------------------------------------------------------------------- 3 : * 4 : * syncrep_gram.y - Parser for synchronous_standby_names 5 : * 6 : * Portions Copyright (c) 1996-2020, 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 "replication/syncrep.h" 18 : 19 : /* Result of parsing is returned in one of these two variables */ 20 : SyncRepConfigData *syncrep_parse_result; 21 : char *syncrep_parse_error_msg; 22 : 23 : static SyncRepConfigData *create_syncrep_config(const char *num_sync, 24 : List *members, uint8 syncrep_method); 25 : 26 : /* 27 : * Bison doesn't allocate anything that needs to live across parser calls, 28 : * so we can easily have it use palloc instead of malloc. This prevents 29 : * memory leaks if we error out during parsing. Note this only works with 30 : * bison >= 2.0. However, in bison 1.875 the default is to use alloca() 31 : * if possible, so there's not really much problem anyhow, at least if 32 : * you're building with gcc. 33 : */ 34 : #define YYMALLOC palloc 35 : #define YYFREE pfree 36 : 37 : %} 38 : 39 : %expect 0 40 : %name-prefix="syncrep_yy" 41 : 42 : %union 43 : { 44 : char *str; 45 : List *list; 46 : SyncRepConfigData *config; 47 : } 48 : 49 : %token <str> NAME NUM JUNK ANY FIRST 50 : 51 : %type <config> result standby_config 52 : %type <list> standby_list 53 : %type <str> standby_name 54 : 55 : %start result 56 : 57 : %% 58 : result: 59 0 : standby_config { syncrep_parse_result = $1; } 60 : ; 61 : 62 : standby_config: 63 0 : standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_PRIORITY); } 64 0 : | NUM '(' standby_list ')' { $$ = create_syncrep_config($1, $3, SYNC_REP_PRIORITY); } 65 0 : | ANY NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_QUORUM); } 66 0 : | FIRST NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_PRIORITY); } 67 : ; 68 : 69 : standby_list: 70 0 : standby_name { $$ = list_make1($1); } 71 0 : | standby_list ',' standby_name { $$ = lappend($1, $3); } 72 : ; 73 : 74 : standby_name: 75 0 : NAME { $$ = $1; } 76 0 : | NUM { $$ = $1; } 77 : ; 78 : %% 79 : 80 : static SyncRepConfigData * 81 0 : create_syncrep_config(const char *num_sync, List *members, uint8 syncrep_method) 82 : { 83 : SyncRepConfigData *config; 84 : int size; 85 : ListCell *lc; 86 : char *ptr; 87 : 88 : /* Compute space needed for flat representation */ 89 0 : size = offsetof(SyncRepConfigData, member_names); 90 0 : foreach(lc, members) 91 : { 92 0 : char *standby_name = (char *) lfirst(lc); 93 : 94 0 : size += strlen(standby_name) + 1; 95 : } 96 : 97 : /* And transform the data into flat representation */ 98 0 : config = (SyncRepConfigData *) palloc(size); 99 : 100 0 : config->config_size = size; 101 0 : config->num_sync = atoi(num_sync); 102 0 : config->syncrep_method = syncrep_method; 103 0 : config->nmembers = list_length(members); 104 0 : ptr = config->member_names; 105 0 : foreach(lc, members) 106 : { 107 0 : char *standby_name = (char *) lfirst(lc); 108 : 109 0 : strcpy(ptr, standby_name); 110 0 : ptr += strlen(standby_name) + 1; 111 : } 112 : 113 0 : return config; 114 : } 115 : 116 : #include "syncrep_scanner.c"