1 %{ 2 /*------------------------------------------------------------------------- 3 * 4 * syncrep_gram.y - Parser for synchronous_standby_names 5 * 6 * Portions Copyright (c) 1996-2019, 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 standby_config { syncrep_parse_result = $1; } 60 ; 61 62 standby_config: 63 standby_list { $$ = create_syncrep_config("1", $1, SYNC_REP_PRIORITY); } 64 | NUM '(' standby_list ')' { $$ = create_syncrep_config($1, $3, SYNC_REP_PRIORITY); } 65 | ANY NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_QUORUM); } 66 | FIRST NUM '(' standby_list ')' { $$ = create_syncrep_config($2, $4, SYNC_REP_PRIORITY); } 67 ; 68 69 standby_list: 70 standby_name { $$ = list_make1($1); } 71 | standby_list ',' standby_name { $$ = lappend($1, $3); } 72 ; 73 74 standby_name: 75 NAME { $$ = $1; } 76 | NUM { $$ = $1; } 77 ; 78 %% 79 80 static SyncRepConfigData * 81 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 size = offsetof(SyncRepConfigData, member_names); foreach(lc,members)90 foreach(lc, members) 91 { 92 char *standby_name = (char *) lfirst(lc); 93 94 size += strlen(standby_name) + 1; 95 } 96 97 /* And transform the data into flat representation */ 98 config = (SyncRepConfigData *) palloc(size); 99 100 config->config_size = size; 101 config->num_sync = atoi(num_sync); 102 config->syncrep_method = syncrep_method; 103 config->nmembers = list_length(members); 104 ptr = config->member_names; foreach(lc,members)105 foreach(lc, members) 106 { 107 char *standby_name = (char *) lfirst(lc); 108 109 strcpy(ptr, standby_name); 110 ptr += strlen(standby_name) + 1; 111 } 112 113 return config; 114 } 115 116 #include "syncrep_scanner.c" 117