diff options
Diffstat (limited to 'src')
66 files changed, 1114 insertions, 1191 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index eceab341255..fd91bcd68ec 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -749,6 +749,7 @@ XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, + uint64 fpi_bytes, bool topxid_included) { XLogCtlInsert *Insert = &XLogCtl->Insert; @@ -1081,6 +1082,7 @@ XLogInsertRecord(XLogRecData *rdata, pgWalUsage.wal_bytes += rechdr->xl_tot_len; pgWalUsage.wal_records++; pgWalUsage.wal_fpi += num_fpi; + pgWalUsage.wal_fpi_bytes += fpi_bytes; /* Required for the flush of pending stats WAL data */ pgstat_report_fixed = true; diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c index 496e0fa4ac6..58cb4b1b00c 100644 --- a/src/backend/access/transam/xloginsert.c +++ b/src/backend/access/transam/xloginsert.c @@ -33,12 +33,14 @@ #include "access/xloginsert.h" #include "catalog/pg_control.h" #include "common/pg_lzcompress.h" +#include "executor/instrument.h" #include "miscadmin.h" #include "pg_trace.h" #include "replication/origin.h" #include "storage/bufmgr.h" #include "storage/proc.h" #include "utils/memutils.h" +#include "utils/pgstat_internal.h" /* * Guess the maximum buffer size required to store a compressed version of @@ -137,6 +139,7 @@ static MemoryContext xloginsert_cxt; static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi, + uint64 *fpi_bytes, bool *topxid_included); static bool XLogCompressBackupBlock(const PageData *page, uint16 hole_offset, uint16 hole_length, void *dest, uint16 *dlen); @@ -510,6 +513,7 @@ XLogInsert(RmgrId rmid, uint8 info) XLogRecPtr fpw_lsn; XLogRecData *rdt; int num_fpi = 0; + uint64 fpi_bytes = 0; /* * Get values needed to decide whether to do full-page writes. Since @@ -519,10 +523,11 @@ XLogInsert(RmgrId rmid, uint8 info) GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites); rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites, - &fpw_lsn, &num_fpi, &topxid_included); + &fpw_lsn, &num_fpi, &fpi_bytes, + &topxid_included); EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi, - topxid_included); + fpi_bytes, topxid_included); } while (EndPos == InvalidXLogRecPtr); XLogResetInsertion(); @@ -560,7 +565,8 @@ XLogSimpleInsertInt64(RmgrId rmid, uint8 info, int64 value) static XLogRecData * XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, - XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included) + XLogRecPtr *fpw_lsn, int *num_fpi, uint64 *fpi_bytes, + bool *topxid_included) { XLogRecData *rdt; uint64 total_len = 0; @@ -796,6 +802,9 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, } total_len += bimg.length; + + /* Track the WAL full page images in bytes */ + *fpi_bytes += bimg.length; } if (needs_data) diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 6002fd0002f..9944e4bd2d1 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -937,10 +937,12 @@ RemoveConstraintById(Oid conId) con->conrelid); classForm = (Form_pg_class) GETSTRUCT(relTup); - if (classForm->relchecks == 0) /* should not happen */ - elog(ERROR, "relation \"%s\" has relchecks = 0", - RelationGetRelationName(rel)); - classForm->relchecks--; + if (classForm->relchecks > 0) + classForm->relchecks--; + else + /* should not happen */ + elog(WARNING, "relation \"%s\" has relchecks = %d", + RelationGetRelationName(rel), classForm->relchecks); CatalogTupleUpdate(pgrel, &relTup->t_self, relTup); diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 823776c1498..dec8df4f8ee 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1221,6 +1221,7 @@ CREATE VIEW pg_stat_wal AS w.wal_records, w.wal_fpi, w.wal_bytes, + w.wal_fpi_bytes, w.wal_buffers_full, w.stats_reset FROM pg_stat_get_wal() w; diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index a0974d71de1..1f45444b499 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -1082,7 +1082,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data, sub_remove_rels = lappend(sub_remove_rels, remove_rel); - logicalrep_worker_stop(sub->oid, relid); + logicalrep_worker_stop(WORKERTYPE_TABLESYNC, sub->oid, relid); /* * For READY state, we would have already dropped the @@ -2134,7 +2134,7 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) { LogicalRepWorker *w = (LogicalRepWorker *) lfirst(lc); - logicalrep_worker_stop(w->subid, w->relid); + logicalrep_worker_stop(w->type, w->subid, w->relid); } list_free(subworkers); diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c index 56e635f4700..9e11c662a7c 100644 --- a/src/backend/executor/instrument.c +++ b/src/backend/executor/instrument.c @@ -280,6 +280,7 @@ WalUsageAdd(WalUsage *dst, WalUsage *add) dst->wal_bytes += add->wal_bytes; dst->wal_records += add->wal_records; dst->wal_fpi += add->wal_fpi; + dst->wal_fpi_bytes += add->wal_fpi_bytes; dst->wal_buffers_full += add->wal_buffers_full; } @@ -289,5 +290,6 @@ WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, const WalUsage *sub) dst->wal_bytes += add->wal_bytes - sub->wal_bytes; dst->wal_records += add->wal_records - sub->wal_records; dst->wal_fpi += add->wal_fpi - sub->wal_fpi; + dst->wal_fpi_bytes += add->wal_fpi_bytes - sub->wal_fpi_bytes; dst->wal_buffers_full += add->wal_buffers_full - sub->wal_buffers_full; } diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c index 33a040506b4..a3679f8e86c 100644 --- a/src/backend/parser/parser.c +++ b/src/backend/parser/parser.c @@ -339,7 +339,7 @@ hexval(unsigned char c) /* is Unicode code point acceptable? */ static void -check_unicode_value(pg_wchar c) +check_unicode_value(char32_t c) { if (!is_valid_unicode_codepoint(c)) ereport(ERROR, @@ -376,7 +376,7 @@ str_udeescape(const char *str, char escape, char *new, *out; size_t new_len; - pg_wchar pair_first = 0; + char16_t pair_first = 0; ScannerCallbackState scbstate; /* @@ -420,7 +420,7 @@ str_udeescape(const char *str, char escape, isxdigit((unsigned char) in[3]) && isxdigit((unsigned char) in[4])) { - pg_wchar unicode; + char32_t unicode; unicode = (hexval(in[1]) << 12) + (hexval(in[2]) << 8) + @@ -457,7 +457,7 @@ str_udeescape(const char *str, char escape, isxdigit((unsigned char) in[6]) && isxdigit((unsigned char) in[7])) { - pg_wchar unicode; + char32_t unicode; unicode = (hexval(in[2]) << 20) + (hexval(in[3]) << 16) + diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 08990831fe8..a67815339b7 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -121,7 +121,7 @@ static void addlitchar(unsigned char ychar, core_yyscan_t yyscanner); static char *litbufdup(core_yyscan_t yyscanner); static unsigned char unescape_single_char(unsigned char c, core_yyscan_t yyscanner); static int process_integer_literal(const char *token, YYSTYPE *lval, int base); -static void addunicode(pg_wchar c, yyscan_t yyscanner); +static void addunicode(char32_t c, yyscan_t yyscanner); #define yyerror(msg) scanner_yyerror(msg, yyscanner) @@ -640,7 +640,7 @@ other . addlit(yytext, yyleng, yyscanner); } <xe>{xeunicode} { - pg_wchar c = strtoul(yytext + 2, NULL, 16); + char32_t c = strtoul(yytext + 2, NULL, 16); /* * For consistency with other productions, issue any @@ -668,7 +668,7 @@ other . POP_YYLLOC(); } <xeu>{xeunicode} { - pg_wchar c = strtoul(yytext + 2, NULL, 16); + char32_t c = strtoul(yytext + 2, NULL, 16); /* Remember start of overall string token ... */ PUSH_YYLLOC(); @@ -1376,7 +1376,7 @@ process_integer_literal(const char *token, YYSTYPE *lval, int base) } static void -addunicode(pg_wchar c, core_yyscan_t yyscanner) +addunicode(char32_t c, core_yyscan_t yyscanner) { ScannerCallbackState scbstate; char buf[MAX_UNICODE_EQUIVALENT_STRING + 1]; diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index 218cefe86e2..95b5cae9a55 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -245,20 +245,25 @@ WaitForReplicationWorkerAttach(LogicalRepWorker *worker, } /* - * Walks the workers array and searches for one that matches given - * subscription id and relid. + * Walks the workers array and searches for one that matches given worker type, + * subscription id, and relation id. * - * We are only interested in the leader apply worker or table sync worker. + * For apply workers, the relid should be set to InvalidOid, as they manage + * changes across all tables. For table sync workers, the relid should be set + * to the OID of the relation being synchronized. */ LogicalRepWorker * -logicalrep_worker_find(Oid subid, Oid relid, bool only_running) +logicalrep_worker_find(LogicalRepWorkerType wtype, Oid subid, Oid relid, + bool only_running) { int i; LogicalRepWorker *res = NULL; + /* relid must be valid only for table sync workers */ + Assert((wtype == WORKERTYPE_TABLESYNC) == OidIsValid(relid)); Assert(LWLockHeldByMe(LogicalRepWorkerLock)); - /* Search for attached worker for a given subscription id. */ + /* Search for an attached worker that matches the specified criteria. */ for (i = 0; i < max_logical_replication_workers; i++) { LogicalRepWorker *w = &LogicalRepCtx->workers[i]; @@ -268,7 +273,7 @@ logicalrep_worker_find(Oid subid, Oid relid, bool only_running) continue; if (w->in_use && w->subid == subid && w->relid == relid && - (!only_running || w->proc)) + w->type == wtype && (!only_running || w->proc)) { res = w; break; @@ -627,16 +632,20 @@ logicalrep_worker_stop_internal(LogicalRepWorker *worker, int signo) } /* - * Stop the logical replication worker for subid/relid, if any. + * Stop the logical replication worker that matches the specified worker type, + * subscription id, and relation id. */ void -logicalrep_worker_stop(Oid subid, Oid relid) +logicalrep_worker_stop(LogicalRepWorkerType wtype, Oid subid, Oid relid) { LogicalRepWorker *worker; + /* relid must be valid only for table sync workers */ + Assert((wtype == WORKERTYPE_TABLESYNC) == OidIsValid(relid)); + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); - worker = logicalrep_worker_find(subid, relid, false); + worker = logicalrep_worker_find(wtype, subid, relid, false); if (worker) { @@ -694,16 +703,20 @@ logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo) } /* - * Wake up (using latch) any logical replication worker for specified sub/rel. + * Wake up (using latch) any logical replication worker that matches the + * specified worker type, subscription id, and relation id. */ void -logicalrep_worker_wakeup(Oid subid, Oid relid) +logicalrep_worker_wakeup(LogicalRepWorkerType wtype, Oid subid, Oid relid) { LogicalRepWorker *worker; + /* relid must be valid only for table sync workers */ + Assert((wtype == WORKERTYPE_TABLESYNC) == OidIsValid(relid)); + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); - worker = logicalrep_worker_find(subid, relid, true); + worker = logicalrep_worker_find(wtype, subid, relid, true); if (worker) logicalrep_worker_wakeup_ptr(worker); @@ -1260,7 +1273,8 @@ ApplyLauncherMain(Datum main_arg) continue; LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); - w = logicalrep_worker_find(sub->oid, InvalidOid, false); + w = logicalrep_worker_find(WORKERTYPE_APPLY, sub->oid, InvalidOid, + false); if (w != NULL) { diff --git a/src/backend/replication/logical/syncutils.c b/src/backend/replication/logical/syncutils.c index e452a1e78d4..ae8c9385916 100644 --- a/src/backend/replication/logical/syncutils.c +++ b/src/backend/replication/logical/syncutils.c @@ -69,7 +69,8 @@ FinishSyncWorker(void) CommitTransactionCommand(); /* Find the leader apply worker and signal it. */ - logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid); + logicalrep_worker_wakeup(WORKERTYPE_APPLY, MyLogicalRepWorker->subid, + InvalidOid); /* Stop gracefully */ proc_exit(0); diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index 40e1ed3c20e..58c98488d7b 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -160,7 +160,8 @@ wait_for_table_state_change(Oid relid, char expected_state) /* Check if the sync worker is still running and bail if not. */ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); - worker = logicalrep_worker_find(MyLogicalRepWorker->subid, relid, + worker = logicalrep_worker_find(WORKERTYPE_TABLESYNC, + MyLogicalRepWorker->subid, relid, false); LWLockRelease(LogicalRepWorkerLock); if (!worker) @@ -207,8 +208,9 @@ wait_for_worker_state_change(char expected_state) * waiting. */ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); - worker = logicalrep_worker_find(MyLogicalRepWorker->subid, - InvalidOid, false); + worker = logicalrep_worker_find(WORKERTYPE_APPLY, + MyLogicalRepWorker->subid, InvalidOid, + false); if (worker && worker->proc) logicalrep_worker_wakeup_ptr(worker); LWLockRelease(LogicalRepWorkerLock); @@ -476,7 +478,8 @@ ProcessSyncingTablesForApply(XLogRecPtr current_lsn) */ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); - syncworker = logicalrep_worker_find(MyLogicalRepWorker->subid, + syncworker = logicalrep_worker_find(WORKERTYPE_TABLESYNC, + MyLogicalRepWorker->subid, rstate->relid, false); if (syncworker) diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 5df5a4612b6..7edd1c9cf06 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -1817,7 +1817,8 @@ apply_handle_stream_start(StringInfo s) * Signal the leader apply worker, as it may be waiting for * us. */ - logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid); + logicalrep_worker_wakeup(WORKERTYPE_APPLY, + MyLogicalRepWorker->subid, InvalidOid); } parallel_stream_nchanges = 0; @@ -3284,8 +3285,9 @@ FindDeletedTupleInLocalRel(Relation localrel, Oid localidxoid, * maybe_advance_nonremovable_xid() for details). */ LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); - leader = logicalrep_worker_find(MyLogicalRepWorker->subid, - InvalidOid, false); + leader = logicalrep_worker_find(WORKERTYPE_APPLY, + MyLogicalRepWorker->subid, InvalidOid, + false); if (!leader) { ereport(ERROR, diff --git a/src/backend/utils/activity/pgstat_backend.c b/src/backend/utils/activity/pgstat_backend.c index a864ae8e6a6..199ba2cc17a 100644 --- a/src/backend/utils/activity/pgstat_backend.c +++ b/src/backend/utils/activity/pgstat_backend.c @@ -252,6 +252,7 @@ pgstat_flush_backend_entry_wal(PgStat_EntryRef *entry_ref) WALSTAT_ACC(wal_records, wal_usage_diff); WALSTAT_ACC(wal_fpi, wal_usage_diff); WALSTAT_ACC(wal_bytes, wal_usage_diff); + WALSTAT_ACC(wal_fpi_bytes, wal_usage_diff); #undef WALSTAT_ACC /* diff --git a/src/backend/utils/activity/pgstat_wal.c b/src/backend/utils/activity/pgstat_wal.c index 0d04480d2f6..d4edb8b5733 100644 --- a/src/backend/utils/activity/pgstat_wal.c +++ b/src/backend/utils/activity/pgstat_wal.c @@ -121,6 +121,7 @@ pgstat_wal_flush_cb(bool nowait) WALSTAT_ACC(wal_records, wal_usage_diff); WALSTAT_ACC(wal_fpi, wal_usage_diff); WALSTAT_ACC(wal_bytes, wal_usage_diff); + WALSTAT_ACC(wal_fpi_bytes, wal_usage_diff); WALSTAT_ACC(wal_buffers_full, wal_usage_diff); #undef WALSTAT_ACC diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 78e19ac39ac..85418d73198 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,4 +1,4 @@ -/* ----------------------------------------------------------------------- +/*------------------------------------------------------------------------- * formatting.c * * src/backend/utils/adt/formatting.c @@ -54,7 +54,7 @@ * than Oracle :-), * to_char('Hello', 'X X X X X') -> 'H e l l o' * - * ----------------------------------------------------------------------- + *------------------------------------------------------------------------- */ #ifdef DEBUG_TO_FROM_CHAR @@ -92,44 +92,39 @@ #include "varatt.h" -/* ---------- +/* * Routines flags - * ---------- */ #define DCH_FLAG 0x1 /* DATE-TIME flag */ #define NUM_FLAG 0x2 /* NUMBER flag */ #define STD_FLAG 0x4 /* STANDARD flag */ -/* ---------- +/* * KeyWord Index (ascii from position 32 (' ') to 126 (~)) - * ---------- */ #define KeyWord_INDEX_SIZE ('~' - ' ') #define KeyWord_INDEX_FILTER(_c) ((_c) <= ' ' || (_c) >= '~' ? 0 : 1) -/* ---------- +/* * Maximal length of one node - * ---------- */ #define DCH_MAX_ITEM_SIZ 12 /* max localized day name */ #define NUM_MAX_ITEM_SIZ 8 /* roman number (RN has 15 chars) */ -/* ---------- +/* * Format parser structs - * ---------- */ typedef struct { const char *name; /* suffix string */ - int len, /* suffix length */ - id, /* used in node->suffix */ - type; /* prefix / postfix */ + size_t len; /* suffix length */ + int id; /* used in node->suffix */ + int type; /* prefix / postfix */ } KeySuffix; -/* ---------- +/* * FromCharDateMode - * ---------- * * This value is used to nominate one of several distinct (and mutually * exclusive) date conventions that a keyword can belong to. @@ -144,7 +139,7 @@ typedef enum typedef struct { const char *name; - int len; + size_t len; int id; bool is_digit; FromCharDateMode date_mode; @@ -171,9 +166,8 @@ typedef struct #define CLOCK_12_HOUR 1 -/* ---------- +/* * Full months - * ---------- */ static const char *const months_full[] = { "January", "February", "March", "April", "May", "June", "July", @@ -184,9 +178,9 @@ static const char *const days_short[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL }; -/* ---------- +/* * AD / BC - * ---------- + * * There is no 0 AD. Years go from 1 BC to 1 AD, so we make it * positive and map year == -1 to year zero, and shift all negative * years up one. For interval years, we just return the year. @@ -216,9 +210,8 @@ static const char *const days_short[] = { static const char *const adbc_strings[] = {ad_STR, bc_STR, AD_STR, BC_STR, NULL}; static const char *const adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_STR, NULL}; -/* ---------- +/* * AM / PM - * ---------- */ #define A_M_STR "A.M." #define a_m_STR "a.m." @@ -243,11 +236,10 @@ static const char *const adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_S static const char *const ampm_strings[] = {am_STR, pm_STR, AM_STR, PM_STR, NULL}; static const char *const ampm_strings_long[] = {a_m_STR, p_m_STR, A_M_STR, P_M_STR, NULL}; -/* ---------- +/* * Months in roman-numeral * (Must be in reverse order for seq_search (in FROM_CHAR), because * 'VIII' must have higher precedence than 'V') - * ---------- */ static const char *const rm_months_upper[] = {"XII", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I", NULL}; @@ -255,9 +247,8 @@ static const char *const rm_months_upper[] = static const char *const rm_months_lower[] = {"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL}; -/* ---------- +/* * Roman numerals - * ---------- */ static const char *const rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL}; static const char *const rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL}; @@ -289,23 +280,20 @@ static const char *const rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "D */ #define MAX_ROMAN_LEN 15 -/* ---------- +/* * Ordinal postfixes - * ---------- */ static const char *const numTH[] = {"ST", "ND", "RD", "TH", NULL}; static const char *const numth[] = {"st", "nd", "rd", "th", NULL}; -/* ---------- +/* * Flags & Options: - * ---------- */ #define TH_UPPER 1 #define TH_LOWER 2 -/* ---------- +/* * Number description struct - * ---------- */ typedef struct { @@ -320,9 +308,8 @@ typedef struct need_locale; /* needs it locale */ } NUMDesc; -/* ---------- +/* * Flags for NUMBER version - * ---------- */ #define NUM_F_DECIMAL (1 << 1) #define NUM_F_LDECIMAL (1 << 2) @@ -343,9 +330,8 @@ typedef struct #define NUM_LSIGN_POST 1 #define NUM_LSIGN_NONE 0 -/* ---------- +/* * Tests - * ---------- */ #define IS_DECIMAL(_f) ((_f)->flag & NUM_F_DECIMAL) #define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL) @@ -360,7 +346,7 @@ typedef struct #define IS_MULTI(_f) ((_f)->flag & NUM_F_MULTI) #define IS_EEEE(_f) ((_f)->flag & NUM_F_EEEE) -/* ---------- +/* * Format picture cache * * We will cache datetime format pictures up to DCH_CACHE_SIZE bytes long; @@ -376,7 +362,6 @@ typedef struct * * The max number of entries in each cache is DCH_CACHE_ENTRIES * resp. NUM_CACHE_ENTRIES. - * ---------- */ #define DCH_CACHE_OVERHEAD \ MAXALIGN(sizeof(bool) + sizeof(int)) @@ -419,9 +404,8 @@ static NUMCacheEntry *NUMCache[NUM_CACHE_ENTRIES]; static int n_NUMCache = 0; /* current number of entries */ static int NUMCounter = 0; /* aging-event counter */ -/* ---------- +/* * For char->date/time conversion - * ---------- */ typedef struct { @@ -452,7 +436,7 @@ typedef struct bool has_tz; /* was there a TZ field? */ int gmtoffset; /* GMT offset of fixed-offset zone abbrev */ pg_tz *tzp; /* pg_tz for dynamic abbrev */ - char *abbrev; /* dynamic abbrev */ + const char *abbrev; /* dynamic abbrev */ } TmFromChar; #define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar)) @@ -463,9 +447,8 @@ struct fmt_tz /* do_to_timestamp's timezone info output */ int gmtoffset; /* GMT offset in seconds */ }; -/* ---------- +/* * Debug - * ---------- */ #ifdef DEBUG_TO_FROM_CHAR #define DEBUG_TMFC(_X) \ @@ -484,13 +467,12 @@ struct fmt_tz /* do_to_timestamp's timezone info output */ #define DEBUG_TM(_X) #endif -/* ---------- +/* * Datetime to char conversion * * To support intervals as well as timestamps, we use a custom "tm" struct * that is almost like struct pg_tm, but has a 64-bit tm_hour field. * We omit the tm_isdst and tm_zone fields, which are not used here. - * ---------- */ struct fmt_tm { @@ -561,9 +543,8 @@ do { \ * KeyWord definitions *****************************************************************************/ -/* ---------- +/* * Suffixes (FormatNode.suffix is an OR of these codes) - * ---------- */ #define DCH_S_FM 0x01 #define DCH_S_TH 0x02 @@ -571,9 +552,8 @@ do { \ #define DCH_S_SP 0x08 #define DCH_S_TM 0x10 -/* ---------- +/* * Suffix tests - * ---------- */ #define S_THth(_s) ((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0) #define S_TH(_s) (((_s) & DCH_S_TH) ? 1 : 0) @@ -585,9 +565,8 @@ do { \ #define S_SP(_s) (((_s) & DCH_S_SP) ? 1 : 0) #define S_TM(_s) (((_s) & DCH_S_TM) ? 1 : 0) -/* ---------- +/* * Suffixes definition for DATE-TIME TO/FROM CHAR - * ---------- */ #define TM_SUFFIX_LEN 2 @@ -604,7 +583,7 @@ static const KeySuffix DCH_suff[] = { }; -/* ---------- +/* * Format-pictures (KeyWord). * * The KeyWord field; alphabetic sorted, *BUT* strings alike is sorted @@ -628,8 +607,6 @@ static const KeySuffix DCH_suff[] = { * 1) see in index to index['M' - 32], * 2) take keywords position (enum DCH_MI) from index * 3) run sequential search in keywords[] from this position - * - * ---------- */ typedef enum @@ -794,9 +771,8 @@ typedef enum _NUM_last_ } NUM_poz; -/* ---------- +/* * KeyWords for DATE-TIME version - * ---------- */ static const KeyWord DCH_keywords[] = { /* name, len, id, is_digit, date_mode */ @@ -917,11 +893,10 @@ static const KeyWord DCH_keywords[] = { {NULL, 0, 0, 0, 0} }; -/* ---------- +/* * KeyWords for NUMBER version * * The is_digit and date_mode fields are not relevant here. - * ---------- */ static const KeyWord NUM_keywords[] = { /* name, len, id is in Index */ @@ -967,9 +942,8 @@ static const KeyWord NUM_keywords[] = { }; -/* ---------- +/* * KeyWords index for DATE-TIME version - * ---------- */ static const int DCH_index[KeyWord_INDEX_SIZE] = { /* @@ -991,9 +965,8 @@ static const int DCH_index[KeyWord_INDEX_SIZE] = { /*---- chars over 126 are skipped ----*/ }; -/* ---------- +/* * KeyWords index for NUMBER version - * ---------- */ static const int NUM_index[KeyWord_INDEX_SIZE] = { /* @@ -1015,9 +988,8 @@ static const int NUM_index[KeyWord_INDEX_SIZE] = { /*---- chars over 126 are skipped ----*/ }; -/* ---------- +/* * Number processor struct - * ---------- */ typedef struct NUMProc { @@ -1062,9 +1034,8 @@ typedef struct NUMProc #define AMOUNT_TEST(s) (Np->inout_p <= Np->inout + (input_len - (s))) -/* ---------- +/* * Functions - * ---------- */ static const KeyWord *index_seq_search(const char *str, const KeyWord *kw, const int *index); @@ -1084,38 +1055,38 @@ static void dump_index(const KeyWord *k, const int *index); static void dump_node(FormatNode *node, int max); #endif -static const char *get_th(char *num, int type); -static char *str_numth(char *dest, char *num, int type); +static const char *get_th(const char *num, int type); +static char *str_numth(char *dest, const char *num, int type); static int adjust_partial_year_to_2020(int year); -static int strspace_len(const char *str); +static size_t strspace_len(const char *str); static bool from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode, Node *escontext); static bool from_char_set_int(int *dest, const int value, const FormatNode *node, Node *escontext); -static int from_char_parse_int_len(int *dest, const char **src, const int len, +static int from_char_parse_int_len(int *dest, const char **src, const size_t len, FormatNode *node, Node *escontext); static int from_char_parse_int(int *dest, const char **src, FormatNode *node, Node *escontext); -static int seq_search_ascii(const char *name, const char *const *array, int *len); -static int seq_search_localized(const char *name, char **array, int *len, +static int seq_search_ascii(const char *name, const char *const *array, size_t *len); +static int seq_search_localized(const char *name, char **array, size_t *len, Oid collid); static bool from_char_seq_search(int *dest, const char **src, const char *const *array, char **localized_array, Oid collid, FormatNode *node, Node *escontext); -static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, +static bool do_to_timestamp(const text *date_txt, const text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz, int *fprec, uint32 *flags, Node *escontext); static char *fill_str(char *str, int c, int max); -static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree); +static FormatNode *NUM_cache(int len, NUMDesc *Num, const text *pars_str, bool *shouldFree); static char *int_to_roman(int number); -static int roman_to_int(NUMProc *Np, int input_len); +static int roman_to_int(NUMProc *Np, size_t input_len); static void NUM_prepare_locale(NUMProc *Np); -static char *get_last_relevant_decnum(char *num); -static void NUM_numpart_from_char(NUMProc *Np, int id, int input_len); +static char *get_last_relevant_decnum(const char *num); +static void NUM_numpart_from_char(NUMProc *Np, int id, size_t input_len); static void NUM_numpart_to_char(NUMProc *Np, int id); static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, - char *number, int input_len, int to_char_out_pre_spaces, + char *number, size_t input_len, int to_char_out_pre_spaces, int sign, bool is_to_char, Oid collid); static DCHCacheEntry *DCH_cache_getnew(const char *str, bool std); static DCHCacheEntry *DCH_cache_search(const char *str, bool std); @@ -1125,11 +1096,10 @@ static NUMCacheEntry *NUM_cache_search(const char *str); static NUMCacheEntry *NUM_cache_fetch(const char *str); -/* ---------- +/* * Fast sequential search, use index for data selection which * go to seq. cycle (it is very fast for unwanted strings) * (can't be used binary search in format parsing) - * ---------- */ static const KeyWord * index_seq_search(const char *str, const KeyWord *kw, const int *index) @@ -1139,7 +1109,7 @@ index_seq_search(const char *str, const KeyWord *kw, const int *index) if (!KeyWord_INDEX_FILTER(*str)) return NULL; - if ((poz = *(index + (*str - ' '))) > -1) + if ((poz = index[*str - ' ']) > -1) { const KeyWord *k = kw + poz; @@ -1158,9 +1128,7 @@ index_seq_search(const char *str, const KeyWord *kw, const int *index) static const KeySuffix * suff_search(const char *str, const KeySuffix *suf, int type) { - const KeySuffix *s; - - for (s = suf; s->name != NULL; s++) + for (const KeySuffix *s = suf; s->name != NULL; s++) { if (s->type != type) continue; @@ -1181,9 +1149,8 @@ is_separator_char(const char *str) !(*str >= '0' && *str <= '9')); } -/* ---------- +/* * Prepare NUMDesc (number description struct) via FormatNode struct - * ---------- */ static void NUMDesc_prepare(NUMDesc *num, FormatNode *n) @@ -1233,7 +1200,7 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n) break; case NUM_B: - if (num->pre == 0 && num->post == 0 && (!IS_ZERO(num))) + if (num->pre == 0 && num->post == 0 && !IS_ZERO(num)) num->flag |= NUM_F_BLANK; break; @@ -1364,12 +1331,11 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n) errdetail("\"RN\" may only be used together with \"FM\"."))); } -/* ---------- +/* * Format parser, search small keywords and keyword's suffixes, and make * format-node tree. * * for DATE-TIME & NUMBER version - * ---------- */ static void parse_format(FormatNode *node, const char *str, const KeyWord *kw, @@ -1514,9 +1480,8 @@ parse_format(FormatNode *node, const char *str, const KeyWord *kw, n->suffix = 0; } -/* ---------- +/* * DEBUG: Dump the FormatNode Tree (debug) - * ---------- */ #ifdef DEBUG_TO_FROM_CHAR @@ -1554,20 +1519,19 @@ dump_node(FormatNode *node, int max) * Private utils *****************************************************************************/ -/* ---------- +/* * Return ST/ND/RD/TH for simple (1..9) numbers * type --> 0 upper, 1 lower - * ---------- */ static const char * -get_th(char *num, int type) +get_th(const char *num, int type) { - int len = strlen(num), - last; + size_t len = strlen(num); + char last; Assert(len > 0); - last = *(num + (len - 1)); + last = num[len - 1]; if (!isdigit((unsigned char) last)) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), @@ -1577,7 +1541,7 @@ get_th(char *num, int type) * All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get * 'ST/st', 'ND/nd', 'RD/rd', respectively */ - if ((len > 1) && (num[len - 2] == '1')) + if (len > 1 && num[len - 2] == '1') last = 0; switch (last) @@ -1601,13 +1565,12 @@ get_th(char *num, int type) } } -/* ---------- +/* * Convert string-number to ordinal string-number * type --> 0 upper, 1 lower - * ---------- */ static char * -str_numth(char *dest, char *num, int type) +str_numth(char *dest, const char *num, int type) { if (dest != num) strcpy(dest, num); @@ -1900,14 +1863,13 @@ char * asc_tolower(const char *buff, size_t nbytes) { char *result; - char *p; if (!buff) return NULL; result = pnstrdup(buff, nbytes); - for (p = result; *p; p++) + for (char *p = result; *p; p++) *p = pg_ascii_tolower((unsigned char) *p); return result; @@ -1923,14 +1885,13 @@ char * asc_toupper(const char *buff, size_t nbytes) { char *result; - char *p; if (!buff) return NULL; result = pnstrdup(buff, nbytes); - for (p = result; *p; p++) + for (char *p = result; *p; p++) *p = pg_ascii_toupper((unsigned char) *p); return result; @@ -1946,7 +1907,6 @@ char * asc_initcap(const char *buff, size_t nbytes) { char *result; - char *p; int wasalnum = false; if (!buff) @@ -1954,7 +1914,7 @@ asc_initcap(const char *buff, size_t nbytes) result = pnstrdup(buff, nbytes); - for (p = result; *p; p++) + for (char *p = result; *p; p++) { char c; @@ -2006,11 +1966,10 @@ asc_toupper_z(const char *buff) /* asc_initcap_z is not currently needed */ -/* ---------- +/* * Skip TM / th in FROM_CHAR * * If S_THth is on, skip two chars, assuming there are two available - * ---------- */ #define SKIP_THth(ptr, _suf) \ do { \ @@ -2023,21 +1982,19 @@ asc_toupper_z(const char *buff) #ifdef DEBUG_TO_FROM_CHAR -/* ----------- +/* * DEBUG: Call for debug and for index checking; (Show ASCII char * and defined keyword for each used position - * ---------- */ static void dump_index(const KeyWord *k, const int *index) { - int i, - count = 0, + int count = 0, free_i = 0; elog(DEBUG_elog_output, "TO-FROM_CHAR: Dump KeyWord Index:"); - for (i = 0; i < KeyWord_INDEX_SIZE; i++) + for (int i = 0; i < KeyWord_INDEX_SIZE; i++) { if (index[i] != -1) { @@ -2055,9 +2012,8 @@ dump_index(const KeyWord *k, const int *index) } #endif /* DEBUG */ -/* ---------- +/* * Return true if next format picture is not digit value - * ---------- */ static bool is_next_separator(FormatNode *n) @@ -2116,10 +2072,10 @@ adjust_partial_year_to_2020(int year) } -static int +static size_t strspace_len(const char *str) { - int len = 0; + size_t len = 0; while (*str && isspace((unsigned char) *str)) { @@ -2202,13 +2158,13 @@ from_char_set_int(int *dest, const int value, const FormatNode *node, * with DD and MI). */ static int -from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node, +from_char_parse_int_len(int *dest, const char **src, const size_t len, FormatNode *node, Node *escontext) { long result; char copy[DCH_MAX_ITEM_SIZ + 1]; const char *init = *src; - int used; + size_t used; /* * Skip any whitespace before parsing the integer. @@ -2216,7 +2172,7 @@ from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode * *src += strspace_len(*src); Assert(len <= DCH_MAX_ITEM_SIZ); - used = (int) strlcpy(copy, *src, len + 1); + used = strlcpy(copy, *src, len + 1); if (S_FM(node->suffix) || is_next_separator(node)) { @@ -2243,7 +2199,7 @@ from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode * (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("source string too short for \"%s\" formatting field", node->key->name), - errdetail("Field requires %d characters, but only %d remain.", + errdetail("Field requires %zu characters, but only %zu remain.", len, used), errhint("If your source string is not fixed-width, " "try using the \"FM\" modifier."))); @@ -2257,7 +2213,7 @@ from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode * (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("invalid value \"%s\" for \"%s\"", copy, node->key->name), - errdetail("Field requires %d characters, but only %d could be parsed.", + errdetail("Field requires %zu characters, but only %zu could be parsed.", len, used), errhint("If your source string is not fixed-width, " "try using the \"FM\" modifier."))); @@ -2317,10 +2273,9 @@ from_char_parse_int(int *dest, const char **src, FormatNode *node, * suitable for comparisons to ASCII strings. */ static int -seq_search_ascii(const char *name, const char *const *array, int *len) +seq_search_ascii(const char *name, const char *const *array, size_t *len) { unsigned char firstc; - const char *const *a; *len = 0; @@ -2331,17 +2286,14 @@ seq_search_ascii(const char *name, const char *const *array, int *len) /* we handle first char specially to gain some speed */ firstc = pg_ascii_tolower((unsigned char) *name); - for (a = array; *a != NULL; a++) + for (const char *const *a = array; *a != NULL; a++) { - const char *p; - const char *n; - /* compare first chars */ if (pg_ascii_tolower((unsigned char) **a) != firstc) continue; /* compare rest of string */ - for (p = *a + 1, n = name + 1;; p++, n++) + for (const char *p = *a + 1, *n = name + 1;; p++, n++) { /* return success if we matched whole array entry */ if (*p == '\0') @@ -2374,9 +2326,8 @@ seq_search_ascii(const char *name, const char *const *array, int *len) * the arrays exported by pg_locale.c aren't const. */ static int -seq_search_localized(const char *name, char **array, int *len, Oid collid) +seq_search_localized(const char *name, char **array, size_t *len, Oid collid) { - char **a; char *upper_name; char *lower_name; @@ -2390,9 +2341,9 @@ seq_search_localized(const char *name, char **array, int *len, Oid collid) * The case-folding processing done below is fairly expensive, so before * doing that, make a quick pass to see if there is an exact match. */ - for (a = array; *a != NULL; a++) + for (char **a = array; *a != NULL; a++) { - int element_len = strlen(*a); + size_t element_len = strlen(*a); if (strncmp(name, *a, element_len) == 0) { @@ -2409,11 +2360,11 @@ seq_search_localized(const char *name, char **array, int *len, Oid collid) lower_name = str_tolower(upper_name, strlen(upper_name), collid); pfree(upper_name); - for (a = array; *a != NULL; a++) + for (char **a = array; *a != NULL; a++) { char *upper_element; char *lower_element; - int element_len; + size_t element_len; /* Likewise upper/lower-case array element */ upper_element = str_toupper(*a, strlen(*a), collid); @@ -2462,7 +2413,7 @@ from_char_seq_search(int *dest, const char **src, const char *const *array, char **localized_array, Oid collid, FormatNode *node, Node *escontext) { - int len; + size_t len; if (localized_array == NULL) *dest = seq_search_ascii(*src, array, &len); @@ -2476,9 +2427,8 @@ from_char_seq_search(int *dest, const char **src, const char *const *array, * any) to avoid including irrelevant data. */ char *copy = pstrdup(*src); - char *c; - for (c = copy; *c; c++) + for (char *c = copy; *c; c++) { if (scanner_isspace(*c)) { @@ -2498,15 +2448,13 @@ from_char_seq_search(int *dest, const char **src, const char *const *array, return true; } -/* ---------- +/* * Process a TmToChar struct as denoted by a list of FormatNodes. * The formatted data is written to the string pointed to by 'out'. - * ---------- */ static void DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid) { - FormatNode *n; char *s; struct fmt_tm *tm = &in->tm; int i; @@ -2515,7 +2463,7 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col cache_locale_time(); s = out; - for (n = node; n->type != NODE_TYPE_END; n++) + for (FormatNode *n = node; n->type != NODE_TYPE_END; n++) { if (n->type != NODE_TYPE_ACTION) { @@ -3725,10 +3673,9 @@ DCH_prevent_counter_overflow(void) static int DCH_datetime_type(FormatNode *node) { - FormatNode *n; int flags = 0; - for (n = node; n->type != NODE_TYPE_END; n++) + for (FormatNode *n = node; n->type != NODE_TYPE_END; n++) { if (n->type != NODE_TYPE_ACTION) continue; @@ -3928,13 +3875,13 @@ DCH_cache_fetch(const char *str, bool std) * for formatting. */ static text * -datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid) +datetime_to_char_body(TmToChar *tmtc, const text *fmt, bool is_interval, Oid collid) { FormatNode *format; char *fmt_str, *result; bool incache; - int fmt_len; + size_t fmt_len; text *res; /* @@ -3992,9 +3939,8 @@ datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid) * Public routines ***************************************************************************/ -/* ------------------- +/* * TIMESTAMP to_char() - * ------------------- */ Datum timestamp_to_char(PG_FUNCTION_ARGS) @@ -4068,9 +4014,8 @@ timestamptz_to_char(PG_FUNCTION_ARGS) } -/* ------------------- +/* * INTERVAL to_char() - * ------------------- */ Datum interval_to_char(PG_FUNCTION_ARGS) @@ -4107,12 +4052,11 @@ interval_to_char(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(res); } -/* --------------------- +/* * TO_TIMESTAMP() * * Make Timestamp from date_str which is formatted at argument 'fmt' * ( to_timestamp is reverse to_char() ) - * --------------------- */ Datum to_timestamp(PG_FUNCTION_ARGS) @@ -4148,10 +4092,9 @@ to_timestamp(PG_FUNCTION_ARGS) PG_RETURN_TIMESTAMP(result); } -/* ---------- +/* * TO_DATE * Make Date from date_str which is formatted at argument 'fmt' - * ---------- */ Datum to_date(PG_FUNCTION_ARGS) @@ -4368,7 +4311,7 @@ bool datetime_format_has_tz(const char *fmt_str) { bool incache; - int fmt_len = strlen(fmt_str); + size_t fmt_len = strlen(fmt_str); int result; FormatNode *format; @@ -4428,7 +4371,7 @@ datetime_format_has_tz(const char *fmt_str) * struct 'tm', 'fsec', struct 'tz', and 'fprec'. */ static bool -do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, +do_to_timestamp(const text *date_txt, const text *fmt, Oid collid, bool std, struct pg_tm *tm, fsec_t *fsec, struct fmt_tz *tz, int *fprec, uint32 *flags, Node *escontext) { @@ -4864,7 +4807,7 @@ static char * fill_str(char *str, int c, int max) { memset(str, c, max); - *(str + max) = '\0'; + str[max] = '\0'; return str; } @@ -4998,12 +4941,11 @@ NUM_cache_fetch(const char *str) return ent; } -/* ---------- +/* * Cache routine for NUM to_char version - * ---------- */ static FormatNode * -NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree) +NUM_cache(int len, NUMDesc *Num, const text *pars_str, bool *shouldFree) { FormatNode *format = NULL; char *str; @@ -5070,8 +5012,7 @@ int_to_roman(int number) { int len, num; - char *p, - *result, + char *result, numstr[12]; result = (char *) palloc(MAX_ROMAN_LEN + 1); @@ -5092,7 +5033,7 @@ int_to_roman(int number) len = snprintf(numstr, sizeof(numstr), "%d", number); Assert(len > 0 && len <= 4); - for (p = numstr; *p != '\0'; p++, --len) + for (char *p = numstr; *p != '\0'; p++, --len) { num = *p - ('0' + 1); if (num < 0) @@ -5126,10 +5067,10 @@ int_to_roman(int number) * If input is invalid, return -1. */ static int -roman_to_int(NUMProc *Np, int input_len) +roman_to_int(NUMProc *Np, size_t input_len) { int result = 0; - int len; + size_t len; char romanChars[MAX_ROMAN_LEN]; int romanValues[MAX_ROMAN_LEN]; int repeatCount = 1; @@ -5168,7 +5109,7 @@ roman_to_int(NUMProc *Np, int input_len) return -1; /* No valid roman numerals. */ /* Check for valid combinations and compute the represented value. */ - for (int i = 0; i < len; i++) + for (size_t i = 0; i < len; i++) { char currChar = romanChars[i]; int currValue = romanValues[i]; @@ -5271,9 +5212,8 @@ roman_to_int(NUMProc *Np, int input_len) } -/* ---------- +/* * Locale - * ---------- */ static void NUM_prepare_locale(NUMProc *Np) @@ -5349,16 +5289,15 @@ NUM_prepare_locale(NUMProc *Np) } } -/* ---------- +/* * Return pointer of last relevant number after decimal point * 12.0500 --> last relevant is '5' * 12.0000 --> last relevant is '.' * If there is no decimal point, return NULL (which will result in same * behavior as if FM hadn't been specified). - * ---------- */ static char * -get_last_relevant_decnum(char *num) +get_last_relevant_decnum(const char *num) { char *result, *p = strchr(num, '.'); @@ -5381,12 +5320,11 @@ get_last_relevant_decnum(char *num) return result; } -/* ---------- +/* * Number extraction for TO_NUMBER() - * ---------- */ static void -NUM_numpart_from_char(NUMProc *Np, int id, int input_len) +NUM_numpart_from_char(NUMProc *Np, int id, size_t input_len) { bool isread = false; @@ -5420,7 +5358,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len) */ if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_PRE) { - int x = 0; + size_t x = 0; #ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "Try read locale pre-sign (%c)", *Np->inout_p); @@ -5499,7 +5437,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len) * Np->decimal is always just "." if we don't have a D format token. * So we just unconditionally match to Np->decimal. */ - int x = strlen(Np->decimal); + size_t x = strlen(Np->decimal); #ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "Try read decimal point (%c)", @@ -5538,7 +5476,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len) (Np->inout_p + 1) < Np->inout + input_len && !isdigit((unsigned char) *(Np->inout_p + 1))) { - int x; + size_t x; char *tmp = Np->inout_p++; #ifdef DEBUG_TO_FROM_CHAR @@ -5596,9 +5534,8 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len) *(_n)->number == '0' && \ (_n)->Num->post != 0) -/* ---------- +/* * Add digit or sign to number-string - * ---------- */ static void NUM_numpart_to_char(NUMProc *Np, int id) @@ -5791,7 +5728,7 @@ NUM_numpart_to_char(NUMProc *Np, int id) * Skip over "n" input characters, but only if they aren't numeric data */ static void -NUM_eat_non_data_chars(NUMProc *Np, int n, int input_len) +NUM_eat_non_data_chars(NUMProc *Np, int n, size_t input_len) { while (n-- > 0) { @@ -5805,14 +5742,14 @@ NUM_eat_non_data_chars(NUMProc *Np, int n, int input_len) static char * NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, - char *number, int input_len, int to_char_out_pre_spaces, + char *number, size_t input_len, int to_char_out_pre_spaces, int sign, bool is_to_char, Oid collid) { FormatNode *n; NUMProc _Np, *Np = &_Np; const char *pattern; - int pattern_len; + size_t pattern_len; MemSet(Np, 0, sizeof(NUMProc)); @@ -5893,7 +5830,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, */ if (Np->last_relevant && Np->Num->zero_end > Np->out_pre_spaces) { - int last_zero_pos; + size_t last_zero_pos; char *last_zero; /* note that Np->number cannot be zero-length here */ @@ -6267,10 +6204,9 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, } } -/* ---------- +/* * MACRO: Start part of NUM - for all NUM's to_char variants * (sorry, but I hate copy same code - macro is better..) - * ---------- */ #define NUM_TOCHAR_prepare \ do { \ @@ -6281,13 +6217,12 @@ do { \ format = NUM_cache(len, &Num, fmt, &shouldFree); \ } while (0) -/* ---------- +/* * MACRO: Finish part of NUM - * ---------- */ #define NUM_TOCHAR_finish \ do { \ - int len; \ + size_t len; \ \ NUM_processor(format, &Num, VARDATA(result), numstr, 0, out_pre_spaces, sign, true, PG_GET_COLLATION()); \ \ @@ -6303,9 +6238,8 @@ do { \ SET_VARSIZE(result, len + VARHDRSZ); \ } while (0) -/* ------------------- +/* * NUMERIC to_number() (convert string to numeric) - * ------------------- */ Datum numeric_to_number(PG_FUNCTION_ARGS) @@ -6362,9 +6296,8 @@ numeric_to_number(PG_FUNCTION_ARGS) return result; } -/* ------------------ +/* * NUMERIC to_char() - * ------------------ */ Datum numeric_to_char(PG_FUNCTION_ARGS) @@ -6434,7 +6367,7 @@ numeric_to_char(PG_FUNCTION_ARGS) } else { - int numstr_pre_len; + size_t numstr_pre_len; Numeric val = value; Numeric x; @@ -6490,9 +6423,8 @@ numeric_to_char(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } -/* --------------- +/* * INT4 to_char() - * --------------- */ Datum int4_to_char(PG_FUNCTION_ARGS) @@ -6532,7 +6464,7 @@ int4_to_char(PG_FUNCTION_ARGS) } else { - int numstr_pre_len; + size_t numstr_pre_len; if (IS_MULTI(&Num)) { @@ -6584,9 +6516,8 @@ int4_to_char(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } -/* --------------- +/* * INT8 to_char() - * --------------- */ Datum int8_to_char(PG_FUNCTION_ARGS) @@ -6642,7 +6573,7 @@ int8_to_char(PG_FUNCTION_ARGS) } else { - int numstr_pre_len; + size_t numstr_pre_len; if (IS_MULTI(&Num)) { @@ -6696,9 +6627,8 @@ int8_to_char(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } -/* ----------------- +/* * FLOAT4 to_char() - * ----------------- */ Datum float4_to_char(PG_FUNCTION_ARGS) @@ -6757,7 +6687,7 @@ float4_to_char(PG_FUNCTION_ARGS) { float4 val = value; char *orgnum; - int numstr_pre_len; + size_t numstr_pre_len; if (IS_MULTI(&Num)) { @@ -6809,9 +6739,8 @@ float4_to_char(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } -/* ----------------- +/* * FLOAT8 to_char() - * ----------------- */ Datum float8_to_char(PG_FUNCTION_ARGS) @@ -6870,7 +6799,7 @@ float8_to_char(PG_FUNCTION_ARGS) { float8 val = value; char *orgnum; - int numstr_pre_len; + size_t numstr_pre_len; if (IS_MULTI(&Num)) { diff --git a/src/backend/utils/adt/jsonpath_scan.l b/src/backend/utils/adt/jsonpath_scan.l index c7aab83eeb4..8c3a0a9c642 100644 --- a/src/backend/utils/adt/jsonpath_scan.l +++ b/src/backend/utils/adt/jsonpath_scan.l @@ -574,7 +574,7 @@ hexval(char c, int *result, struct Node *escontext, yyscan_t yyscanner) /* Add given unicode character to scanstring */ static bool -addUnicodeChar(int ch, struct Node *escontext, yyscan_t yyscanner) +addUnicodeChar(char32_t ch, struct Node *escontext, yyscan_t yyscanner) { if (ch == 0) { @@ -607,7 +607,7 @@ addUnicodeChar(int ch, struct Node *escontext, yyscan_t yyscanner) /* Add unicode character, processing any surrogate pairs */ static bool -addUnicode(int ch, int *hi_surrogate, struct Node *escontext, yyscan_t yyscanner) +addUnicode(char32_t ch, int *hi_surrogate, struct Node *escontext, yyscan_t yyscanner) { if (is_utf16_surrogate_first(ch)) { @@ -655,7 +655,7 @@ parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner) for (i = 2; i < l; i += 2) /* skip '\u' */ { - int ch = 0; + char32_t ch = 0; int j, si; diff --git a/src/backend/utils/adt/pg_locale_builtin.c b/src/backend/utils/adt/pg_locale_builtin.c index 3dc611b50e1..1021e0d129b 100644 --- a/src/backend/utils/adt/pg_locale_builtin.c +++ b/src/backend/utils/adt/pg_locale_builtin.c @@ -15,7 +15,6 @@ #include "catalog/pg_collation.h" #include "common/unicode_case.h" #include "common/unicode_category.h" -#include "mb/pg_wchar.h" #include "miscadmin.h" #include "utils/builtins.h" #include "utils/pg_locale.h" @@ -36,6 +35,23 @@ struct WordBoundaryState }; /* + * In UTF-8, pg_wchar is guaranteed to be the code point value. + */ +static inline char32_t +to_char32(pg_wchar wc) +{ + Assert(GetDatabaseEncoding() == PG_UTF8); + return (char32_t) wc; +} + +static inline pg_wchar +to_pg_wchar(char32_t c32) +{ + Assert(GetDatabaseEncoding() == PG_UTF8); + return (pg_wchar) c32; +} + +/* * Simple word boundary iterator that draws boundaries each time the result of * pg_u_isalnum() changes. */ @@ -47,7 +63,7 @@ initcap_wbnext(void *state) while (wbstate->offset < wbstate->len && wbstate->str[wbstate->offset] != '\0') { - pg_wchar u = utf8_to_unicode((unsigned char *) wbstate->str + + char32_t u = utf8_to_unicode((unsigned char *) wbstate->str + wbstate->offset); bool curr_alnum = pg_u_isalnum(u, wbstate->posix); @@ -112,61 +128,61 @@ strfold_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen, static bool wc_isdigit_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isdigit(wc, !locale->builtin.casemap_full); + return pg_u_isdigit(to_char32(wc), !locale->builtin.casemap_full); } static bool wc_isalpha_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isalpha(wc); + return pg_u_isalpha(to_char32(wc)); } static bool wc_isalnum_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isalnum(wc, !locale->builtin.casemap_full); + return pg_u_isalnum(to_char32(wc), !locale->builtin.casemap_full); } static bool wc_isupper_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isupper(wc); + return pg_u_isupper(to_char32(wc)); } static bool wc_islower_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_islower(wc); + return pg_u_islower(to_char32(wc)); } static bool wc_isgraph_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isgraph(wc); + return pg_u_isgraph(to_char32(wc)); } static bool wc_isprint_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isprint(wc); + return pg_u_isprint(to_char32(wc)); } static bool wc_ispunct_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_ispunct(wc, !locale->builtin.casemap_full); + return pg_u_ispunct(to_char32(wc), !locale->builtin.casemap_full); } static bool wc_isspace_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isspace(wc); + return pg_u_isspace(to_char32(wc)); } static bool wc_isxdigit_builtin(pg_wchar wc, pg_locale_t locale) { - return pg_u_isxdigit(wc, !locale->builtin.casemap_full); + return pg_u_isxdigit(to_char32(wc), !locale->builtin.casemap_full); } static bool @@ -179,13 +195,13 @@ char_is_cased_builtin(char ch, pg_locale_t locale) static pg_wchar wc_toupper_builtin(pg_wchar wc, pg_locale_t locale) { - return unicode_uppercase_simple(wc); + return to_pg_wchar(unicode_uppercase_simple(to_char32(wc))); } static pg_wchar wc_tolower_builtin(pg_wchar wc, pg_locale_t locale) { - return unicode_lowercase_simple(wc); + return to_pg_wchar(unicode_lowercase_simple(to_char32(wc))); } static const struct ctype_methods ctype_methods_builtin = { diff --git a/src/backend/utils/adt/pg_locale_icu.c b/src/backend/utils/adt/pg_locale_icu.c index 05bad202669..f5a0cc8fe41 100644 --- a/src/backend/utils/adt/pg_locale_icu.c +++ b/src/backend/utils/adt/pg_locale_icu.c @@ -128,6 +128,11 @@ char_is_cased_icu(char ch, pg_locale_t locale) (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); } +/* + * XXX: many of the functions below rely on casts directly from pg_wchar to + * UChar32, which is correct for the UTF-8 encoding, but not in general. + */ + static pg_wchar toupper_icu(pg_wchar wc, pg_locale_t locale) { diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c index 7ae778dc296..9c7fcd1fc7a 100644 --- a/src/backend/utils/adt/pg_locale_libc.c +++ b/src/backend/utils/adt/pg_locale_libc.c @@ -45,8 +45,7 @@ * * 2. When working in UTF8 encoding, we use the <wctype.h> functions. * This assumes that every platform uses Unicode codepoints directly - * as the wchar_t representation of Unicode. (XXX: ICU makes this assumption - * even for non-UTF8 encodings, which may be a problem.) On some platforms + * as the wchar_t representation of Unicode. On some platforms * wchar_t is only 16 bits wide, so we have to punt for codepoints > 0xFFFF. * * 3. In all other encodings, we use the <ctype.h> functions for pg_wchar diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 1fe33df2756..a710508979e 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -1637,7 +1637,7 @@ static Datum pg_stat_wal_build_tuple(PgStat_WalCounters wal_counters, TimestampTz stat_reset_timestamp) { -#define PG_STAT_WAL_COLS 5 +#define PG_STAT_WAL_COLS 6 TupleDesc tupdesc; Datum values[PG_STAT_WAL_COLS] = {0}; bool nulls[PG_STAT_WAL_COLS] = {0}; @@ -1651,9 +1651,11 @@ pg_stat_wal_build_tuple(PgStat_WalCounters wal_counters, INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "wal_bytes", NUMERICOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_buffers_full", + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_fpi_bytes", + NUMERICOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "wal_buffers_full", INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "stats_reset", + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "stats_reset", TIMESTAMPTZOID, -1, 0); BlessTupleDesc(tupdesc); @@ -1669,12 +1671,18 @@ pg_stat_wal_build_tuple(PgStat_WalCounters wal_counters, ObjectIdGetDatum(0), Int32GetDatum(-1)); - values[3] = Int64GetDatum(wal_counters.wal_buffers_full); + snprintf(buf, sizeof buf, UINT64_FORMAT, wal_counters.wal_fpi_bytes); + values[3] = DirectFunctionCall3(numeric_in, + CStringGetDatum(buf), + ObjectIdGetDatum(0), + Int32GetDatum(-1)); + + values[4] = Int64GetDatum(wal_counters.wal_buffers_full); if (stat_reset_timestamp != 0) - values[4] = TimestampTzGetDatum(stat_reset_timestamp); + values[5] = TimestampTzGetDatum(stat_reset_timestamp); else - nulls[4] = true; + nulls[5] = true; /* Returns the record as Datum */ PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index e5e066a5537..cb23ad52782 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -6575,6 +6575,13 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, continue; /* + * get_actual_variable_endpoint uses the index-only-scan machinery, so + * ignore indexes that can't use it on their first column. + */ + if (!index->canreturn[0]) + continue; + + /* * The first index column must match the desired variable, sortop, and * collation --- but we can use a descending-order index. */ diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 2c398cd9e5c..8d735786e51 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -5419,12 +5419,12 @@ unicode_assigned(PG_FUNCTION_ARGS) ereport(ERROR, (errmsg("Unicode categorization can only be performed if server encoding is UTF8"))); - /* convert to pg_wchar */ + /* convert to char32_t */ size = pg_mbstrlen_with_len(VARDATA_ANY(input), VARSIZE_ANY_EXHDR(input)); p = (unsigned char *) VARDATA_ANY(input); for (int i = 0; i < size; i++) { - pg_wchar uchar = utf8_to_unicode(p); + char32_t uchar = utf8_to_unicode(p); int category = unicode_category(uchar); if (category == PG_U_UNASSIGNED) @@ -5443,24 +5443,24 @@ unicode_normalize_func(PG_FUNCTION_ARGS) char *formstr = text_to_cstring(PG_GETARG_TEXT_PP(1)); UnicodeNormalizationForm form; int size; - pg_wchar *input_chars; - pg_wchar *output_chars; + char32_t *input_chars; + char32_t *output_chars; unsigned char *p; text *result; int i; form = unicode_norm_form_from_string(formstr); - /* convert to pg_wchar */ + /* convert to char32_t */ size = pg_mbstrlen_with_len(VARDATA_ANY(input), VARSIZE_ANY_EXHDR(input)); - input_chars = palloc((size + 1) * sizeof(pg_wchar)); + input_chars = palloc((size + 1) * sizeof(char32_t)); p = (unsigned char *) VARDATA_ANY(input); for (i = 0; i < size; i++) { input_chars[i] = utf8_to_unicode(p); p += pg_utf_mblen(p); } - input_chars[i] = (pg_wchar) '\0'; + input_chars[i] = (char32_t) '\0'; Assert((char *) p == VARDATA_ANY(input) + VARSIZE_ANY_EXHDR(input)); /* action */ @@ -5468,7 +5468,7 @@ unicode_normalize_func(PG_FUNCTION_ARGS) /* convert back to UTF-8 string */ size = 0; - for (pg_wchar *wp = output_chars; *wp; wp++) + for (char32_t *wp = output_chars; *wp; wp++) { unsigned char buf[4]; @@ -5480,7 +5480,7 @@ unicode_normalize_func(PG_FUNCTION_ARGS) SET_VARSIZE(result, size + VARHDRSZ); p = (unsigned char *) VARDATA_ANY(result); - for (pg_wchar *wp = output_chars; *wp; wp++) + for (char32_t *wp = output_chars; *wp; wp++) { unicode_to_utf8(*wp, p); p += pg_utf_mblen(p); @@ -5509,8 +5509,8 @@ unicode_is_normalized(PG_FUNCTION_ARGS) char *formstr = text_to_cstring(PG_GETARG_TEXT_PP(1)); UnicodeNormalizationForm form; int size; - pg_wchar *input_chars; - pg_wchar *output_chars; + char32_t *input_chars; + char32_t *output_chars; unsigned char *p; int i; UnicodeNormalizationQC quickcheck; @@ -5519,16 +5519,16 @@ unicode_is_normalized(PG_FUNCTION_ARGS) form = unicode_norm_form_from_string(formstr); - /* convert to pg_wchar */ + /* convert to char32_t */ size = pg_mbstrlen_with_len(VARDATA_ANY(input), VARSIZE_ANY_EXHDR(input)); - input_chars = palloc((size + 1) * sizeof(pg_wchar)); + input_chars = palloc((size + 1) * sizeof(char32_t)); p = (unsigned char *) VARDATA_ANY(input); for (i = 0; i < size; i++) { input_chars[i] = utf8_to_unicode(p); p += pg_utf_mblen(p); } - input_chars[i] = (pg_wchar) '\0'; + input_chars[i] = (char32_t) '\0'; Assert((char *) p == VARDATA_ANY(input) + VARSIZE_ANY_EXHDR(input)); /* quick check (see UAX #15) */ @@ -5542,11 +5542,11 @@ unicode_is_normalized(PG_FUNCTION_ARGS) output_chars = unicode_normalize(form, input_chars); output_size = 0; - for (pg_wchar *wp = output_chars; *wp; wp++) + for (char32_t *wp = output_chars; *wp; wp++) output_size++; result = (size == output_size) && - (memcmp(input_chars, output_chars, size * sizeof(pg_wchar)) == 0); + (memcmp(input_chars, output_chars, size * sizeof(char32_t)) == 0); PG_RETURN_BOOL(result); } @@ -5602,7 +5602,7 @@ unistr(PG_FUNCTION_ARGS) int len; StringInfoData str; text *result; - pg_wchar pair_first = 0; + char16_t pair_first = 0; char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1]; instr = VARDATA_ANY(input_text); @@ -5626,7 +5626,7 @@ unistr(PG_FUNCTION_ARGS) else if ((len >= 5 && isxdigits_n(instr + 1, 4)) || (len >= 6 && instr[1] == 'u' && isxdigits_n(instr + 2, 4))) { - pg_wchar unicode; + char32_t unicode; int offset = instr[1] == 'u' ? 2 : 1; unicode = hexval_n(instr + offset, 4); @@ -5662,7 +5662,7 @@ unistr(PG_FUNCTION_ARGS) } else if (len >= 8 && instr[1] == '+' && isxdigits_n(instr + 2, 6)) { - pg_wchar unicode; + char32_t unicode; unicode = hexval_n(instr + 2, 6); @@ -5697,7 +5697,7 @@ unistr(PG_FUNCTION_ARGS) } else if (len >= 10 && instr[1] == 'U' && isxdigits_n(instr + 2, 8)) { - pg_wchar unicode; + char32_t unicode; unicode = hexval_n(instr + 2, 8); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 2b798b823ea..915d0bc9084 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4658,12 +4658,6 @@ CheckNNConstraintFetch(Relation relation) break; } - check[found].ccenforced = conform->conenforced; - check[found].ccvalid = conform->convalidated; - check[found].ccnoinherit = conform->connoinherit; - check[found].ccname = MemoryContextStrdup(CacheMemoryContext, - NameStr(conform->conname)); - /* Grab and test conbin is actually set */ val = fastgetattr(htup, Anum_pg_constraint_conbin, @@ -4676,7 +4670,13 @@ CheckNNConstraintFetch(Relation relation) /* detoast and convert to cstring in caller's context */ char *s = TextDatumGetCString(val); + check[found].ccenforced = conform->conenforced; + check[found].ccvalid = conform->convalidated; + check[found].ccnoinherit = conform->connoinherit; + check[found].ccname = MemoryContextStrdup(CacheMemoryContext, + NameStr(conform->conname)); check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s); + pfree(s); found++; } diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c index 886ecbad871..fb629ed5c8f 100644 --- a/src/backend/utils/mb/mbutils.c +++ b/src/backend/utils/mb/mbutils.c @@ -862,7 +862,7 @@ perform_default_encoding_conversion(const char *src, int len, * may call this outside any transaction, or in an aborted transaction. */ void -pg_unicode_to_server(pg_wchar c, unsigned char *s) +pg_unicode_to_server(char32_t c, unsigned char *s) { unsigned char c_as_utf8[MAX_MULTIBYTE_CHAR_LEN + 1]; int c_as_utf8_len; @@ -924,7 +924,7 @@ pg_unicode_to_server(pg_wchar c, unsigned char *s) * but simply return false on conversion failure. */ bool -pg_unicode_to_server_noerror(pg_wchar c, unsigned char *s) +pg_unicode_to_server_noerror(char32_t c, unsigned char *s) { unsigned char c_as_utf8[MAX_MULTIBYTE_CHAR_LEN + 1]; int c_as_utf8_len; diff --git a/src/backend/utils/misc/gen_guc_tables.pl b/src/backend/utils/misc/gen_guc_tables.pl index b187259bf1e..3efde02bab8 100644 --- a/src/backend/utils/misc/gen_guc_tables.pl +++ b/src/backend/utils/misc/gen_guc_tables.pl @@ -25,10 +25,7 @@ my $parse = Catalog::ParseData($input_fname); open my $ofh, '>', $output_fname or die; print_boilerplate($ofh, $output_fname, 'GUC tables'); -foreach my $type (qw(bool int real string enum)) -{ - print_one_table($ofh, $type); -} +print_table($ofh); close $ofh; @@ -41,56 +38,52 @@ sub dquote return q{"} . $s =~ s/"/\\"/gr . q{"}; } -# Print GUC table for one type. -sub print_one_table +# Print GUC table. +sub print_table { - my ($ofh, $type) = @_; - my $Type = ucfirst $type; + my ($ofh) = @_; print $ofh "\n\n"; - print $ofh "struct config_${type} ConfigureNames${Type}[] =\n"; + print $ofh "struct config_generic ConfigureNames[] =\n"; print $ofh "{\n"; foreach my $entry (@{$parse}) { - next if $entry->{type} ne $type; - print $ofh "#ifdef $entry->{ifdef}\n" if $entry->{ifdef}; print $ofh "\t{\n"; - print $ofh "\t\t{\n"; - printf $ofh "\t\t\t.name = %s,\n", dquote($entry->{name}); - printf $ofh "\t\t\t.context = %s,\n", $entry->{context}; - printf $ofh "\t\t\t.group = %s,\n", $entry->{group}; - printf $ofh "\t\t\t.short_desc = gettext_noop(%s),\n", + printf $ofh "\t\t.name = %s,\n", dquote($entry->{name}); + printf $ofh "\t\t.context = %s,\n", $entry->{context}; + printf $ofh "\t\t.group = %s,\n", $entry->{group}; + printf $ofh "\t\t.short_desc = gettext_noop(%s),\n", dquote($entry->{short_desc}); - printf $ofh "\t\t\t.long_desc = gettext_noop(%s),\n", + printf $ofh "\t\t.long_desc = gettext_noop(%s),\n", dquote($entry->{long_desc}) if $entry->{long_desc}; - printf $ofh "\t\t\t.flags = %s,\n", $entry->{flags} - if $entry->{flags}; - printf $ofh "\t\t\t.vartype = %s,\n", ('PGC_' . uc($type)); - print $ofh "\t\t},\n"; - printf $ofh "\t\t.variable = &%s,\n", $entry->{variable}; - printf $ofh "\t\t.boot_val = %s,\n", $entry->{boot_val}; - printf $ofh "\t\t.min = %s,\n", $entry->{min} + printf $ofh "\t\t.flags = %s,\n", $entry->{flags} if $entry->{flags}; + printf $ofh "\t\t.vartype = %s,\n", ('PGC_' . uc($entry->{type})); + printf $ofh "\t\t._%s = {\n", $entry->{type}; + printf $ofh "\t\t\t.variable = &%s,\n", $entry->{variable}; + printf $ofh "\t\t\t.boot_val = %s,\n", $entry->{boot_val}; + printf $ofh "\t\t\t.min = %s,\n", $entry->{min} if $entry->{type} eq 'int' || $entry->{type} eq 'real'; - printf $ofh "\t\t.max = %s,\n", $entry->{max} + printf $ofh "\t\t\t.max = %s,\n", $entry->{max} if $entry->{type} eq 'int' || $entry->{type} eq 'real'; - printf $ofh "\t\t.options = %s,\n", $entry->{options} + printf $ofh "\t\t\t.options = %s,\n", $entry->{options} if $entry->{type} eq 'enum'; - printf $ofh "\t\t.check_hook = %s,\n", $entry->{check_hook} + printf $ofh "\t\t\t.check_hook = %s,\n", $entry->{check_hook} if $entry->{check_hook}; - printf $ofh "\t\t.assign_hook = %s,\n", $entry->{assign_hook} + printf $ofh "\t\t\t.assign_hook = %s,\n", $entry->{assign_hook} if $entry->{assign_hook}; - printf $ofh "\t\t.show_hook = %s,\n", $entry->{show_hook} + printf $ofh "\t\t\t.show_hook = %s,\n", $entry->{show_hook} if $entry->{show_hook}; + print $ofh "\t\t},\n"; print $ofh "\t},\n"; print $ofh "#endif\n" if $entry->{ifdef}; print $ofh "\n"; } print $ofh "\t/* End-of-list marker */\n"; - print $ofh "\t{{0}}\n"; + print $ofh "\t{0}\n"; print $ofh "};\n"; return; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a82286cc98a..679846da42c 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -245,12 +245,12 @@ static void ReportGUCOption(struct config_generic *record); static void set_config_sourcefile(const char *name, char *sourcefile, int sourceline); static void reapply_stacked_values(struct config_generic *variable, - struct config_string *pHolder, + struct config_generic *pHolder, GucStack *stack, const char *curvalue, GucContext curscontext, GucSource cursource, Oid cursrole); -static void free_placeholder(struct config_string *pHolder); +static void free_placeholder(struct config_generic *pHolder); static bool validate_option_array_item(const char *name, const char *value, bool skipIfNoPermissions); static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *head); @@ -261,15 +261,15 @@ static bool assignable_custom_variable_name(const char *name, bool skip_errors, int elevel); static void do_serialize(char **destptr, Size *maxbytes, const char *fmt,...) pg_attribute_printf(3, 4); -static bool call_bool_check_hook(const struct config_bool *conf, bool *newval, +static bool call_bool_check_hook(const struct config_generic *conf, bool *newval, void **extra, GucSource source, int elevel); -static bool call_int_check_hook(const struct config_int *conf, int *newval, +static bool call_int_check_hook(const struct config_generic *conf, int *newval, void **extra, GucSource source, int elevel); -static bool call_real_check_hook(const struct config_real *conf, double *newval, +static bool call_real_check_hook(const struct config_generic *conf, double *newval, void **extra, GucSource source, int elevel); -static bool call_string_check_hook(const struct config_string *conf, char **newval, +static bool call_string_check_hook(const struct config_generic *conf, char **newval, void **extra, GucSource source, int elevel); -static bool call_enum_check_hook(const struct config_enum *conf, int *newval, +static bool call_enum_check_hook(const struct config_generic *conf, int *newval, void **extra, GucSource source, int elevel); @@ -703,13 +703,13 @@ guc_free(void *ptr) * Detect whether strval is referenced anywhere in a GUC string item */ static bool -string_field_used(struct config_string *conf, char *strval) +string_field_used(struct config_generic *conf, char *strval) { - if (strval == *(conf->variable) || - strval == conf->reset_val || - strval == conf->boot_val) + if (strval == *(conf->_string.variable) || + strval == conf->_string.reset_val || + strval == conf->_string.boot_val) return true; - for (GucStack *stack = conf->gen.stack; stack; stack = stack->prev) + for (GucStack *stack = conf->stack; stack; stack = stack->prev) { if (strval == stack->prior.val.stringval || strval == stack->masked.val.stringval) @@ -724,7 +724,7 @@ string_field_used(struct config_string *conf, char *strval) * states). */ static void -set_string_field(struct config_string *conf, char **field, char *newval) +set_string_field(struct config_generic *conf, char **field, char *newval) { char *oldval = *field; @@ -787,25 +787,19 @@ set_stack_value(struct config_generic *gconf, config_var_value *val) switch (gconf->vartype) { case PGC_BOOL: - val->val.boolval = - *((struct config_bool *) gconf)->variable; + val->val.boolval = *gconf->_bool.variable; break; case PGC_INT: - val->val.intval = - *((struct config_int *) gconf)->variable; + val->val.intval = *gconf->_int.variable; break; case PGC_REAL: - val->val.realval = - *((struct config_real *) gconf)->variable; + val->val.realval = *gconf->_real.variable; break; case PGC_STRING: - set_string_field((struct config_string *) gconf, - &(val->val.stringval), - *((struct config_string *) gconf)->variable); + set_string_field(gconf, &(val->val.stringval), *gconf->_string.variable); break; case PGC_ENUM: - val->val.enumval = - *((struct config_enum *) gconf)->variable; + val->val.enumval = *gconf->_enum.variable; break; } set_extra_field(gconf, &(val->extra), gconf->extra); @@ -827,7 +821,7 @@ discard_stack_value(struct config_generic *gconf, config_var_value *val) /* no need to do anything */ break; case PGC_STRING: - set_string_field((struct config_string *) gconf, + set_string_field(gconf, &(val->val.stringval), NULL); break; @@ -892,19 +886,7 @@ build_guc_variables(void) /* * Count all the built-in variables. */ - for (int i = 0; ConfigureNamesBool[i].gen.name; i++) - num_vars++; - - for (int i = 0; ConfigureNamesInt[i].gen.name; i++) - num_vars++; - - for (int i = 0; ConfigureNamesReal[i].gen.name; i++) - num_vars++; - - for (int i = 0; ConfigureNamesString[i].gen.name; i++) - num_vars++; - - for (int i = 0; ConfigureNamesEnum[i].gen.name; i++) + for (int i = 0; ConfigureNames[i].name; i++) num_vars++; /* @@ -922,57 +904,9 @@ build_guc_variables(void) &hash_ctl, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT); - for (int i = 0; ConfigureNamesBool[i].gen.name; i++) - { - struct config_generic *gucvar = &ConfigureNamesBool[i].gen; - - hentry = (GUCHashEntry *) hash_search(guc_hashtab, - &gucvar->name, - HASH_ENTER, - &found); - Assert(!found); - hentry->gucvar = gucvar; - } - - for (int i = 0; ConfigureNamesInt[i].gen.name; i++) - { - struct config_generic *gucvar = &ConfigureNamesInt[i].gen; - - hentry = (GUCHashEntry *) hash_search(guc_hashtab, - &gucvar->name, - HASH_ENTER, - &found); - Assert(!found); - hentry->gucvar = gucvar; - } - - for (int i = 0; ConfigureNamesReal[i].gen.name; i++) - { - struct config_generic *gucvar = &ConfigureNamesReal[i].gen; - - hentry = (GUCHashEntry *) hash_search(guc_hashtab, - &gucvar->name, - HASH_ENTER, - &found); - Assert(!found); - hentry->gucvar = gucvar; - } - - for (int i = 0; ConfigureNamesString[i].gen.name; i++) - { - struct config_generic *gucvar = &ConfigureNamesString[i].gen; - - hentry = (GUCHashEntry *) hash_search(guc_hashtab, - &gucvar->name, - HASH_ENTER, - &found); - Assert(!found); - hentry->gucvar = gucvar; - } - - for (int i = 0; ConfigureNamesEnum[i].gen.name; i++) + for (int i = 0; ConfigureNames[i].name; i++) { - struct config_generic *gucvar = &ConfigureNamesEnum[i].gen; + struct config_generic *gucvar = &ConfigureNames[i]; hentry = (GUCHashEntry *) hash_search(guc_hashtab, &gucvar->name, @@ -1122,44 +1056,42 @@ assignable_custom_variable_name(const char *name, bool skip_errors, int elevel) static struct config_generic * add_placeholder_variable(const char *name, int elevel) { - size_t sz = sizeof(struct config_string) + sizeof(char *); - struct config_string *var; - struct config_generic *gen; + size_t sz = sizeof(struct config_generic) + sizeof(char *); + struct config_generic *var; - var = (struct config_string *) guc_malloc(elevel, sz); + var = (struct config_generic *) guc_malloc(elevel, sz); if (var == NULL) return NULL; memset(var, 0, sz); - gen = &var->gen; - gen->name = guc_strdup(elevel, name); - if (gen->name == NULL) + var->name = guc_strdup(elevel, name); + if (var->name == NULL) { guc_free(var); return NULL; } - gen->context = PGC_USERSET; - gen->group = CUSTOM_OPTIONS; - gen->short_desc = "GUC placeholder variable"; - gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER; - gen->vartype = PGC_STRING; + var->context = PGC_USERSET; + var->group = CUSTOM_OPTIONS; + var->short_desc = "GUC placeholder variable"; + var->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER; + var->vartype = PGC_STRING; /* * The char* is allocated at the end of the struct since we have no * 'static' place to point to. Note that the current value, as well as * the boot and reset values, start out NULL. */ - var->variable = (char **) (var + 1); + var->_string.variable = (char **) (var + 1); - if (!add_guc_variable((struct config_generic *) var, elevel)) + if (!add_guc_variable(var, elevel)) { - guc_free(unconstify(char *, gen->name)); + guc_free(unconstify(char *, var->name)); guc_free(var); return NULL; } - return gen; + return var; } /* @@ -1385,62 +1317,62 @@ check_GUC_init(const struct config_generic *gconf) { case PGC_BOOL: { - const struct config_bool *conf = (const struct config_bool *) gconf; + const struct config_bool *conf = &gconf->_bool; if (*conf->variable && !conf->boot_val) { elog(LOG, "GUC (PGC_BOOL) %s, boot_val=%d, C-var=%d", - conf->gen.name, conf->boot_val, *conf->variable); + gconf->name, conf->boot_val, *conf->variable); return false; } break; } case PGC_INT: { - const struct config_int *conf = (const struct config_int *) gconf; + const struct config_int *conf = &gconf->_int; if (*conf->variable != 0 && *conf->variable != conf->boot_val) { elog(LOG, "GUC (PGC_INT) %s, boot_val=%d, C-var=%d", - conf->gen.name, conf->boot_val, *conf->variable); + gconf->name, conf->boot_val, *conf->variable); return false; } break; } case PGC_REAL: { - const struct config_real *conf = (const struct config_real *) gconf; + const struct config_real *conf = &gconf->_real; if (*conf->variable != 0.0 && *conf->variable != conf->boot_val) { elog(LOG, "GUC (PGC_REAL) %s, boot_val=%g, C-var=%g", - conf->gen.name, conf->boot_val, *conf->variable); + gconf->name, conf->boot_val, *conf->variable); return false; } break; } case PGC_STRING: { - const struct config_string *conf = (const struct config_string *) gconf; + const struct config_string *conf = &gconf->_string; if (*conf->variable != NULL && (conf->boot_val == NULL || strcmp(*conf->variable, conf->boot_val) != 0)) { elog(LOG, "GUC (PGC_STRING) %s, boot_val=%s, C-var=%s", - conf->gen.name, conf->boot_val ? conf->boot_val : "<null>", *conf->variable); + gconf->name, conf->boot_val ? conf->boot_val : "<null>", *conf->variable); return false; } break; } case PGC_ENUM: { - const struct config_enum *conf = (const struct config_enum *) gconf; + const struct config_enum *conf = &gconf->_enum; if (*conf->variable != conf->boot_val) { elog(LOG, "GUC (PGC_ENUM) %s, boot_val=%d, C-var=%d", - conf->gen.name, conf->boot_val, *conf->variable); + gconf->name, conf->boot_val, *conf->variable); return false; } break; @@ -1607,13 +1539,13 @@ InitializeOneGUCOption(struct config_generic *gconf) { case PGC_BOOL: { - struct config_bool *conf = (struct config_bool *) gconf; + struct config_bool *conf = &gconf->_bool; bool newval = conf->boot_val; - if (!call_bool_check_hook(conf, &newval, &extra, + if (!call_bool_check_hook(gconf, &newval, &extra, PGC_S_DEFAULT, LOG)) elog(FATAL, "failed to initialize %s to %d", - conf->gen.name, (int) newval); + gconf->name, (int) newval); if (conf->assign_hook) conf->assign_hook(newval, extra); *conf->variable = conf->reset_val = newval; @@ -1621,15 +1553,15 @@ InitializeOneGUCOption(struct config_generic *gconf) } case PGC_INT: { - struct config_int *conf = (struct config_int *) gconf; + struct config_int *conf = &gconf->_int; int newval = conf->boot_val; Assert(newval >= conf->min); Assert(newval <= conf->max); - if (!call_int_check_hook(conf, &newval, &extra, + if (!call_int_check_hook(gconf, &newval, &extra, PGC_S_DEFAULT, LOG)) elog(FATAL, "failed to initialize %s to %d", - conf->gen.name, newval); + gconf->name, newval); if (conf->assign_hook) conf->assign_hook(newval, extra); *conf->variable = conf->reset_val = newval; @@ -1637,15 +1569,15 @@ InitializeOneGUCOption(struct config_generic *gconf) } case PGC_REAL: { - struct config_real *conf = (struct config_real *) gconf; + struct config_real *conf = &gconf->_real; double newval = conf->boot_val; Assert(newval >= conf->min); Assert(newval <= conf->max); - if (!call_real_check_hook(conf, &newval, &extra, + if (!call_real_check_hook(gconf, &newval, &extra, PGC_S_DEFAULT, LOG)) elog(FATAL, "failed to initialize %s to %g", - conf->gen.name, newval); + gconf->name, newval); if (conf->assign_hook) conf->assign_hook(newval, extra); *conf->variable = conf->reset_val = newval; @@ -1653,7 +1585,7 @@ InitializeOneGUCOption(struct config_generic *gconf) } case PGC_STRING: { - struct config_string *conf = (struct config_string *) gconf; + struct config_string *conf = &gconf->_string; char *newval; /* non-NULL boot_val must always get strdup'd */ @@ -1662,10 +1594,10 @@ InitializeOneGUCOption(struct config_generic *gconf) else newval = NULL; - if (!call_string_check_hook(conf, &newval, &extra, + if (!call_string_check_hook(gconf, &newval, &extra, PGC_S_DEFAULT, LOG)) elog(FATAL, "failed to initialize %s to \"%s\"", - conf->gen.name, newval ? newval : ""); + gconf->name, newval ? newval : ""); if (conf->assign_hook) conf->assign_hook(newval, extra); *conf->variable = conf->reset_val = newval; @@ -1673,13 +1605,13 @@ InitializeOneGUCOption(struct config_generic *gconf) } case PGC_ENUM: { - struct config_enum *conf = (struct config_enum *) gconf; + struct config_enum *conf = &gconf->_enum; int newval = conf->boot_val; - if (!call_enum_check_hook(conf, &newval, &extra, + if (!call_enum_check_hook(gconf, &newval, &extra, PGC_S_DEFAULT, LOG)) elog(FATAL, "failed to initialize %s to %d", - conf->gen.name, newval); + gconf->name, newval); if (conf->assign_hook) conf->assign_hook(newval, extra); *conf->variable = conf->reset_val = newval; @@ -1726,7 +1658,7 @@ SelectConfigFiles(const char *userDoption, const char *progname) char *fname; bool fname_is_malloced; struct stat stat_buf; - struct config_string *data_directory_rec; + struct config_generic *data_directory_rec; /* configdir is -D option, or $PGDATA if no -D */ if (userDoption) @@ -1806,10 +1738,10 @@ SelectConfigFiles(const char *userDoption, const char *progname) * Note: SetDataDir will copy and absolute-ize its argument, so we don't * have to. */ - data_directory_rec = (struct config_string *) + data_directory_rec = find_option("data_directory", false, false, PANIC); - if (*data_directory_rec->variable) - SetDataDir(*data_directory_rec->variable); + if (*data_directory_rec->_string.variable) + SetDataDir(*data_directory_rec->_string.variable); else if (configdir) SetDataDir(configdir); else @@ -1971,62 +1903,62 @@ ResetAllOptions(void) { case PGC_BOOL: { - struct config_bool *conf = (struct config_bool *) gconf; + struct config_bool *conf = &gconf->_bool; if (conf->assign_hook) conf->assign_hook(conf->reset_val, - conf->gen.reset_extra); + gconf->reset_extra); *conf->variable = conf->reset_val; - set_extra_field(&conf->gen, &conf->gen.extra, - conf->gen.reset_extra); + set_extra_field(gconf, &gconf->extra, + gconf->reset_extra); break; } case PGC_INT: { - struct config_int *conf = (struct config_int *) gconf; + struct config_int *conf = &gconf->_int; if (conf->assign_hook) conf->assign_hook(conf->reset_val, - conf->gen.reset_extra); + gconf->reset_extra); *conf->variable = conf->reset_val; - set_extra_field(&conf->gen, &conf->gen.extra, - conf->gen.reset_extra); + set_extra_field(gconf, &gconf->extra, + gconf->reset_extra); break; } case PGC_REAL: { - struct config_real *conf = (struct config_real *) gconf; + struct config_real *conf = &gconf->_real; if (conf->assign_hook) conf->assign_hook(conf->reset_val, - conf->gen.reset_extra); + gconf->reset_extra); *conf->variable = conf->reset_val; - set_extra_field(&conf->gen, &conf->gen.extra, - conf->gen.reset_extra); + set_extra_field(gconf, &gconf->extra, + gconf->reset_extra); break; } case PGC_STRING: { - struct config_string *conf = (struct config_string *) gconf; + struct config_string *conf = &gconf->_string; if (conf->assign_hook) conf->assign_hook(conf->reset_val, - conf->gen.reset_extra); - set_string_field(conf, conf->variable, conf->reset_val); - set_extra_field(&conf->gen, &conf->gen.extra, - conf->gen.reset_extra); + gconf->reset_extra); + set_string_field(gconf, conf->variable, conf->reset_val); + set_extra_field(gconf, &gconf->extra, + gconf->reset_extra); break; } case PGC_ENUM: { - struct config_enum *conf = (struct config_enum *) gconf; + struct config_enum *conf = &gconf->_enum; if (conf->assign_hook) conf->assign_hook(conf->reset_val, - conf->gen.reset_extra); + gconf->reset_extra); *conf->variable = conf->reset_val; - set_extra_field(&conf->gen, &conf->gen.extra, - conf->gen.reset_extra); + set_extra_field(gconf, &gconf->extra, + gconf->reset_extra); break; } } @@ -2346,17 +2278,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel) { case PGC_BOOL: { - struct config_bool *conf = (struct config_bool *) gconf; + struct config_bool *conf = &gconf->_bool; bool newval = newvalue.val.boolval; void *newextra = newvalue.extra; if (*conf->variable != newval || - conf->gen.extra != newextra) + gconf->extra != newextra) { if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(gconf, &gconf->extra, newextra); changed = true; } @@ -2364,17 +2296,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel) } case PGC_INT: { - struct config_int *conf = (struct config_int *) gconf; + struct config_int *conf = &gconf->_int; int newval = newvalue.val.intval; void *newextra = newvalue.extra; if (*conf->variable != newval || - conf->gen.extra != newextra) + gconf->extra != newextra) { if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(gconf, &gconf->extra, newextra); changed = true; } @@ -2382,17 +2314,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel) } case PGC_REAL: { - struct config_real *conf = (struct config_real *) gconf; + struct config_real *conf = &gconf->_real; double newval = newvalue.val.realval; void *newextra = newvalue.extra; if (*conf->variable != newval || - conf->gen.extra != newextra) + gconf->extra != newextra) { if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(gconf, &gconf->extra, newextra); changed = true; } @@ -2400,17 +2332,17 @@ AtEOXact_GUC(bool isCommit, int nestLevel) } case PGC_STRING: { - struct config_string *conf = (struct config_string *) gconf; + struct config_string *conf = &gconf->_string; char *newval = newvalue.val.stringval; void *newextra = newvalue.extra; if (*conf->variable != newval || - conf->gen.extra != newextra) + gconf->extra != newextra) { if (conf->assign_hook) conf->assign_hook(newval, newextra); - set_string_field(conf, conf->variable, newval); - set_extra_field(&conf->gen, &conf->gen.extra, + set_string_field(gconf, conf->variable, newval); + set_extra_field(gconf, &gconf->extra, newextra); changed = true; } @@ -2421,23 +2353,23 @@ AtEOXact_GUC(bool isCommit, int nestLevel) * we have type-specific code anyway, might as * well inline it. */ - set_string_field(conf, &stack->prior.val.stringval, NULL); - set_string_field(conf, &stack->masked.val.stringval, NULL); + set_string_field(gconf, &stack->prior.val.stringval, NULL); + set_string_field(gconf, &stack->masked.val.stringval, NULL); break; } case PGC_ENUM: { - struct config_enum *conf = (struct config_enum *) gconf; + struct config_enum *conf = &gconf->_enum; int newval = newvalue.val.enumval; void *newextra = newvalue.extra; if (*conf->variable != newval || - conf->gen.extra != newextra) + gconf->extra != newextra) { if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(gconf, &gconf->extra, newextra); changed = true; } @@ -2960,16 +2892,16 @@ parse_real(const char *value, double *result, int flags, const char **hintmsg) * allocated for modification. */ const char * -config_enum_lookup_by_value(const struct config_enum *record, int val) +config_enum_lookup_by_value(const struct config_generic *record, int val) { - for (const struct config_enum_entry *entry = record->options; entry && entry->name; entry++) + for (const struct config_enum_entry *entry = record->_enum.options; entry && entry->name; entry++) { if (entry->val == val) return entry->name; } elog(ERROR, "could not find enum option %d for %s", - val, record->gen.name); + val, record->name); return NULL; /* silence compiler */ } @@ -3070,41 +3002,39 @@ parse_and_validate_value(const struct config_generic *record, { case PGC_BOOL: { - const struct config_bool *conf = (const struct config_bool *) record; - if (!parse_bool(value, &newval->boolval)) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("parameter \"%s\" requires a Boolean value", - conf->gen.name))); + record->name))); return false; } - if (!call_bool_check_hook(conf, &newval->boolval, newextra, + if (!call_bool_check_hook(record, &newval->boolval, newextra, source, elevel)) return false; } break; case PGC_INT: { - const struct config_int *conf = (const struct config_int *) record; + const struct config_int *conf = &record->_int; const char *hintmsg; if (!parse_int(value, &newval->intval, - conf->gen.flags, &hintmsg)) + record->flags, &hintmsg)) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value for parameter \"%s\": \"%s\"", - conf->gen.name, value), + record->name, value), hintmsg ? errhint("%s", _(hintmsg)) : 0)); return false; } if (newval->intval < conf->min || newval->intval > conf->max) { - const char *unit = get_config_unit_name(conf->gen.flags); + const char *unit = get_config_unit_name(record->flags); const char *unitspace; if (unit) @@ -3116,36 +3046,36 @@ parse_and_validate_value(const struct config_generic *record, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)", newval->intval, unitspace, unit, - conf->gen.name, + record->name, conf->min, unitspace, unit, conf->max, unitspace, unit))); return false; } - if (!call_int_check_hook(conf, &newval->intval, newextra, + if (!call_int_check_hook(record, &newval->intval, newextra, source, elevel)) return false; } break; case PGC_REAL: { - const struct config_real *conf = (const struct config_real *) record; + const struct config_real *conf = &record->_real; const char *hintmsg; if (!parse_real(value, &newval->realval, - conf->gen.flags, &hintmsg)) + record->flags, &hintmsg)) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value for parameter \"%s\": \"%s\"", - conf->gen.name, value), + record->name, value), hintmsg ? errhint("%s", _(hintmsg)) : 0)); return false; } if (newval->realval < conf->min || newval->realval > conf->max) { - const char *unit = get_config_unit_name(conf->gen.flags); + const char *unit = get_config_unit_name(record->flags); const char *unitspace; if (unit) @@ -3157,21 +3087,19 @@ parse_and_validate_value(const struct config_generic *record, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)", newval->realval, unitspace, unit, - conf->gen.name, + record->name, conf->min, unitspace, unit, conf->max, unitspace, unit))); return false; } - if (!call_real_check_hook(conf, &newval->realval, newextra, + if (!call_real_check_hook(record, &newval->realval, newextra, source, elevel)) return false; } break; case PGC_STRING: { - const struct config_string *conf = (const struct config_string *) record; - /* * The value passed by the caller could be transient, so we * always strdup it. @@ -3184,12 +3112,12 @@ parse_and_validate_value(const struct config_generic *record, * The only built-in "parsing" check we have is to apply * truncation if GUC_IS_NAME. */ - if (conf->gen.flags & GUC_IS_NAME) + if (record->flags & GUC_IS_NAME) truncate_identifier(newval->stringval, strlen(newval->stringval), true); - if (!call_string_check_hook(conf, &newval->stringval, newextra, + if (!call_string_check_hook(record, &newval->stringval, newextra, source, elevel)) { guc_free(newval->stringval); @@ -3200,7 +3128,7 @@ parse_and_validate_value(const struct config_generic *record, break; case PGC_ENUM: { - const struct config_enum *conf = (const struct config_enum *) record; + const struct config_enum *conf = &record->_enum; if (!config_enum_lookup_by_name(conf, value, &newval->enumval)) { @@ -3213,7 +3141,7 @@ parse_and_validate_value(const struct config_generic *record, ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value for parameter \"%s\": \"%s\"", - conf->gen.name, value), + record->name, value), hintmsg ? errhint("%s", _(hintmsg)) : 0)); if (hintmsg) @@ -3221,7 +3149,7 @@ parse_and_validate_value(const struct config_generic *record, return false; } - if (!call_enum_check_hook(conf, &newval->enumval, newextra, + if (!call_enum_check_hook(record, &newval->enumval, newextra, source, elevel)) return false; } @@ -3639,7 +3567,7 @@ set_config_with_handle(const char *name, config_handle *handle, { case PGC_BOOL: { - struct config_bool *conf = (struct config_bool *) record; + struct config_bool *conf = &record->_bool; #define newval (newval_union.boolval) @@ -3653,23 +3581,23 @@ set_config_with_handle(const char *name, config_handle *handle, else if (source == PGC_S_DEFAULT) { newval = conf->boot_val; - if (!call_bool_check_hook(conf, &newval, &newextra, + if (!call_bool_check_hook(record, &newval, &newextra, source, elevel)) return 0; } else { newval = conf->reset_val; - newextra = conf->gen.reset_extra; - source = conf->gen.reset_source; - context = conf->gen.reset_scontext; - srole = conf->gen.reset_srole; + newextra = record->reset_extra; + source = record->reset_source; + context = record->reset_scontext; + srole = record->reset_srole; } if (prohibitValueChange) { /* Release newextra, unless it's reset_extra */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); if (*conf->variable != newval) @@ -3678,7 +3606,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - conf->gen.name))); + record->name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -3689,34 +3617,34 @@ set_config_with_handle(const char *name, config_handle *handle, { /* Save old value to support transaction abort */ if (!makeDefault) - push_old_value(&conf->gen, action); + push_old_value(record, action); if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(record, &record->extra, newextra); - set_guc_source(&conf->gen, source); - conf->gen.scontext = context; - conf->gen.srole = srole; + set_guc_source(record, source); + record->scontext = context; + record->srole = srole; } if (makeDefault) { - if (conf->gen.reset_source <= source) + if (record->reset_source <= source) { conf->reset_val = newval; - set_extra_field(&conf->gen, &conf->gen.reset_extra, + set_extra_field(record, &record->reset_extra, newextra); - conf->gen.reset_source = source; - conf->gen.reset_scontext = context; - conf->gen.reset_srole = srole; + record->reset_source = source; + record->reset_scontext = context; + record->reset_srole = srole; } - for (GucStack *stack = conf->gen.stack; stack; stack = stack->prev) + for (GucStack *stack = record->stack; stack; stack = stack->prev) { if (stack->source <= source) { stack->prior.val.boolval = newval; - set_extra_field(&conf->gen, &stack->prior.extra, + set_extra_field(record, &stack->prior.extra, newextra); stack->source = source; stack->scontext = context; @@ -3726,7 +3654,7 @@ set_config_with_handle(const char *name, config_handle *handle, } /* Perhaps we didn't install newextra anywhere */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); break; @@ -3735,7 +3663,7 @@ set_config_with_handle(const char *name, config_handle *handle, case PGC_INT: { - struct config_int *conf = (struct config_int *) record; + struct config_int *conf = &record->_int; #define newval (newval_union.intval) @@ -3749,23 +3677,23 @@ set_config_with_handle(const char *name, config_handle *handle, else if (source == PGC_S_DEFAULT) { newval = conf->boot_val; - if (!call_int_check_hook(conf, &newval, &newextra, + if (!call_int_check_hook(record, &newval, &newextra, source, elevel)) return 0; } else { newval = conf->reset_val; - newextra = conf->gen.reset_extra; - source = conf->gen.reset_source; - context = conf->gen.reset_scontext; - srole = conf->gen.reset_srole; + newextra = record->reset_extra; + source = record->reset_source; + context = record->reset_scontext; + srole = record->reset_srole; } if (prohibitValueChange) { /* Release newextra, unless it's reset_extra */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); if (*conf->variable != newval) @@ -3774,7 +3702,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - conf->gen.name))); + record->name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -3785,34 +3713,34 @@ set_config_with_handle(const char *name, config_handle *handle, { /* Save old value to support transaction abort */ if (!makeDefault) - push_old_value(&conf->gen, action); + push_old_value(record, action); if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(record, &record->extra, newextra); - set_guc_source(&conf->gen, source); - conf->gen.scontext = context; - conf->gen.srole = srole; + set_guc_source(record, source); + record->scontext = context; + record->srole = srole; } if (makeDefault) { - if (conf->gen.reset_source <= source) + if (record->reset_source <= source) { conf->reset_val = newval; - set_extra_field(&conf->gen, &conf->gen.reset_extra, + set_extra_field(record, &record->reset_extra, newextra); - conf->gen.reset_source = source; - conf->gen.reset_scontext = context; - conf->gen.reset_srole = srole; + record->reset_source = source; + record->reset_scontext = context; + record->reset_srole = srole; } - for (GucStack *stack = conf->gen.stack; stack; stack = stack->prev) + for (GucStack *stack = record->stack; stack; stack = stack->prev) { if (stack->source <= source) { stack->prior.val.intval = newval; - set_extra_field(&conf->gen, &stack->prior.extra, + set_extra_field(record, &stack->prior.extra, newextra); stack->source = source; stack->scontext = context; @@ -3822,7 +3750,7 @@ set_config_with_handle(const char *name, config_handle *handle, } /* Perhaps we didn't install newextra anywhere */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); break; @@ -3831,7 +3759,7 @@ set_config_with_handle(const char *name, config_handle *handle, case PGC_REAL: { - struct config_real *conf = (struct config_real *) record; + struct config_real *conf = &record->_real; #define newval (newval_union.realval) @@ -3845,23 +3773,23 @@ set_config_with_handle(const char *name, config_handle *handle, else if (source == PGC_S_DEFAULT) { newval = conf->boot_val; - if (!call_real_check_hook(conf, &newval, &newextra, + if (!call_real_check_hook(record, &newval, &newextra, source, elevel)) return 0; } else { newval = conf->reset_val; - newextra = conf->gen.reset_extra; - source = conf->gen.reset_source; - context = conf->gen.reset_scontext; - srole = conf->gen.reset_srole; + newextra = record->reset_extra; + source = record->reset_source; + context = record->reset_scontext; + srole = record->reset_srole; } if (prohibitValueChange) { /* Release newextra, unless it's reset_extra */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); if (*conf->variable != newval) @@ -3870,7 +3798,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - conf->gen.name))); + record->name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -3881,34 +3809,34 @@ set_config_with_handle(const char *name, config_handle *handle, { /* Save old value to support transaction abort */ if (!makeDefault) - push_old_value(&conf->gen, action); + push_old_value(record, action); if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(record, &record->extra, newextra); - set_guc_source(&conf->gen, source); - conf->gen.scontext = context; - conf->gen.srole = srole; + set_guc_source(record, source); + record->scontext = context; + record->srole = srole; } if (makeDefault) { - if (conf->gen.reset_source <= source) + if (record->reset_source <= source) { conf->reset_val = newval; - set_extra_field(&conf->gen, &conf->gen.reset_extra, + set_extra_field(record, &record->reset_extra, newextra); - conf->gen.reset_source = source; - conf->gen.reset_scontext = context; - conf->gen.reset_srole = srole; + record->reset_source = source; + record->reset_scontext = context; + record->reset_srole = srole; } - for (GucStack *stack = conf->gen.stack; stack; stack = stack->prev) + for (GucStack *stack = record->stack; stack; stack = stack->prev) { if (stack->source <= source) { stack->prior.val.realval = newval; - set_extra_field(&conf->gen, &stack->prior.extra, + set_extra_field(record, &stack->prior.extra, newextra); stack->source = source; stack->scontext = context; @@ -3918,7 +3846,7 @@ set_config_with_handle(const char *name, config_handle *handle, } /* Perhaps we didn't install newextra anywhere */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); break; @@ -3927,7 +3855,7 @@ set_config_with_handle(const char *name, config_handle *handle, case PGC_STRING: { - struct config_string *conf = (struct config_string *) record; + struct config_string *conf = &record->_string; GucContext orig_context = context; GucSource orig_source = source; Oid orig_srole = srole; @@ -3953,7 +3881,7 @@ set_config_with_handle(const char *name, config_handle *handle, else newval = NULL; - if (!call_string_check_hook(conf, &newval, &newextra, + if (!call_string_check_hook(record, &newval, &newextra, source, elevel)) { guc_free(newval); @@ -3967,10 +3895,10 @@ set_config_with_handle(const char *name, config_handle *handle, * guc.c's control */ newval = conf->reset_val; - newextra = conf->gen.reset_extra; - source = conf->gen.reset_source; - context = conf->gen.reset_scontext; - srole = conf->gen.reset_srole; + newextra = record->reset_extra; + source = record->reset_source; + context = record->reset_scontext; + srole = record->reset_srole; } if (prohibitValueChange) @@ -3983,10 +3911,10 @@ set_config_with_handle(const char *name, config_handle *handle, strcmp(*conf->variable, newval) != 0); /* Release newval, unless it's reset_val */ - if (newval && !string_field_used(conf, newval)) + if (newval && !string_field_used(record, newval)) guc_free(newval); /* Release newextra, unless it's reset_extra */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); if (newval_different) @@ -3995,7 +3923,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - conf->gen.name))); + record->name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -4006,16 +3934,16 @@ set_config_with_handle(const char *name, config_handle *handle, { /* Save old value to support transaction abort */ if (!makeDefault) - push_old_value(&conf->gen, action); + push_old_value(record, action); if (conf->assign_hook) conf->assign_hook(newval, newextra); - set_string_field(conf, conf->variable, newval); - set_extra_field(&conf->gen, &conf->gen.extra, + set_string_field(record, conf->variable, newval); + set_extra_field(record, &record->extra, newextra); - set_guc_source(&conf->gen, source); - conf->gen.scontext = context; - conf->gen.srole = srole; + set_guc_source(record, source); + record->scontext = context; + record->srole = srole; /* * Ugly hack: during SET session_authorization, forcibly @@ -4042,7 +3970,7 @@ set_config_with_handle(const char *name, config_handle *handle, * that. */ if (!is_reload && - strcmp(conf->gen.name, "session_authorization") == 0) + strcmp(record->name, "session_authorization") == 0) (void) set_config_with_handle("role", NULL, value ? "none" : NULL, orig_context, @@ -4058,22 +3986,22 @@ set_config_with_handle(const char *name, config_handle *handle, if (makeDefault) { - if (conf->gen.reset_source <= source) + if (record->reset_source <= source) { - set_string_field(conf, &conf->reset_val, newval); - set_extra_field(&conf->gen, &conf->gen.reset_extra, + set_string_field(record, &conf->reset_val, newval); + set_extra_field(record, &record->reset_extra, newextra); - conf->gen.reset_source = source; - conf->gen.reset_scontext = context; - conf->gen.reset_srole = srole; + record->reset_source = source; + record->reset_scontext = context; + record->reset_srole = srole; } - for (GucStack *stack = conf->gen.stack; stack; stack = stack->prev) + for (GucStack *stack = record->stack; stack; stack = stack->prev) { if (stack->source <= source) { - set_string_field(conf, &stack->prior.val.stringval, + set_string_field(record, &stack->prior.val.stringval, newval); - set_extra_field(&conf->gen, &stack->prior.extra, + set_extra_field(record, &stack->prior.extra, newextra); stack->source = source; stack->scontext = context; @@ -4083,10 +4011,10 @@ set_config_with_handle(const char *name, config_handle *handle, } /* Perhaps we didn't install newval anywhere */ - if (newval && !string_field_used(conf, newval)) + if (newval && !string_field_used(record, newval)) guc_free(newval); /* Perhaps we didn't install newextra anywhere */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); break; @@ -4095,7 +4023,7 @@ set_config_with_handle(const char *name, config_handle *handle, case PGC_ENUM: { - struct config_enum *conf = (struct config_enum *) record; + struct config_enum *conf = &record->_enum; #define newval (newval_union.enumval) @@ -4109,23 +4037,23 @@ set_config_with_handle(const char *name, config_handle *handle, else if (source == PGC_S_DEFAULT) { newval = conf->boot_val; - if (!call_enum_check_hook(conf, &newval, &newextra, + if (!call_enum_check_hook(record, &newval, &newextra, source, elevel)) return 0; } else { newval = conf->reset_val; - newextra = conf->gen.reset_extra; - source = conf->gen.reset_source; - context = conf->gen.reset_scontext; - srole = conf->gen.reset_srole; + newextra = record->reset_extra; + source = record->reset_source; + context = record->reset_scontext; + srole = record->reset_srole; } if (prohibitValueChange) { /* Release newextra, unless it's reset_extra */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); if (*conf->variable != newval) @@ -4134,7 +4062,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - conf->gen.name))); + record->name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -4145,34 +4073,34 @@ set_config_with_handle(const char *name, config_handle *handle, { /* Save old value to support transaction abort */ if (!makeDefault) - push_old_value(&conf->gen, action); + push_old_value(record, action); if (conf->assign_hook) conf->assign_hook(newval, newextra); *conf->variable = newval; - set_extra_field(&conf->gen, &conf->gen.extra, + set_extra_field(record, &record->extra, newextra); - set_guc_source(&conf->gen, source); - conf->gen.scontext = context; - conf->gen.srole = srole; + set_guc_source(record, source); + record->scontext = context; + record->srole = srole; } if (makeDefault) { - if (conf->gen.reset_source <= source) + if (record->reset_source <= source) { conf->reset_val = newval; - set_extra_field(&conf->gen, &conf->gen.reset_extra, + set_extra_field(record, &record->reset_extra, newextra); - conf->gen.reset_source = source; - conf->gen.reset_scontext = context; - conf->gen.reset_srole = srole; + record->reset_source = source; + record->reset_scontext = context; + record->reset_srole = srole; } - for (GucStack *stack = conf->gen.stack; stack; stack = stack->prev) + for (GucStack *stack = record->stack; stack; stack = stack->prev) { if (stack->source <= source) { stack->prior.val.enumval = newval; - set_extra_field(&conf->gen, &stack->prior.extra, + set_extra_field(record, &stack->prior.extra, newextra); stack->source = source; stack->scontext = context; @@ -4182,7 +4110,7 @@ set_config_with_handle(const char *name, config_handle *handle, } /* Perhaps we didn't install newextra anywhere */ - if (newextra && !extra_field_used(&conf->gen, newextra)) + if (newextra && !extra_field_used(record, newextra)) guc_free(newextra); break; @@ -4296,25 +4224,25 @@ GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged) switch (record->vartype) { case PGC_BOOL: - return *((struct config_bool *) record)->variable ? "on" : "off"; + return *record->_bool.variable ? "on" : "off"; case PGC_INT: snprintf(buffer, sizeof(buffer), "%d", - *((struct config_int *) record)->variable); + *record->_int.variable); return buffer; case PGC_REAL: snprintf(buffer, sizeof(buffer), "%g", - *((struct config_real *) record)->variable); + *record->_real.variable); return buffer; case PGC_STRING: - return *((struct config_string *) record)->variable ? - *((struct config_string *) record)->variable : ""; + return *record->_string.variable ? + *record->_string.variable : ""; case PGC_ENUM: - return config_enum_lookup_by_value((struct config_enum *) record, - *((struct config_enum *) record)->variable); + return config_enum_lookup_by_value(record, + *record->_enum.variable); } return NULL; } @@ -4344,25 +4272,25 @@ GetConfigOptionResetString(const char *name) switch (record->vartype) { case PGC_BOOL: - return ((struct config_bool *) record)->reset_val ? "on" : "off"; + return record->_bool.reset_val ? "on" : "off"; case PGC_INT: snprintf(buffer, sizeof(buffer), "%d", - ((struct config_int *) record)->reset_val); + record->_int.reset_val); return buffer; case PGC_REAL: snprintf(buffer, sizeof(buffer), "%g", - ((struct config_real *) record)->reset_val); + record->_real.reset_val); return buffer; case PGC_STRING: - return ((struct config_string *) record)->reset_val ? - ((struct config_string *) record)->reset_val : ""; + return record->_string.reset_val ? + record->_string.reset_val : ""; case PGC_ENUM: - return config_enum_lookup_by_value((struct config_enum *) record, - ((struct config_enum *) record)->reset_val); + return config_enum_lookup_by_value(record, + record->_enum.reset_val); } return NULL; } @@ -4802,8 +4730,7 @@ init_custom_variable(const char *name, const char *long_desc, GucContext context, int flags, - enum config_type type, - size_t sz) + enum config_type type) { struct config_generic *gen; @@ -4839,8 +4766,8 @@ init_custom_variable(const char *name, context = PGC_SUSET; /* As above, an OOM here is FATAL */ - gen = (struct config_generic *) guc_malloc(FATAL, sz); - memset(gen, 0, sz); + gen = (struct config_generic *) guc_malloc(FATAL, sizeof(struct config_generic)); + memset(gen, 0, sizeof(struct config_generic)); gen->name = guc_strdup(FATAL, name); gen->context = context; @@ -4862,7 +4789,7 @@ define_custom_variable(struct config_generic *variable) { const char *name = variable->name; GUCHashEntry *hentry; - struct config_string *pHolder; + struct config_generic *pHolder; /* Check mapping between initial and default value */ Assert(check_GUC_init(variable)); @@ -4894,7 +4821,7 @@ define_custom_variable(struct config_generic *variable) errmsg("attempt to redefine parameter \"%s\"", name))); Assert(hentry->gucvar->vartype == PGC_STRING); - pHolder = (struct config_string *) hentry->gucvar; + pHolder = hentry->gucvar; /* * First, set the variable to its default value. We must do this even @@ -4913,7 +4840,7 @@ define_custom_variable(struct config_generic *variable) /* * Remove the placeholder from any lists it's in, too. */ - RemoveGUCFromLists(&pHolder->gen); + RemoveGUCFromLists(pHolder); /* * Assign the string value(s) stored in the placeholder to the real @@ -4927,25 +4854,25 @@ define_custom_variable(struct config_generic *variable) */ /* First, apply the reset value if any */ - if (pHolder->reset_val) - (void) set_config_option_ext(name, pHolder->reset_val, - pHolder->gen.reset_scontext, - pHolder->gen.reset_source, - pHolder->gen.reset_srole, + if (pHolder->_string.reset_val) + (void) set_config_option_ext(name, pHolder->_string.reset_val, + pHolder->reset_scontext, + pHolder->reset_source, + pHolder->reset_srole, GUC_ACTION_SET, true, WARNING, false); /* That should not have resulted in stacking anything */ Assert(variable->stack == NULL); /* Now, apply current and stacked values, in the order they were stacked */ - reapply_stacked_values(variable, pHolder, pHolder->gen.stack, - *(pHolder->variable), - pHolder->gen.scontext, pHolder->gen.source, - pHolder->gen.srole); + reapply_stacked_values(variable, pHolder, pHolder->stack, + *(pHolder->_string.variable), + pHolder->scontext, pHolder->source, + pHolder->srole); /* Also copy over any saved source-location information */ - if (pHolder->gen.sourcefile) - set_config_sourcefile(name, pHolder->gen.sourcefile, - pHolder->gen.sourceline); + if (pHolder->sourcefile) + set_config_sourcefile(name, pHolder->sourcefile, + pHolder->sourceline); /* Now we can free the no-longer-referenced placeholder variable */ free_placeholder(pHolder); @@ -4960,7 +4887,7 @@ define_custom_variable(struct config_generic *variable) */ static void reapply_stacked_values(struct config_generic *variable, - struct config_string *pHolder, + struct config_generic *pHolder, GucStack *stack, const char *curvalue, GucContext curscontext, GucSource cursource, @@ -5030,10 +4957,10 @@ reapply_stacked_values(struct config_generic *variable, * this is to be just a transactional assignment. (We leak the stack * entry.) */ - if (curvalue != pHolder->reset_val || - curscontext != pHolder->gen.reset_scontext || - cursource != pHolder->gen.reset_source || - cursrole != pHolder->gen.reset_srole) + if (curvalue != pHolder->_string.reset_val || + curscontext != pHolder->reset_scontext || + cursource != pHolder->reset_source || + cursrole != pHolder->reset_srole) { (void) set_config_option_ext(name, curvalue, curscontext, cursource, cursrole, @@ -5055,14 +4982,14 @@ reapply_stacked_values(struct config_generic *variable, * doesn't seem worth spending much code on. */ static void -free_placeholder(struct config_string *pHolder) +free_placeholder(struct config_generic *pHolder) { /* Placeholders are always STRING type, so free their values */ - Assert(pHolder->gen.vartype == PGC_STRING); - set_string_field(pHolder, pHolder->variable, NULL); - set_string_field(pHolder, &pHolder->reset_val, NULL); + Assert(pHolder->vartype == PGC_STRING); + set_string_field(pHolder, pHolder->_string.variable, NULL); + set_string_field(pHolder, &pHolder->_string.reset_val, NULL); - guc_free(unconstify(char *, pHolder->gen.name)); + guc_free(unconstify(char *, pHolder->name)); guc_free(pHolder); } @@ -5081,18 +5008,16 @@ DefineCustomBoolVariable(const char *name, GucBoolAssignHook assign_hook, GucShowHook show_hook) { - struct config_bool *var; - - var = (struct config_bool *) - init_custom_variable(name, short_desc, long_desc, context, flags, - PGC_BOOL, sizeof(struct config_bool)); - var->variable = valueAddr; - var->boot_val = bootValue; - var->reset_val = bootValue; - var->check_hook = check_hook; - var->assign_hook = assign_hook; - var->show_hook = show_hook; - define_custom_variable(&var->gen); + struct config_generic *var; + + var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_BOOL); + var->_bool.variable = valueAddr; + var->_bool.boot_val = bootValue; + var->_bool.reset_val = bootValue; + var->_bool.check_hook = check_hook; + var->_bool.assign_hook = assign_hook; + var->_bool.show_hook = show_hook; + define_custom_variable(var); } void @@ -5109,20 +5034,18 @@ DefineCustomIntVariable(const char *name, GucIntAssignHook assign_hook, GucShowHook show_hook) { - struct config_int *var; - - var = (struct config_int *) - init_custom_variable(name, short_desc, long_desc, context, flags, - PGC_INT, sizeof(struct config_int)); - var->variable = valueAddr; - var->boot_val = bootValue; - var->reset_val = bootValue; - var->min = minValue; - var->max = maxValue; - var->check_hook = check_hook; - var->assign_hook = assign_hook; - var->show_hook = show_hook; - define_custom_variable(&var->gen); + struct config_generic *var; + + var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_INT); + var->_int.variable = valueAddr; + var->_int.boot_val = bootValue; + var->_int.reset_val = bootValue; + var->_int.min = minValue; + var->_int.max = maxValue; + var->_int.check_hook = check_hook; + var->_int.assign_hook = assign_hook; + var->_int.show_hook = show_hook; + define_custom_variable(var); } void @@ -5139,20 +5062,18 @@ DefineCustomRealVariable(const char *name, GucRealAssignHook assign_hook, GucShowHook show_hook) { - struct config_real *var; - - var = (struct config_real *) - init_custom_variable(name, short_desc, long_desc, context, flags, - PGC_REAL, sizeof(struct config_real)); - var->variable = valueAddr; - var->boot_val = bootValue; - var->reset_val = bootValue; - var->min = minValue; - var->max = maxValue; - var->check_hook = check_hook; - var->assign_hook = assign_hook; - var->show_hook = show_hook; - define_custom_variable(&var->gen); + struct config_generic *var; + + var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_REAL); + var->_real.variable = valueAddr; + var->_real.boot_val = bootValue; + var->_real.reset_val = bootValue; + var->_real.min = minValue; + var->_real.max = maxValue; + var->_real.check_hook = check_hook; + var->_real.assign_hook = assign_hook; + var->_real.show_hook = show_hook; + define_custom_variable(var); } void @@ -5167,17 +5088,15 @@ DefineCustomStringVariable(const char *name, GucStringAssignHook assign_hook, GucShowHook show_hook) { - struct config_string *var; - - var = (struct config_string *) - init_custom_variable(name, short_desc, long_desc, context, flags, - PGC_STRING, sizeof(struct config_string)); - var->variable = valueAddr; - var->boot_val = bootValue; - var->check_hook = check_hook; - var->assign_hook = assign_hook; - var->show_hook = show_hook; - define_custom_variable(&var->gen); + struct config_generic *var; + + var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_STRING); + var->_string.variable = valueAddr; + var->_string.boot_val = bootValue; + var->_string.check_hook = check_hook; + var->_string.assign_hook = assign_hook; + var->_string.show_hook = show_hook; + define_custom_variable(var); } void @@ -5193,19 +5112,17 @@ DefineCustomEnumVariable(const char *name, GucEnumAssignHook assign_hook, GucShowHook show_hook) { - struct config_enum *var; - - var = (struct config_enum *) - init_custom_variable(name, short_desc, long_desc, context, flags, - PGC_ENUM, sizeof(struct config_enum)); - var->variable = valueAddr; - var->boot_val = bootValue; - var->reset_val = bootValue; - var->options = options; - var->check_hook = check_hook; - var->assign_hook = assign_hook; - var->show_hook = show_hook; - define_custom_variable(&var->gen); + struct config_generic *var; + + var = init_custom_variable(name, short_desc, long_desc, context, flags, PGC_ENUM); + var->_enum.variable = valueAddr; + var->_enum.boot_val = bootValue; + var->_enum.reset_val = bootValue; + var->_enum.options = options; + var->_enum.check_hook = check_hook; + var->_enum.assign_hook = assign_hook; + var->_enum.show_hook = show_hook; + define_custom_variable(var); } /* @@ -5251,7 +5168,7 @@ MarkGUCPrefixReserved(const char *className) /* Remove it from any lists it's in, too */ RemoveGUCFromLists(var); /* And free it */ - free_placeholder((struct config_string *) var); + free_placeholder(var); } } @@ -5304,7 +5221,7 @@ get_explain_guc_options(int *num) { case PGC_BOOL: { - struct config_bool *lconf = (struct config_bool *) conf; + struct config_bool *lconf = &conf->_bool; modified = (lconf->boot_val != *(lconf->variable)); } @@ -5312,7 +5229,7 @@ get_explain_guc_options(int *num) case PGC_INT: { - struct config_int *lconf = (struct config_int *) conf; + struct config_int *lconf = &conf->_int; modified = (lconf->boot_val != *(lconf->variable)); } @@ -5320,7 +5237,7 @@ get_explain_guc_options(int *num) case PGC_REAL: { - struct config_real *lconf = (struct config_real *) conf; + struct config_real *lconf = &conf->_real; modified = (lconf->boot_val != *(lconf->variable)); } @@ -5328,7 +5245,7 @@ get_explain_guc_options(int *num) case PGC_STRING: { - struct config_string *lconf = (struct config_string *) conf; + struct config_string *lconf = &conf->_string; if (lconf->boot_val == NULL && *lconf->variable == NULL) @@ -5343,7 +5260,7 @@ get_explain_guc_options(int *num) case PGC_ENUM: { - struct config_enum *lconf = (struct config_enum *) conf; + struct config_enum *lconf = &conf->_enum; modified = (lconf->boot_val != *(lconf->variable)); } @@ -5412,7 +5329,7 @@ ShowGUCOption(const struct config_generic *record, bool use_units) { case PGC_BOOL: { - const struct config_bool *conf = (const struct config_bool *) record; + const struct config_bool *conf = &record->_bool; if (conf->show_hook) val = conf->show_hook(); @@ -5423,7 +5340,7 @@ ShowGUCOption(const struct config_generic *record, bool use_units) case PGC_INT: { - const struct config_int *conf = (const struct config_int *) record; + const struct config_int *conf = &record->_int; if (conf->show_hook) val = conf->show_hook(); @@ -5452,7 +5369,7 @@ ShowGUCOption(const struct config_generic *record, bool use_units) case PGC_REAL: { - const struct config_real *conf = (const struct config_real *) record; + const struct config_real *conf = &record->_real; if (conf->show_hook) val = conf->show_hook(); @@ -5477,7 +5394,7 @@ ShowGUCOption(const struct config_generic *record, bool use_units) case PGC_STRING: { - const struct config_string *conf = (const struct config_string *) record; + const struct config_string *conf = &record->_string; if (conf->show_hook) val = conf->show_hook(); @@ -5490,12 +5407,12 @@ ShowGUCOption(const struct config_generic *record, bool use_units) case PGC_ENUM: { - const struct config_enum *conf = (const struct config_enum *) record; + const struct config_enum *conf = &record->_enum; if (conf->show_hook) val = conf->show_hook(); else - val = config_enum_lookup_by_value(conf, *conf->variable); + val = config_enum_lookup_by_value(record, *conf->variable); } break; @@ -5535,7 +5452,7 @@ write_one_nondefault_variable(FILE *fp, struct config_generic *gconf) { case PGC_BOOL: { - struct config_bool *conf = (struct config_bool *) gconf; + struct config_bool *conf = &gconf->_bool; if (*conf->variable) fprintf(fp, "true"); @@ -5546,7 +5463,7 @@ write_one_nondefault_variable(FILE *fp, struct config_generic *gconf) case PGC_INT: { - struct config_int *conf = (struct config_int *) gconf; + struct config_int *conf = &gconf->_int; fprintf(fp, "%d", *conf->variable); } @@ -5554,7 +5471,7 @@ write_one_nondefault_variable(FILE *fp, struct config_generic *gconf) case PGC_REAL: { - struct config_real *conf = (struct config_real *) gconf; + struct config_real *conf = &gconf->_real; fprintf(fp, "%.17g", *conf->variable); } @@ -5562,7 +5479,7 @@ write_one_nondefault_variable(FILE *fp, struct config_generic *gconf) case PGC_STRING: { - struct config_string *conf = (struct config_string *) gconf; + struct config_string *conf = &gconf->_string; if (*conf->variable) fprintf(fp, "%s", *conf->variable); @@ -5571,10 +5488,10 @@ write_one_nondefault_variable(FILE *fp, struct config_generic *gconf) case PGC_ENUM: { - struct config_enum *conf = (struct config_enum *) gconf; + struct config_enum *conf = &gconf->_enum; fprintf(fp, "%s", - config_enum_lookup_by_value(conf, *conf->variable)); + config_enum_lookup_by_value(gconf, *conf->variable)); } break; } @@ -5809,7 +5726,7 @@ estimate_variable_size(struct config_generic *gconf) case PGC_INT: { - struct config_int *conf = (struct config_int *) gconf; + struct config_int *conf = &gconf->_int; /* * Instead of getting the exact display length, use max @@ -5838,7 +5755,7 @@ estimate_variable_size(struct config_generic *gconf) case PGC_STRING: { - struct config_string *conf = (struct config_string *) gconf; + struct config_string *conf = &gconf->_string; /* * If the value is NULL, we transmit it as an empty string. @@ -5854,9 +5771,9 @@ estimate_variable_size(struct config_generic *gconf) case PGC_ENUM: { - struct config_enum *conf = (struct config_enum *) gconf; + struct config_enum *conf = &gconf->_enum; - valsize = strlen(config_enum_lookup_by_value(conf, *conf->variable)); + valsize = strlen(config_enum_lookup_by_value(gconf, *conf->variable)); } break; } @@ -5975,7 +5892,7 @@ serialize_variable(char **destptr, Size *maxbytes, { case PGC_BOOL: { - struct config_bool *conf = (struct config_bool *) gconf; + struct config_bool *conf = &gconf->_bool; do_serialize(destptr, maxbytes, (*conf->variable ? "true" : "false")); @@ -5984,7 +5901,7 @@ serialize_variable(char **destptr, Size *maxbytes, case PGC_INT: { - struct config_int *conf = (struct config_int *) gconf; + struct config_int *conf = &gconf->_int; do_serialize(destptr, maxbytes, "%d", *conf->variable); } @@ -5992,7 +5909,7 @@ serialize_variable(char **destptr, Size *maxbytes, case PGC_REAL: { - struct config_real *conf = (struct config_real *) gconf; + struct config_real *conf = &gconf->_real; do_serialize(destptr, maxbytes, "%.*e", REALTYPE_PRECISION, *conf->variable); @@ -6001,7 +5918,7 @@ serialize_variable(char **destptr, Size *maxbytes, case PGC_STRING: { - struct config_string *conf = (struct config_string *) gconf; + struct config_string *conf = &gconf->_string; /* NULL becomes empty string, see estimate_variable_size() */ do_serialize(destptr, maxbytes, "%s", @@ -6011,10 +5928,10 @@ serialize_variable(char **destptr, Size *maxbytes, case PGC_ENUM: { - struct config_enum *conf = (struct config_enum *) gconf; + struct config_enum *conf = &gconf->_enum; do_serialize(destptr, maxbytes, "%s", - config_enum_lookup_by_value(conf, *conf->variable)); + config_enum_lookup_by_value(gconf, *conf->variable)); } break; } @@ -6199,7 +6116,7 @@ RestoreGUCState(void *gucstate) break; case PGC_STRING: { - struct config_string *conf = (struct config_string *) gconf; + struct config_string *conf = &gconf->_string; guc_free(*conf->variable); if (conf->reset_val && conf->reset_val != *conf->variable) @@ -6710,11 +6627,11 @@ GUC_check_errcode(int sqlerrcode) */ static bool -call_bool_check_hook(const struct config_bool *conf, bool *newval, void **extra, +call_bool_check_hook(const struct config_generic *conf, bool *newval, void **extra, GucSource source, int elevel) { /* Quick success if no hook */ - if (!conf->check_hook) + if (!conf->_bool.check_hook) return true; /* Reset variables that might be set by hook */ @@ -6723,14 +6640,14 @@ call_bool_check_hook(const struct config_bool *conf, bool *newval, void **extra, GUC_check_errdetail_string = NULL; GUC_check_errhint_string = NULL; - if (!conf->check_hook(newval, extra, source)) + if (!conf->_bool.check_hook(newval, extra, source)) { ereport(elevel, (errcode(GUC_check_errcode_value), GUC_check_errmsg_string ? errmsg_internal("%s", GUC_check_errmsg_string) : errmsg("invalid value for parameter \"%s\": %d", - conf->gen.name, (int) *newval), + conf->name, (int) *newval), GUC_check_errdetail_string ? errdetail_internal("%s", GUC_check_errdetail_string) : 0, GUC_check_errhint_string ? @@ -6744,11 +6661,11 @@ call_bool_check_hook(const struct config_bool *conf, bool *newval, void **extra, } static bool -call_int_check_hook(const struct config_int *conf, int *newval, void **extra, +call_int_check_hook(const struct config_generic *conf, int *newval, void **extra, GucSource source, int elevel) { /* Quick success if no hook */ - if (!conf->check_hook) + if (!conf->_int.check_hook) return true; /* Reset variables that might be set by hook */ @@ -6757,14 +6674,14 @@ call_int_check_hook(const struct config_int *conf, int *newval, void **extra, GUC_check_errdetail_string = NULL; GUC_check_errhint_string = NULL; - if (!conf->check_hook(newval, extra, source)) + if (!conf->_int.check_hook(newval, extra, source)) { ereport(elevel, (errcode(GUC_check_errcode_value), GUC_check_errmsg_string ? errmsg_internal("%s", GUC_check_errmsg_string) : errmsg("invalid value for parameter \"%s\": %d", - conf->gen.name, *newval), + conf->name, *newval), GUC_check_errdetail_string ? errdetail_internal("%s", GUC_check_errdetail_string) : 0, GUC_check_errhint_string ? @@ -6778,11 +6695,11 @@ call_int_check_hook(const struct config_int *conf, int *newval, void **extra, } static bool -call_real_check_hook(const struct config_real *conf, double *newval, void **extra, +call_real_check_hook(const struct config_generic *conf, double *newval, void **extra, GucSource source, int elevel) { /* Quick success if no hook */ - if (!conf->check_hook) + if (!conf->_real.check_hook) return true; /* Reset variables that might be set by hook */ @@ -6791,14 +6708,14 @@ call_real_check_hook(const struct config_real *conf, double *newval, void **extr GUC_check_errdetail_string = NULL; GUC_check_errhint_string = NULL; - if (!conf->check_hook(newval, extra, source)) + if (!conf->_real.check_hook(newval, extra, source)) { ereport(elevel, (errcode(GUC_check_errcode_value), GUC_check_errmsg_string ? errmsg_internal("%s", GUC_check_errmsg_string) : errmsg("invalid value for parameter \"%s\": %g", - conf->gen.name, *newval), + conf->name, *newval), GUC_check_errdetail_string ? errdetail_internal("%s", GUC_check_errdetail_string) : 0, GUC_check_errhint_string ? @@ -6812,13 +6729,13 @@ call_real_check_hook(const struct config_real *conf, double *newval, void **extr } static bool -call_string_check_hook(const struct config_string *conf, char **newval, void **extra, +call_string_check_hook(const struct config_generic *conf, char **newval, void **extra, GucSource source, int elevel) { volatile bool result = true; /* Quick success if no hook */ - if (!conf->check_hook) + if (!conf->_string.check_hook) return true; /* @@ -6834,14 +6751,14 @@ call_string_check_hook(const struct config_string *conf, char **newval, void **e GUC_check_errdetail_string = NULL; GUC_check_errhint_string = NULL; - if (!conf->check_hook(newval, extra, source)) + if (!conf->_string.check_hook(newval, extra, source)) { ereport(elevel, (errcode(GUC_check_errcode_value), GUC_check_errmsg_string ? errmsg_internal("%s", GUC_check_errmsg_string) : errmsg("invalid value for parameter \"%s\": \"%s\"", - conf->gen.name, *newval ? *newval : ""), + conf->name, *newval ? *newval : ""), GUC_check_errdetail_string ? errdetail_internal("%s", GUC_check_errdetail_string) : 0, GUC_check_errhint_string ? @@ -6862,11 +6779,11 @@ call_string_check_hook(const struct config_string *conf, char **newval, void **e } static bool -call_enum_check_hook(const struct config_enum *conf, int *newval, void **extra, +call_enum_check_hook(const struct config_generic *conf, int *newval, void **extra, GucSource source, int elevel) { /* Quick success if no hook */ - if (!conf->check_hook) + if (!conf->_enum.check_hook) return true; /* Reset variables that might be set by hook */ @@ -6875,14 +6792,14 @@ call_enum_check_hook(const struct config_enum *conf, int *newval, void **extra, GUC_check_errdetail_string = NULL; GUC_check_errhint_string = NULL; - if (!conf->check_hook(newval, extra, source)) + if (!conf->_enum.check_hook(newval, extra, source)) { ereport(elevel, (errcode(GUC_check_errcode_value), GUC_check_errmsg_string ? errmsg_internal("%s", GUC_check_errmsg_string) : errmsg("invalid value for parameter \"%s\": \"%s\"", - conf->gen.name, + conf->name, config_enum_lookup_by_value(conf, *newval)), GUC_check_errdetail_string ? errdetail_internal("%s", GUC_check_errdetail_string) : 0, diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c index d7a822e1462..4f58fa3d4e0 100644 --- a/src/backend/utils/misc/guc_funcs.c +++ b/src/backend/utils/misc/guc_funcs.c @@ -629,7 +629,7 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) { case PGC_BOOL: { - const struct config_bool *lconf = (const struct config_bool *) conf; + const struct config_bool *lconf = &conf->_bool; /* min_val */ values[9] = NULL; @@ -650,7 +650,7 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) case PGC_INT: { - const struct config_int *lconf = (const struct config_int *) conf; + const struct config_int *lconf = &conf->_int; /* min_val */ snprintf(buffer, sizeof(buffer), "%d", lconf->min); @@ -675,7 +675,7 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) case PGC_REAL: { - const struct config_real *lconf = (const struct config_real *) conf; + const struct config_real *lconf = &conf->_real; /* min_val */ snprintf(buffer, sizeof(buffer), "%g", lconf->min); @@ -700,7 +700,7 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) case PGC_STRING: { - const struct config_string *lconf = (const struct config_string *) conf; + const struct config_string *lconf = &conf->_string; /* min_val */ values[9] = NULL; @@ -727,7 +727,7 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) case PGC_ENUM: { - const struct config_enum *lconf = (const struct config_enum *) conf; + const struct config_enum *lconf = &conf->_enum; /* min_val */ values[9] = NULL; @@ -745,11 +745,11 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) "{\"", "\"}", "\",\""); /* boot_val */ - values[12] = pstrdup(config_enum_lookup_by_value(lconf, + values[12] = pstrdup(config_enum_lookup_by_value(conf, lconf->boot_val)); /* reset_val */ - values[13] = pstrdup(config_enum_lookup_by_value(lconf, + values[13] = pstrdup(config_enum_lookup_by_value(conf, lconf->reset_val)); } break; diff --git a/src/backend/utils/misc/help_config.c b/src/backend/utils/misc/help_config.c index 86812ac881f..2810715693c 100644 --- a/src/backend/utils/misc/help_config.c +++ b/src/backend/utils/misc/help_config.c @@ -23,23 +23,8 @@ #include "utils/help_config.h" -/* - * This union allows us to mix the numerous different types of structs - * that we are organizing. - */ -typedef union -{ - struct config_generic generic; - struct config_bool _bool; - struct config_real real; - struct config_int integer; - struct config_string string; - struct config_enum _enum; -} mixedStruct; - - -static void printMixedStruct(mixedStruct *structToPrint); -static bool displayStruct(mixedStruct *structToDisplay); +static void printMixedStruct(const struct config_generic *structToPrint); +static bool displayStruct(const struct config_generic *structToDisplay); void @@ -55,7 +40,7 @@ GucInfoMain(void) for (int i = 0; i < numOpts; i++) { - mixedStruct *var = (mixedStruct *) guc_vars[i]; + const struct config_generic *var = guc_vars[i]; if (displayStruct(var)) printMixedStruct(var); @@ -70,11 +55,11 @@ GucInfoMain(void) * should be displayed to the user. */ static bool -displayStruct(mixedStruct *structToDisplay) +displayStruct(const struct config_generic *structToDisplay) { - return !(structToDisplay->generic.flags & (GUC_NO_SHOW_ALL | - GUC_NOT_IN_SAMPLE | - GUC_DISALLOW_IN_FILE)); + return !(structToDisplay->flags & (GUC_NO_SHOW_ALL | + GUC_NOT_IN_SAMPLE | + GUC_DISALLOW_IN_FILE)); } @@ -83,14 +68,14 @@ displayStruct(mixedStruct *structToDisplay) * a different format, depending on what the user wants to see. */ static void -printMixedStruct(mixedStruct *structToPrint) +printMixedStruct(const struct config_generic *structToPrint) { printf("%s\t%s\t%s\t", - structToPrint->generic.name, - GucContext_Names[structToPrint->generic.context], - _(config_group_names[structToPrint->generic.group])); + structToPrint->name, + GucContext_Names[structToPrint->context], + _(config_group_names[structToPrint->group])); - switch (structToPrint->generic.vartype) + switch (structToPrint->vartype) { case PGC_BOOL: @@ -101,26 +86,26 @@ printMixedStruct(mixedStruct *structToPrint) case PGC_INT: printf("INTEGER\t%d\t%d\t%d\t", - structToPrint->integer.reset_val, - structToPrint->integer.min, - structToPrint->integer.max); + structToPrint->_int.reset_val, + structToPrint->_int.min, + structToPrint->_int.max); break; case PGC_REAL: printf("REAL\t%g\t%g\t%g\t", - structToPrint->real.reset_val, - structToPrint->real.min, - structToPrint->real.max); + structToPrint->_real.reset_val, + structToPrint->_real.min, + structToPrint->_real.max); break; case PGC_STRING: printf("STRING\t%s\t\t\t", - structToPrint->string.boot_val ? structToPrint->string.boot_val : ""); + structToPrint->_string.boot_val ? structToPrint->_string.boot_val : ""); break; case PGC_ENUM: printf("ENUM\t%s\t\t\t", - config_enum_lookup_by_value(&structToPrint->_enum, + config_enum_lookup_by_value(structToPrint, structToPrint->_enum.boot_val)); break; @@ -130,6 +115,6 @@ printMixedStruct(mixedStruct *structToPrint) } printf("%s\t%s\n", - (structToPrint->generic.short_desc == NULL) ? "" : _(structToPrint->generic.short_desc), - (structToPrint->generic.long_desc == NULL) ? "" : _(structToPrint->generic.long_desc)); + (structToPrint->short_desc == NULL) ? "" : _(structToPrint->short_desc), + (structToPrint->long_desc == NULL) ? "" : _(structToPrint->long_desc)); } diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c index 5e6c13bb921..8d5befa947f 100644 --- a/src/bin/pg_verifybackup/pg_verifybackup.c +++ b/src/bin/pg_verifybackup/pg_verifybackup.c @@ -1228,7 +1228,7 @@ parse_required_wal(verifier_context *context, char *pg_waldump_path, * context says we should. */ void -report_backup_error(verifier_context *context, const char *pg_restrict fmt,...) +report_backup_error(verifier_context *context, const char *restrict fmt,...) { va_list ap; @@ -1245,7 +1245,7 @@ report_backup_error(verifier_context *context, const char *pg_restrict fmt,...) * Report a fatal error and exit */ void -report_fatal_error(const char *pg_restrict fmt,...) +report_fatal_error(const char *restrict fmt,...) { va_list ap; diff --git a/src/bin/pg_verifybackup/pg_verifybackup.h b/src/bin/pg_verifybackup/pg_verifybackup.h index 8cb6f9c53ad..3bdae62b822 100644 --- a/src/bin/pg_verifybackup/pg_verifybackup.h +++ b/src/bin/pg_verifybackup/pg_verifybackup.h @@ -96,9 +96,9 @@ typedef struct verifier_context } verifier_context; extern void report_backup_error(verifier_context *context, - const char *pg_restrict fmt,...) + const char *restrict fmt,...) pg_attribute_printf(2, 3); -pg_noreturn extern void report_fatal_error(const char *pg_restrict fmt,...) +pg_noreturn extern void report_fatal_error(const char *restrict fmt,...) pg_attribute_printf(1, 2); extern bool should_ignore_relpath(verifier_context *context, const char *relpath); diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c index b08d7328fbf..59a2ceee07a 100644 --- a/src/bin/psql/prompt.c +++ b/src/bin/psql/prompt.c @@ -34,6 +34,7 @@ * %P - pipeline status: on, off or abort * %> - database server port number * %n - database user name + * %S - search_path * %s - service * %/ - current database * %~ - like %/ but "~" when database name equals user name @@ -167,6 +168,16 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) if (pset.db) strlcpy(buf, session_username(), sizeof(buf)); break; + /* search_path */ + case 'S': + if (pset.db) + { + const char *sp = PQparameterStatus(pset.db, "search_path"); + + /* Use ? for versions that don't report search_path. */ + strlcpy(buf, sp ? sp : "?", sizeof(buf)); + } + break; /* service name */ case 's': { diff --git a/src/common/logging.c b/src/common/logging.c index 125a172af80..7319a5b4e20 100644 --- a/src/common/logging.c +++ b/src/common/logging.c @@ -206,7 +206,7 @@ pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno) void pg_log_generic(enum pg_log_level level, enum pg_log_part part, - const char *pg_restrict fmt,...) + const char *restrict fmt,...) { va_list ap; @@ -217,7 +217,7 @@ pg_log_generic(enum pg_log_level level, enum pg_log_part part, void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, - const char *pg_restrict fmt, va_list ap) + const char *restrict fmt, va_list ap) { int save_errno = errno; const char *filename = NULL; diff --git a/src/common/saslprep.c b/src/common/saslprep.c index 97beb47940b..101e8d65a4d 100644 --- a/src/common/saslprep.c +++ b/src/common/saslprep.c @@ -47,7 +47,7 @@ /* Prototypes for local functions */ static int codepoint_range_cmp(const void *a, const void *b); -static bool is_code_in_table(pg_wchar code, const pg_wchar *map, int mapsize); +static bool is_code_in_table(char32_t code, const char32_t *map, int mapsize); static int pg_utf8_string_len(const char *source); /* @@ -64,7 +64,7 @@ static int pg_utf8_string_len(const char *source); * * These are all mapped to the ASCII space character (U+00A0). */ -static const pg_wchar non_ascii_space_ranges[] = +static const char32_t non_ascii_space_ranges[] = { 0x00A0, 0x00A0, 0x1680, 0x1680, @@ -79,7 +79,7 @@ static const pg_wchar non_ascii_space_ranges[] = * * If any of these appear in the input, they are removed. */ -static const pg_wchar commonly_mapped_to_nothing_ranges[] = +static const char32_t commonly_mapped_to_nothing_ranges[] = { 0x00AD, 0x00AD, 0x034F, 0x034F, @@ -114,7 +114,7 @@ static const pg_wchar commonly_mapped_to_nothing_ranges[] = * tables, so one code might originate from multiple source tables. * Adjacent ranges have also been merged together, to save space. */ -static const pg_wchar prohibited_output_ranges[] = +static const char32_t prohibited_output_ranges[] = { 0x0000, 0x001F, /* C.2.1 */ 0x007F, 0x00A0, /* C.1.2, C.2.1, C.2.2 */ @@ -155,7 +155,7 @@ static const pg_wchar prohibited_output_ranges[] = }; /* A.1 Unassigned code points in Unicode 3.2 */ -static const pg_wchar unassigned_codepoint_ranges[] = +static const char32_t unassigned_codepoint_ranges[] = { 0x0221, 0x0221, 0x0234, 0x024F, @@ -556,7 +556,7 @@ static const pg_wchar unassigned_codepoint_ranges[] = }; /* D.1 Characters with bidirectional property "R" or "AL" */ -static const pg_wchar RandALCat_codepoint_ranges[] = +static const char32_t RandALCat_codepoint_ranges[] = { 0x05BE, 0x05BE, 0x05C0, 0x05C0, @@ -595,7 +595,7 @@ static const pg_wchar RandALCat_codepoint_ranges[] = }; /* D.2 Characters with bidirectional property "L" */ -static const pg_wchar LCat_codepoint_ranges[] = +static const char32_t LCat_codepoint_ranges[] = { 0x0041, 0x005A, 0x0061, 0x007A, @@ -968,8 +968,8 @@ static const pg_wchar LCat_codepoint_ranges[] = static int codepoint_range_cmp(const void *a, const void *b) { - const pg_wchar *key = (const pg_wchar *) a; - const pg_wchar *range = (const pg_wchar *) b; + const char32_t *key = (const char32_t *) a; + const char32_t *range = (const char32_t *) b; if (*key < range[0]) return -1; /* less than lower bound */ @@ -980,14 +980,14 @@ codepoint_range_cmp(const void *a, const void *b) } static bool -is_code_in_table(pg_wchar code, const pg_wchar *map, int mapsize) +is_code_in_table(char32_t code, const char32_t *map, int mapsize) { Assert(mapsize % 2 == 0); if (code < map[0] || code > map[mapsize - 1]) return false; - if (bsearch(&code, map, mapsize / 2, sizeof(pg_wchar) * 2, + if (bsearch(&code, map, mapsize / 2, sizeof(char32_t) * 2, codepoint_range_cmp)) return true; else @@ -1046,8 +1046,8 @@ pg_utf8_string_len(const char *source) pg_saslprep_rc pg_saslprep(const char *input, char **output) { - pg_wchar *input_chars = NULL; - pg_wchar *output_chars = NULL; + char32_t *input_chars = NULL; + char32_t *output_chars = NULL; int input_size; char *result; int result_size; @@ -1055,7 +1055,7 @@ pg_saslprep(const char *input, char **output) int i; bool contains_RandALCat; unsigned char *p; - pg_wchar *wp; + char32_t *wp; /* Ensure we return *output as NULL on failure */ *output = NULL; @@ -1080,10 +1080,10 @@ pg_saslprep(const char *input, char **output) input_size = pg_utf8_string_len(input); if (input_size < 0) return SASLPREP_INVALID_UTF8; - if (input_size >= MaxAllocSize / sizeof(pg_wchar)) + if (input_size >= MaxAllocSize / sizeof(char32_t)) goto oom; - input_chars = ALLOC((input_size + 1) * sizeof(pg_wchar)); + input_chars = ALLOC((input_size + 1) * sizeof(char32_t)); if (!input_chars) goto oom; @@ -1093,7 +1093,7 @@ pg_saslprep(const char *input, char **output) input_chars[i] = utf8_to_unicode(p); p += pg_utf_mblen(p); } - input_chars[i] = (pg_wchar) '\0'; + input_chars[i] = (char32_t) '\0'; /* * The steps below correspond to the steps listed in [RFC3454], Section @@ -1107,7 +1107,7 @@ pg_saslprep(const char *input, char **output) count = 0; for (i = 0; i < input_size; i++) { - pg_wchar code = input_chars[i]; + char32_t code = input_chars[i]; if (IS_CODE_IN_TABLE(code, non_ascii_space_ranges)) input_chars[count++] = 0x0020; @@ -1118,7 +1118,7 @@ pg_saslprep(const char *input, char **output) else input_chars[count++] = code; } - input_chars[count] = (pg_wchar) '\0'; + input_chars[count] = (char32_t) '\0'; input_size = count; if (input_size == 0) @@ -1138,7 +1138,7 @@ pg_saslprep(const char *input, char **output) */ for (i = 0; i < input_size; i++) { - pg_wchar code = input_chars[i]; + char32_t code = input_chars[i]; if (IS_CODE_IN_TABLE(code, prohibited_output_ranges)) goto prohibited; @@ -1170,7 +1170,7 @@ pg_saslprep(const char *input, char **output) contains_RandALCat = false; for (i = 0; i < input_size; i++) { - pg_wchar code = input_chars[i]; + char32_t code = input_chars[i]; if (IS_CODE_IN_TABLE(code, RandALCat_codepoint_ranges)) { @@ -1181,12 +1181,12 @@ pg_saslprep(const char *input, char **output) if (contains_RandALCat) { - pg_wchar first = input_chars[0]; - pg_wchar last = input_chars[input_size - 1]; + char32_t first = input_chars[0]; + char32_t last = input_chars[input_size - 1]; for (i = 0; i < input_size; i++) { - pg_wchar code = input_chars[i]; + char32_t code = input_chars[i]; if (IS_CODE_IN_TABLE(code, LCat_codepoint_ranges)) goto prohibited; diff --git a/src/common/string.c b/src/common/string.c index d8a3129c3ba..95c7c07d502 100644 --- a/src/common/string.c +++ b/src/common/string.c @@ -47,7 +47,7 @@ pg_str_endswith(const char *str, const char *end) * strtoint --- just like strtol, but returns int not long */ int -strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base) +strtoint(const char *restrict str, char **restrict endptr, int base) { long val; diff --git a/src/common/unicode/case_test.c b/src/common/unicode/case_test.c index fdfb62e8552..00d4f85e5a5 100644 --- a/src/common/unicode/case_test.c +++ b/src/common/unicode/case_test.c @@ -24,6 +24,7 @@ #include "common/unicode_case.h" #include "common/unicode_category.h" #include "common/unicode_version.h" +#include "mb/pg_wchar.h" /* enough to hold largest source or result string, including NUL */ #define BUFSZ 256 @@ -54,7 +55,7 @@ initcap_wbnext(void *state) while (wbstate->offset < wbstate->len && wbstate->str[wbstate->offset] != '\0') { - pg_wchar u = utf8_to_unicode((unsigned char *) wbstate->str + + char32_t u = utf8_to_unicode((unsigned char *) wbstate->str + wbstate->offset); bool curr_alnum = pg_u_isalnum(u, wbstate->posix); @@ -77,16 +78,16 @@ initcap_wbnext(void *state) #ifdef USE_ICU static void -icu_test_simple(pg_wchar code) +icu_test_simple(char32_t code) { - pg_wchar lower = unicode_lowercase_simple(code); - pg_wchar title = unicode_titlecase_simple(code); - pg_wchar upper = unicode_uppercase_simple(code); - pg_wchar fold = unicode_casefold_simple(code); - pg_wchar iculower = u_tolower(code); - pg_wchar icutitle = u_totitle(code); - pg_wchar icuupper = u_toupper(code); - pg_wchar icufold = u_foldCase(code, U_FOLD_CASE_DEFAULT); + char32_t lower = unicode_lowercase_simple(code); + char32_t title = unicode_titlecase_simple(code); + char32_t upper = unicode_uppercase_simple(code); + char32_t fold = unicode_casefold_simple(code); + char32_t iculower = u_tolower(code); + char32_t icutitle = u_totitle(code); + char32_t icuupper = u_toupper(code); + char32_t icufold = u_foldCase(code, U_FOLD_CASE_DEFAULT); if (lower != iculower || title != icutitle || upper != icuupper || fold != icufold) @@ -172,7 +173,7 @@ test_icu(void) int successful = 0; int skipped_mismatch = 0; - for (pg_wchar code = 0; code <= 0x10ffff; code++) + for (char32_t code = 0; code <= 0x10ffff; code++) { pg_unicode_category category = unicode_category(code); diff --git a/src/common/unicode/category_test.c b/src/common/unicode/category_test.c index 5d37ba39196..1e8c1f7905f 100644 --- a/src/common/unicode/category_test.c +++ b/src/common/unicode/category_test.c @@ -22,6 +22,7 @@ #include "common/unicode_category.h" #include "common/unicode_version.h" +#include "mb/pg_wchar.h" static int pg_unicode_version = 0; #ifdef USE_ICU @@ -59,7 +60,7 @@ icu_test() int pg_skipped_codepoints = 0; int icu_skipped_codepoints = 0; - for (pg_wchar code = 0; code <= 0x10ffff; code++) + for (char32_t code = 0; code <= 0x10ffff; code++) { uint8_t pg_category = unicode_category(code); uint8_t icu_category = u_charType(code); diff --git a/src/common/unicode/generate-norm_test_table.pl b/src/common/unicode/generate-norm_test_table.pl index 1b401be9409..1a8b908ff33 100644 --- a/src/common/unicode/generate-norm_test_table.pl +++ b/src/common/unicode/generate-norm_test_table.pl @@ -47,8 +47,8 @@ print $OUTPUT <<HEADER; typedef struct { int linenum; - pg_wchar input[50]; - pg_wchar output[4][50]; + char32_t input[50]; + char32_t output[4][50]; } pg_unicode_test; /* test table */ diff --git a/src/common/unicode/generate-unicode_case_table.pl b/src/common/unicode/generate-unicode_case_table.pl index 5d9ddd62803..f71eb25c94e 100644 --- a/src/common/unicode/generate-unicode_case_table.pl +++ b/src/common/unicode/generate-unicode_case_table.pl @@ -270,7 +270,6 @@ print $OT <<"EOS"; */ #include "common/unicode_case.h" -#include "mb/pg_wchar.h" /* * The maximum number of codepoints that can result from case mapping @@ -297,7 +296,7 @@ typedef enum typedef struct { int16 conditions; - pg_wchar map[NCaseKind][MAX_CASE_EXPANSION]; + char32_t map[NCaseKind][MAX_CASE_EXPANSION]; } pg_special_case; /* @@ -430,7 +429,7 @@ foreach my $kind ('lower', 'title', 'upper', 'fold') * The entry case_map_${kind}[case_index(codepoint)] is the mapping for the * given codepoint. */ -static const pg_wchar case_map_$kind\[$index\] = +static const char32_t case_map_$kind\[$index\] = { EOS @@ -502,7 +501,7 @@ print $OT <<"EOS"; * the offset into the mapping tables. */ static inline uint16 -case_index(pg_wchar cp) +case_index(char32_t cp) { /* Fast path for codepoints < $fastpath_limit */ if (cp < $fastpath_limit) diff --git a/src/common/unicode/generate-unicode_category_table.pl b/src/common/unicode/generate-unicode_category_table.pl index abab5cd9696..7e094b13720 100644 --- a/src/common/unicode/generate-unicode_category_table.pl +++ b/src/common/unicode/generate-unicode_category_table.pl @@ -366,15 +366,15 @@ print $OT <<"EOS"; */ typedef struct { - uint32 first; /* Unicode codepoint */ - uint32 last; /* Unicode codepoint */ + char32_t first; /* Unicode codepoint */ + char32_t last; /* Unicode codepoint */ uint8 category; /* General Category */ } pg_category_range; typedef struct { - uint32 first; /* Unicode codepoint */ - uint32 last; /* Unicode codepoint */ + char32_t first; /* Unicode codepoint */ + char32_t last; /* Unicode codepoint */ } pg_unicode_range; typedef struct diff --git a/src/common/unicode/norm_test.c b/src/common/unicode/norm_test.c index 25bc59463f2..058817f1719 100644 --- a/src/common/unicode/norm_test.c +++ b/src/common/unicode/norm_test.c @@ -20,7 +20,7 @@ #include "norm_test_table.h" static char * -print_wchar_str(const pg_wchar *s) +print_wchar_str(const char32_t *s) { #define BUF_DIGITS 50 static char buf[BUF_DIGITS * 11 + 1]; @@ -41,7 +41,7 @@ print_wchar_str(const pg_wchar *s) } static int -pg_wcscmp(const pg_wchar *s1, const pg_wchar *s2) +pg_wcscmp(const char32_t *s1, const char32_t *s2) { for (;;) { @@ -65,7 +65,7 @@ main(int argc, char **argv) { for (int form = 0; form < 4; form++) { - pg_wchar *result; + char32_t *result; result = unicode_normalize(form, test->input); diff --git a/src/common/unicode_case.c b/src/common/unicode_case.c index 073faf6a0d5..e5e494db43c 100644 --- a/src/common/unicode_case.c +++ b/src/common/unicode_case.c @@ -30,7 +30,7 @@ enum CaseMapResult /* * Map for each case kind. */ -static const pg_wchar *const casekind_map[NCaseKind] = +static const char32_t *const casekind_map[NCaseKind] = { [CaseLower] = case_map_lower, [CaseTitle] = case_map_title, @@ -38,42 +38,42 @@ static const pg_wchar *const casekind_map[NCaseKind] = [CaseFold] = case_map_fold, }; -static pg_wchar find_case_map(pg_wchar ucs, const pg_wchar *map); +static char32_t find_case_map(char32_t ucs, const char32_t *map); static size_t convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, CaseKind str_casekind, bool full, WordBoundaryNext wbnext, void *wbstate); -static enum CaseMapResult casemap(pg_wchar u1, CaseKind casekind, bool full, +static enum CaseMapResult casemap(char32_t u1, CaseKind casekind, bool full, const char *src, size_t srclen, size_t srcoff, - pg_wchar *simple, const pg_wchar **special); + char32_t *simple, const char32_t **special); -pg_wchar -unicode_lowercase_simple(pg_wchar code) +char32_t +unicode_lowercase_simple(char32_t code) { - pg_wchar cp = find_case_map(code, case_map_lower); + char32_t cp = find_case_map(code, case_map_lower); return cp != 0 ? cp : code; } -pg_wchar -unicode_titlecase_simple(pg_wchar code) +char32_t +unicode_titlecase_simple(char32_t code) { - pg_wchar cp = find_case_map(code, case_map_title); + char32_t cp = find_case_map(code, case_map_title); return cp != 0 ? cp : code; } -pg_wchar -unicode_uppercase_simple(pg_wchar code) +char32_t +unicode_uppercase_simple(char32_t code) { - pg_wchar cp = find_case_map(code, case_map_upper); + char32_t cp = find_case_map(code, case_map_upper); return cp != 0 ? cp : code; } -pg_wchar -unicode_casefold_simple(pg_wchar code) +char32_t +unicode_casefold_simple(char32_t code) { - pg_wchar cp = find_case_map(code, case_map_fold); + char32_t cp = find_case_map(code, case_map_fold); return cp != 0 ? cp : code; } @@ -231,10 +231,10 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, while ((srclen < 0 || srcoff < srclen) && src[srcoff] != '\0') { - pg_wchar u1 = utf8_to_unicode((unsigned char *) src + srcoff); + char32_t u1 = utf8_to_unicode((unsigned char *) src + srcoff); int u1len = unicode_utf8len(u1); - pg_wchar simple = 0; - const pg_wchar *special = NULL; + char32_t simple = 0; + const char32_t *special = NULL; enum CaseMapResult casemap_result; if (str_casekind == CaseTitle) @@ -265,8 +265,8 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, case CASEMAP_SIMPLE: { /* replace with single character */ - pg_wchar u2 = simple; - pg_wchar u2len = unicode_utf8len(u2); + char32_t u2 = simple; + char32_t u2len = unicode_utf8len(u2); Assert(special == NULL); if (result_len + u2len <= dstsize) @@ -280,7 +280,7 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, Assert(simple == 0); for (int i = 0; i < MAX_CASE_EXPANSION && special[i]; i++) { - pg_wchar u2 = special[i]; + char32_t u2 = special[i]; size_t u2len = unicode_utf8len(u2); if (result_len + u2len <= dstsize) @@ -320,7 +320,7 @@ check_final_sigma(const unsigned char *str, size_t len, size_t offset) { if ((str[i] & 0x80) == 0 || (str[i] & 0xC0) == 0xC0) { - pg_wchar curr = utf8_to_unicode(str + i); + char32_t curr = utf8_to_unicode(str + i); if (pg_u_prop_case_ignorable(curr)) continue; @@ -344,7 +344,7 @@ check_final_sigma(const unsigned char *str, size_t len, size_t offset) { if ((str[i] & 0x80) == 0 || (str[i] & 0xC0) == 0xC0) { - pg_wchar curr = utf8_to_unicode(str + i); + char32_t curr = utf8_to_unicode(str + i); if (pg_u_prop_case_ignorable(curr)) continue; @@ -394,9 +394,9 @@ check_special_conditions(int conditions, const char *str, size_t len, * character without modification. */ static enum CaseMapResult -casemap(pg_wchar u1, CaseKind casekind, bool full, +casemap(char32_t u1, CaseKind casekind, bool full, const char *src, size_t srclen, size_t srcoff, - pg_wchar *simple, const pg_wchar **special) + char32_t *simple, const char32_t **special) { uint16 idx; @@ -434,8 +434,8 @@ casemap(pg_wchar u1, CaseKind casekind, bool full, * Find entry in simple case map. * If the entry does not exist, 0 will be returned. */ -static pg_wchar -find_case_map(pg_wchar ucs, const pg_wchar *map) +static char32_t +find_case_map(char32_t ucs, const char32_t *map) { /* Fast path for codepoints < 0x80 */ if (ucs < 0x80) diff --git a/src/common/unicode_category.c b/src/common/unicode_category.c index 4136c4d4f92..aab667a7bb4 100644 --- a/src/common/unicode_category.c +++ b/src/common/unicode_category.c @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * unicode_category.c * Determine general category and character properties of Unicode - * characters. Encoding must be UTF8, where we assume that the pg_wchar + * characters. Encoding must be UTF8, where we assume that the char32_t * representation is a code point. * * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group @@ -76,13 +76,13 @@ #define PG_U_CHARACTER_TAB 0x09 static bool range_search(const pg_unicode_range *tbl, size_t size, - pg_wchar code); + char32_t code); /* * Unicode general category for the given codepoint. */ pg_unicode_category -unicode_category(pg_wchar code) +unicode_category(char32_t code) { int min = 0; int mid; @@ -108,7 +108,7 @@ unicode_category(pg_wchar code) } bool -pg_u_prop_alphabetic(pg_wchar code) +pg_u_prop_alphabetic(char32_t code) { if (code < 0x80) return unicode_opt_ascii[code].properties & PG_U_PROP_ALPHABETIC; @@ -119,7 +119,7 @@ pg_u_prop_alphabetic(pg_wchar code) } bool -pg_u_prop_lowercase(pg_wchar code) +pg_u_prop_lowercase(char32_t code) { if (code < 0x80) return unicode_opt_ascii[code].properties & PG_U_PROP_LOWERCASE; @@ -130,7 +130,7 @@ pg_u_prop_lowercase(pg_wchar code) } bool -pg_u_prop_uppercase(pg_wchar code) +pg_u_prop_uppercase(char32_t code) { if (code < 0x80) return unicode_opt_ascii[code].properties & PG_U_PROP_UPPERCASE; @@ -141,7 +141,7 @@ pg_u_prop_uppercase(pg_wchar code) } bool -pg_u_prop_cased(pg_wchar code) +pg_u_prop_cased(char32_t code) { uint32 category_mask; @@ -156,7 +156,7 @@ pg_u_prop_cased(pg_wchar code) } bool -pg_u_prop_case_ignorable(pg_wchar code) +pg_u_prop_case_ignorable(char32_t code) { if (code < 0x80) return unicode_opt_ascii[code].properties & PG_U_PROP_CASE_IGNORABLE; @@ -167,7 +167,7 @@ pg_u_prop_case_ignorable(pg_wchar code) } bool -pg_u_prop_white_space(pg_wchar code) +pg_u_prop_white_space(char32_t code) { if (code < 0x80) return unicode_opt_ascii[code].properties & PG_U_PROP_WHITE_SPACE; @@ -178,7 +178,7 @@ pg_u_prop_white_space(pg_wchar code) } bool -pg_u_prop_hex_digit(pg_wchar code) +pg_u_prop_hex_digit(char32_t code) { if (code < 0x80) return unicode_opt_ascii[code].properties & PG_U_PROP_HEX_DIGIT; @@ -189,7 +189,7 @@ pg_u_prop_hex_digit(pg_wchar code) } bool -pg_u_prop_join_control(pg_wchar code) +pg_u_prop_join_control(char32_t code) { if (code < 0x80) return unicode_opt_ascii[code].properties & PG_U_PROP_JOIN_CONTROL; @@ -208,7 +208,7 @@ pg_u_prop_join_control(pg_wchar code) */ bool -pg_u_isdigit(pg_wchar code, bool posix) +pg_u_isdigit(char32_t code, bool posix) { if (posix) return ('0' <= code && code <= '9'); @@ -217,19 +217,19 @@ pg_u_isdigit(pg_wchar code, bool posix) } bool -pg_u_isalpha(pg_wchar code) +pg_u_isalpha(char32_t code) { return pg_u_prop_alphabetic(code); } bool -pg_u_isalnum(pg_wchar code, bool posix) +pg_u_isalnum(char32_t code, bool posix) { return pg_u_isalpha(code) || pg_u_isdigit(code, posix); } bool -pg_u_isword(pg_wchar code) +pg_u_isword(char32_t code) { uint32 category_mask = PG_U_CATEGORY_MASK(unicode_category(code)); @@ -240,32 +240,32 @@ pg_u_isword(pg_wchar code) } bool -pg_u_isupper(pg_wchar code) +pg_u_isupper(char32_t code) { return pg_u_prop_uppercase(code); } bool -pg_u_islower(pg_wchar code) +pg_u_islower(char32_t code) { return pg_u_prop_lowercase(code); } bool -pg_u_isblank(pg_wchar code) +pg_u_isblank(char32_t code) { return code == PG_U_CHARACTER_TAB || unicode_category(code) == PG_U_SPACE_SEPARATOR; } bool -pg_u_iscntrl(pg_wchar code) +pg_u_iscntrl(char32_t code) { return unicode_category(code) == PG_U_CONTROL; } bool -pg_u_isgraph(pg_wchar code) +pg_u_isgraph(char32_t code) { uint32 category_mask = PG_U_CATEGORY_MASK(unicode_category(code)); @@ -276,7 +276,7 @@ pg_u_isgraph(pg_wchar code) } bool -pg_u_isprint(pg_wchar code) +pg_u_isprint(char32_t code) { pg_unicode_category category = unicode_category(code); @@ -287,7 +287,7 @@ pg_u_isprint(pg_wchar code) } bool -pg_u_ispunct(pg_wchar code, bool posix) +pg_u_ispunct(char32_t code, bool posix) { uint32 category_mask; @@ -308,13 +308,13 @@ pg_u_ispunct(pg_wchar code, bool posix) } bool -pg_u_isspace(pg_wchar code) +pg_u_isspace(char32_t code) { return pg_u_prop_white_space(code); } bool -pg_u_isxdigit(pg_wchar code, bool posix) +pg_u_isxdigit(char32_t code, bool posix) { if (posix) return (('0' <= code && code <= '9') || @@ -478,7 +478,7 @@ unicode_category_abbrev(pg_unicode_category category) * given table. */ static bool -range_search(const pg_unicode_range *tbl, size_t size, pg_wchar code) +range_search(const pg_unicode_range *tbl, size_t size, char32_t code) { int min = 0; int mid; diff --git a/src/common/unicode_norm.c b/src/common/unicode_norm.c index 6654b4cbc49..489d99cd5ab 100644 --- a/src/common/unicode_norm.c +++ b/src/common/unicode_norm.c @@ -69,7 +69,7 @@ conv_compare(const void *p1, const void *p2) * lookup, while the frontend version uses a binary search. */ static const pg_unicode_decomposition * -get_code_entry(pg_wchar code) +get_code_entry(char32_t code) { #ifndef FRONTEND int h; @@ -109,7 +109,7 @@ get_code_entry(pg_wchar code) * Get the combining class of the given codepoint. */ static uint8 -get_canonical_class(pg_wchar code) +get_canonical_class(char32_t code) { const pg_unicode_decomposition *entry = get_code_entry(code); @@ -130,15 +130,15 @@ get_canonical_class(pg_wchar code) * Note: the returned pointer can point to statically allocated buffer, and * is only valid until next call to this function! */ -static const pg_wchar * +static const char32_t * get_code_decomposition(const pg_unicode_decomposition *entry, int *dec_size) { - static pg_wchar x; + static char32_t x; if (DECOMPOSITION_IS_INLINE(entry)) { Assert(DECOMPOSITION_SIZE(entry) == 1); - x = (pg_wchar) entry->dec_index; + x = (char32_t) entry->dec_index; *dec_size = 1; return &x; } @@ -156,7 +156,7 @@ get_code_decomposition(const pg_unicode_decomposition *entry, int *dec_size) * are, in turn, decomposable. */ static int -get_decomposed_size(pg_wchar code, bool compat) +get_decomposed_size(char32_t code, bool compat) { const pg_unicode_decomposition *entry; int size = 0; @@ -318,7 +318,7 @@ recompose_code(uint32 start, uint32 code, uint32 *result) * in the array result. */ static void -decompose_code(pg_wchar code, bool compat, pg_wchar **result, int *current) +decompose_code(char32_t code, bool compat, char32_t **result, int *current) { const pg_unicode_decomposition *entry; int i; @@ -337,7 +337,7 @@ decompose_code(pg_wchar code, bool compat, pg_wchar **result, int *current) v, tindex, sindex; - pg_wchar *res = *result; + char32_t *res = *result; sindex = code - SBASE; l = LBASE + sindex / (VCOUNT * TCOUNT); @@ -369,7 +369,7 @@ decompose_code(pg_wchar code, bool compat, pg_wchar **result, int *current) if (entry == NULL || DECOMPOSITION_SIZE(entry) == 0 || (!compat && DECOMPOSITION_IS_COMPAT(entry))) { - pg_wchar *res = *result; + char32_t *res = *result; res[*current] = code; (*current)++; @@ -382,7 +382,7 @@ decompose_code(pg_wchar code, bool compat, pg_wchar **result, int *current) decomp = get_code_decomposition(entry, &dec_size); for (i = 0; i < dec_size; i++) { - pg_wchar lcode = (pg_wchar) decomp[i]; + char32_t lcode = (char32_t) decomp[i]; /* Leave if no more decompositions */ decompose_code(lcode, compat, result, current); @@ -398,17 +398,17 @@ decompose_code(pg_wchar code, bool compat, pg_wchar **result, int *current) * malloc. Or NULL if we run out of memory. In backend, the returned * string is palloc'd instead, and OOM is reported with ereport(). */ -pg_wchar * -unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input) +char32_t * +unicode_normalize(UnicodeNormalizationForm form, const char32_t *input) { bool compat = (form == UNICODE_NFKC || form == UNICODE_NFKD); bool recompose = (form == UNICODE_NFC || form == UNICODE_NFKC); - pg_wchar *decomp_chars; - pg_wchar *recomp_chars; + char32_t *decomp_chars; + char32_t *recomp_chars; int decomp_size, current_size; int count; - const pg_wchar *p; + const char32_t *p; /* variables for recomposition */ int last_class; @@ -425,7 +425,7 @@ unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input) for (p = input; *p; p++) decomp_size += get_decomposed_size(*p, compat); - decomp_chars = (pg_wchar *) ALLOC((decomp_size + 1) * sizeof(pg_wchar)); + decomp_chars = (char32_t *) ALLOC((decomp_size + 1) * sizeof(char32_t)); if (decomp_chars == NULL) return NULL; @@ -448,9 +448,9 @@ unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input) */ for (count = 1; count < decomp_size; count++) { - pg_wchar prev = decomp_chars[count - 1]; - pg_wchar next = decomp_chars[count]; - pg_wchar tmp; + char32_t prev = decomp_chars[count - 1]; + char32_t next = decomp_chars[count]; + char32_t tmp; const uint8 prevClass = get_canonical_class(prev); const uint8 nextClass = get_canonical_class(next); @@ -487,7 +487,7 @@ unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input) * longer than the decomposed one, so make the allocation of the output * string based on that assumption. */ - recomp_chars = (pg_wchar *) ALLOC((decomp_size + 1) * sizeof(pg_wchar)); + recomp_chars = (char32_t *) ALLOC((decomp_size + 1) * sizeof(char32_t)); if (!recomp_chars) { FREE(decomp_chars); @@ -501,9 +501,9 @@ unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input) for (count = 1; count < decomp_size; count++) { - pg_wchar ch = decomp_chars[count]; + char32_t ch = decomp_chars[count]; int ch_class = get_canonical_class(ch); - pg_wchar composite; + char32_t composite; if (last_class < ch_class && recompose_code(starter_ch, ch, &composite)) @@ -524,7 +524,7 @@ unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input) recomp_chars[target_pos++] = ch; } } - recomp_chars[target_pos] = (pg_wchar) '\0'; + recomp_chars[target_pos] = (char32_t) '\0'; FREE(decomp_chars); @@ -540,7 +540,7 @@ unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input) #ifndef FRONTEND static const pg_unicode_normprops * -qc_hash_lookup(pg_wchar ch, const pg_unicode_norminfo *norminfo) +qc_hash_lookup(char32_t ch, const pg_unicode_norminfo *norminfo) { int h; uint32 hashkey; @@ -571,7 +571,7 @@ qc_hash_lookup(pg_wchar ch, const pg_unicode_norminfo *norminfo) * Look up the normalization quick check character property */ static UnicodeNormalizationQC -qc_is_allowed(UnicodeNormalizationForm form, pg_wchar ch) +qc_is_allowed(UnicodeNormalizationForm form, char32_t ch) { const pg_unicode_normprops *found = NULL; @@ -595,7 +595,7 @@ qc_is_allowed(UnicodeNormalizationForm form, pg_wchar ch) } UnicodeNormalizationQC -unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const pg_wchar *input) +unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const char32_t *input) { uint8 lastCanonicalClass = 0; UnicodeNormalizationQC result = UNICODE_NORM_QC_YES; @@ -610,9 +610,9 @@ unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const pg_wchar * if (form == UNICODE_NFD || form == UNICODE_NFKD) return UNICODE_NORM_QC_MAYBE; - for (const pg_wchar *p = input; *p; p++) + for (const char32_t *p = input; *p; p++) { - pg_wchar ch = *p; + char32_t ch = *p; uint8 canonicalClass; UnicodeNormalizationQC check; diff --git a/src/fe_utils/mbprint.c b/src/fe_utils/mbprint.c index eb3eeee9925..abffdbe18a2 100644 --- a/src/fe_utils/mbprint.c +++ b/src/fe_utils/mbprint.c @@ -49,20 +49,20 @@ pg_get_utf8_id(void) * * No error checks here, c must point to a long-enough string. */ -static pg_wchar +static char32_t utf8_to_unicode(const unsigned char *c) { if ((*c & 0x80) == 0) - return (pg_wchar) c[0]; + return (char32_t) c[0]; else if ((*c & 0xe0) == 0xc0) - return (pg_wchar) (((c[0] & 0x1f) << 6) | + return (char32_t) (((c[0] & 0x1f) << 6) | (c[1] & 0x3f)); else if ((*c & 0xf0) == 0xe0) - return (pg_wchar) (((c[0] & 0x0f) << 12) | + return (char32_t) (((c[0] & 0x0f) << 12) | ((c[1] & 0x3f) << 6) | (c[2] & 0x3f)); else if ((*c & 0xf8) == 0xf0) - return (pg_wchar) (((c[0] & 0x07) << 18) | + return (char32_t) (((c[0] & 0x07) << 18) | ((c[1] & 0x3f) << 12) | ((c[2] & 0x3f) << 6) | (c[3] & 0x3f)); diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index d12798be3d8..a12757e46e5 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -202,6 +202,7 @@ extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, + uint64 fpi_bytes, bool topxid_included); extern void XLogFlush(XLogRecPtr record); extern bool XLogBackgroundFlush(void); diff --git a/src/include/c.h b/src/include/c.h index 9ab5e617995..757dfff4782 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -93,8 +93,6 @@ /* ---------------------------------------------------------------- * Section 1: compiler characteristics - * - * type prefixes (const, signed, volatile, inline) are handled in pg_config.h. * ---------------------------------------------------------------- */ @@ -109,6 +107,12 @@ #endif /* + * Previously used PostgreSQL-specific spelling, for backward compatibility + * for extensions. + */ +#define pg_restrict restrict + +/* * Attribute macros * * GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html @@ -1372,6 +1376,29 @@ typedef intptr_t sigjmp_buf[5]; /* /port compatibility functions */ #include "port.h" +/* + * char16_t and char32_t + * Unicode code points. + * + * uchar.h should always be available in C11, but it's not available on + * Mac. However, these types are keywords in C++11, so when using C++, we + * can't redefine the types. + * + * XXX: when uchar.h is available everywhere, we can remove this check and + * just include uchar.h unconditionally. + * + * XXX: this section is out of place because uchar.h needs to be included + * after port.h, due to an interaction with win32_port.h in some cases. + */ +#ifdef HAVE_UCHAR_H +#include <uchar.h> +#else +#ifndef __cplusplus +typedef uint16_t char16_t; +typedef uint32_t char32_t; +#endif +#endif + /* IWYU pragma: end_exports */ #endif /* C_H */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 1b0b16a343f..18e95179ab6 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202510221 +#define CATALOG_VERSION_NO 202510281 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index eecb43ec6f0..9121a382f76 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6029,16 +6029,16 @@ { oid => '1136', descr => 'statistics: information about WAL activity', proname => 'pg_stat_get_wal', proisstrict => 'f', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => '', - proallargtypes => '{int8,int8,numeric,int8,timestamptz}', - proargmodes => '{o,o,o,o,o}', - proargnames => '{wal_records,wal_fpi,wal_bytes,wal_buffers_full,stats_reset}', + proallargtypes => '{int8,int8,numeric,numeric,int8,timestamptz}', + proargmodes => '{o,o,o,o,o,o}', + proargnames => '{wal_records,wal_fpi,wal_bytes,wal_fpi_bytes,wal_buffers_full,stats_reset}', prosrc => 'pg_stat_get_wal' }, { oid => '6313', descr => 'statistics: backend WAL activity', proname => 'pg_stat_get_backend_wal', provolatile => 'v', proparallel => 'r', prorettype => 'record', proargtypes => 'int4', - proallargtypes => '{int4,int8,int8,numeric,int8,timestamptz}', - proargmodes => '{i,o,o,o,o,o}', - proargnames => '{backend_pid,wal_records,wal_fpi,wal_bytes,wal_buffers_full,stats_reset}', + proallargtypes => '{int4,int8,int8,numeric,numeric,int8,timestamptz}', + proargmodes => '{i,o,o,o,o,o,o}', + proargnames => '{backend_pid,wal_records,wal_fpi,wal_bytes,wal_fpi_bytes,wal_buffers_full,stats_reset}', prosrc => 'pg_stat_get_backend_wal' }, { oid => '6248', descr => 'statistics: information about WAL prefetching', proname => 'pg_stat_get_recovery_prefetch', prorows => '1', proretset => 't', diff --git a/src/include/common/logging.h b/src/include/common/logging.h index 81529ee8f29..2e0333dc009 100644 --- a/src/include/common/logging.h +++ b/src/include/common/logging.h @@ -93,10 +93,10 @@ void pg_logging_set_pre_callback(void (*cb) (void)); void pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno)); void pg_log_generic(enum pg_log_level level, enum pg_log_part part, - const char *pg_restrict fmt,...) + const char *restrict fmt,...) pg_attribute_printf(3, 4); void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, - const char *pg_restrict fmt, va_list ap) + const char *restrict fmt, va_list ap) pg_attribute_printf(3, 0); /* diff --git a/src/include/common/string.h b/src/include/common/string.h index 55ed8774364..32a97c24b22 100644 --- a/src/include/common/string.h +++ b/src/include/common/string.h @@ -25,7 +25,7 @@ typedef struct PromptInterruptContext /* functions in src/common/string.c */ extern bool pg_str_endswith(const char *str, const char *end); -extern int strtoint(const char *pg_restrict str, char **pg_restrict endptr, +extern int strtoint(const char *restrict str, char **restrict endptr, int base); extern char *pg_clean_ascii(const char *str, int alloc_flags); extern int pg_strip_crlf(char *str); diff --git a/src/include/common/unicode_case.h b/src/include/common/unicode_case.h index 41e2c1f4b33..6bcffd349c2 100644 --- a/src/include/common/unicode_case.h +++ b/src/include/common/unicode_case.h @@ -14,14 +14,12 @@ #ifndef UNICODE_CASE_H #define UNICODE_CASE_H -#include "mb/pg_wchar.h" - typedef size_t (*WordBoundaryNext) (void *wbstate); -pg_wchar unicode_lowercase_simple(pg_wchar code); -pg_wchar unicode_titlecase_simple(pg_wchar code); -pg_wchar unicode_uppercase_simple(pg_wchar code); -pg_wchar unicode_casefold_simple(pg_wchar code); +char32_t unicode_lowercase_simple(char32_t code); +char32_t unicode_titlecase_simple(char32_t code); +char32_t unicode_uppercase_simple(char32_t code); +char32_t unicode_casefold_simple(char32_t code); size_t unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen, bool full); size_t unicode_strtitle(char *dst, size_t dstsize, const char *src, diff --git a/src/include/common/unicode_case_table.h b/src/include/common/unicode_case_table.h index d5311786582..0a14fb2d97b 100644 --- a/src/include/common/unicode_case_table.h +++ b/src/include/common/unicode_case_table.h @@ -18,7 +18,6 @@ */ #include "common/unicode_case.h" -#include "mb/pg_wchar.h" /* * The maximum number of codepoints that can result from case mapping @@ -45,7 +44,7 @@ typedef enum typedef struct { int16 conditions; - pg_wchar map[NCaseKind][MAX_CASE_EXPANSION]; + char32_t map[NCaseKind][MAX_CASE_EXPANSION]; } pg_special_case; /* @@ -166,7 +165,7 @@ static const pg_special_case special_case[106] = * The entry case_map_lower[case_index(codepoint)] is the mapping for the * given codepoint. */ -static const pg_wchar case_map_lower[1704] = +static const char32_t case_map_lower[1704] = { 0x000000, /* reserved */ 0x000000, /* U+000000 */ @@ -1879,7 +1878,7 @@ static const pg_wchar case_map_lower[1704] = * The entry case_map_title[case_index(codepoint)] is the mapping for the * given codepoint. */ -static const pg_wchar case_map_title[1704] = +static const char32_t case_map_title[1704] = { 0x000000, /* reserved */ 0x000000, /* U+000000 */ @@ -3592,7 +3591,7 @@ static const pg_wchar case_map_title[1704] = * The entry case_map_upper[case_index(codepoint)] is the mapping for the * given codepoint. */ -static const pg_wchar case_map_upper[1704] = +static const char32_t case_map_upper[1704] = { 0x000000, /* reserved */ 0x000000, /* U+000000 */ @@ -5305,7 +5304,7 @@ static const pg_wchar case_map_upper[1704] = * The entry case_map_fold[case_index(codepoint)] is the mapping for the * given codepoint. */ -static const pg_wchar case_map_fold[1704] = +static const char32_t case_map_fold[1704] = { 0x000000, /* reserved */ 0x000000, /* U+000000 */ @@ -13522,7 +13521,7 @@ static const uint16 case_map[4778] = * the offset into the mapping tables. */ static inline uint16 -case_index(pg_wchar cp) +case_index(char32_t cp) { /* Fast path for codepoints < 0x0588 */ if (cp < 0x0588) diff --git a/src/include/common/unicode_category.h b/src/include/common/unicode_category.h index 8fd8b67a416..684143d3c8a 100644 --- a/src/include/common/unicode_category.h +++ b/src/include/common/unicode_category.h @@ -14,8 +14,6 @@ #ifndef UNICODE_CATEGORY_H #define UNICODE_CATEGORY_H -#include "mb/pg_wchar.h" - /* * Unicode General Category Values * @@ -61,31 +59,31 @@ typedef enum pg_unicode_category PG_U_FINAL_PUNCTUATION = 29 /* Pf */ } pg_unicode_category; -extern pg_unicode_category unicode_category(pg_wchar code); +extern pg_unicode_category unicode_category(char32_t code); extern const char *unicode_category_string(pg_unicode_category category); extern const char *unicode_category_abbrev(pg_unicode_category category); -extern bool pg_u_prop_alphabetic(pg_wchar code); -extern bool pg_u_prop_lowercase(pg_wchar code); -extern bool pg_u_prop_uppercase(pg_wchar code); -extern bool pg_u_prop_cased(pg_wchar code); -extern bool pg_u_prop_case_ignorable(pg_wchar code); -extern bool pg_u_prop_white_space(pg_wchar code); -extern bool pg_u_prop_hex_digit(pg_wchar code); -extern bool pg_u_prop_join_control(pg_wchar code); +extern bool pg_u_prop_alphabetic(char32_t code); +extern bool pg_u_prop_lowercase(char32_t code); +extern bool pg_u_prop_uppercase(char32_t code); +extern bool pg_u_prop_cased(char32_t code); +extern bool pg_u_prop_case_ignorable(char32_t code); +extern bool pg_u_prop_white_space(char32_t code); +extern bool pg_u_prop_hex_digit(char32_t code); +extern bool pg_u_prop_join_control(char32_t code); -extern bool pg_u_isdigit(pg_wchar code, bool posix); -extern bool pg_u_isalpha(pg_wchar code); -extern bool pg_u_isalnum(pg_wchar code, bool posix); -extern bool pg_u_isword(pg_wchar code); -extern bool pg_u_isupper(pg_wchar code); -extern bool pg_u_islower(pg_wchar code); -extern bool pg_u_isblank(pg_wchar code); -extern bool pg_u_iscntrl(pg_wchar code); -extern bool pg_u_isgraph(pg_wchar code); -extern bool pg_u_isprint(pg_wchar code); -extern bool pg_u_ispunct(pg_wchar code, bool posix); -extern bool pg_u_isspace(pg_wchar code); -extern bool pg_u_isxdigit(pg_wchar code, bool posix); +extern bool pg_u_isdigit(char32_t code, bool posix); +extern bool pg_u_isalpha(char32_t code); +extern bool pg_u_isalnum(char32_t code, bool posix); +extern bool pg_u_isword(char32_t code); +extern bool pg_u_isupper(char32_t code); +extern bool pg_u_islower(char32_t code); +extern bool pg_u_isblank(char32_t code); +extern bool pg_u_iscntrl(char32_t code); +extern bool pg_u_isgraph(char32_t code); +extern bool pg_u_isprint(char32_t code); +extern bool pg_u_ispunct(char32_t code, bool posix); +extern bool pg_u_isspace(char32_t code); +extern bool pg_u_isxdigit(char32_t code, bool posix); #endif /* UNICODE_CATEGORY_H */ diff --git a/src/include/common/unicode_category_table.h b/src/include/common/unicode_category_table.h index 95a1c65da7e..466a41b72b0 100644 --- a/src/include/common/unicode_category_table.h +++ b/src/include/common/unicode_category_table.h @@ -20,15 +20,15 @@ */ typedef struct { - uint32 first; /* Unicode codepoint */ - uint32 last; /* Unicode codepoint */ + char32_t first; /* Unicode codepoint */ + char32_t last; /* Unicode codepoint */ uint8 category; /* General Category */ } pg_category_range; typedef struct { - uint32 first; /* Unicode codepoint */ - uint32 last; /* Unicode codepoint */ + char32_t first; /* Unicode codepoint */ + char32_t last; /* Unicode codepoint */ } pg_unicode_range; typedef struct diff --git a/src/include/common/unicode_norm.h b/src/include/common/unicode_norm.h index 5bc3b79e78e..516c192cc4c 100644 --- a/src/include/common/unicode_norm.h +++ b/src/include/common/unicode_norm.h @@ -14,8 +14,6 @@ #ifndef UNICODE_NORM_H #define UNICODE_NORM_H -#include "mb/pg_wchar.h" - typedef enum { UNICODE_NFC = 0, @@ -32,8 +30,8 @@ typedef enum UNICODE_NORM_QC_MAYBE = -1, } UnicodeNormalizationQC; -extern pg_wchar *unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input); +extern char32_t *unicode_normalize(UnicodeNormalizationForm form, const char32_t *input); -extern UnicodeNormalizationQC unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const pg_wchar *input); +extern UnicodeNormalizationQC unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const char32_t *input); #endif /* UNICODE_NORM_H */ diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h index 03653ab6c6c..ffe470f2b84 100644 --- a/src/include/executor/instrument.h +++ b/src/include/executor/instrument.h @@ -53,6 +53,7 @@ typedef struct WalUsage int64 wal_records; /* # of WAL records produced */ int64 wal_fpi; /* # of WAL full page images produced */ uint64 wal_bytes; /* size of WAL records produced */ + uint64 wal_fpi_bytes; /* size of WAL full page images produced */ int64 wal_buffers_full; /* # of times the WAL buffers became full */ } WalUsage; diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h index 55442caf0e4..127a74e299a 100644 --- a/src/include/libpq/pqformat.h +++ b/src/include/libpq/pqformat.h @@ -34,7 +34,7 @@ extern void pq_sendfloat8(StringInfo buf, float8 f); * Append a [u]int8 to a StringInfo buffer, which already has enough space * preallocated. * - * The use of pg_restrict allows the compiler to optimize the code based on + * The use of restrict allows the compiler to optimize the code based on * the assumption that buf, buf->len, buf->data and *buf->data don't * overlap. Without the annotation buf->len etc cannot be kept in a register * over subsequent pq_writeintN calls. @@ -43,7 +43,7 @@ extern void pq_sendfloat8(StringInfo buf, float8 f); * overly picky and demanding a * before a restrict. */ static inline void -pq_writeint8(StringInfoData *pg_restrict buf, uint8 i) +pq_writeint8(StringInfoData *restrict buf, uint8 i) { uint8 ni = i; @@ -57,7 +57,7 @@ pq_writeint8(StringInfoData *pg_restrict buf, uint8 i) * preallocated. */ static inline void -pq_writeint16(StringInfoData *pg_restrict buf, uint16 i) +pq_writeint16(StringInfoData *restrict buf, uint16 i) { uint16 ni = pg_hton16(i); @@ -71,7 +71,7 @@ pq_writeint16(StringInfoData *pg_restrict buf, uint16 i) * preallocated. */ static inline void -pq_writeint32(StringInfoData *pg_restrict buf, uint32 i) +pq_writeint32(StringInfoData *restrict buf, uint32 i) { uint32 ni = pg_hton32(i); @@ -85,7 +85,7 @@ pq_writeint32(StringInfoData *pg_restrict buf, uint32 i) * preallocated. */ static inline void -pq_writeint64(StringInfoData *pg_restrict buf, uint64 i) +pq_writeint64(StringInfoData *restrict buf, uint64 i) { uint64 ni = pg_hton64(i); @@ -105,7 +105,7 @@ pq_writeint64(StringInfoData *pg_restrict buf, uint64 i) * sent to the frontend. */ static inline void -pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str) +pq_writestring(StringInfoData *restrict buf, const char *restrict str) { int slen = strlen(str); char *p; diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h index 4b4a9974b75..4d84bdc81e4 100644 --- a/src/include/mb/pg_wchar.h +++ b/src/include/mb/pg_wchar.h @@ -532,25 +532,25 @@ typedef uint32 (*utf_local_conversion_func) (uint32 code); * Some handy functions for Unicode-specific tests. */ static inline bool -is_valid_unicode_codepoint(pg_wchar c) +is_valid_unicode_codepoint(char32_t c) { return (c > 0 && c <= 0x10FFFF); } static inline bool -is_utf16_surrogate_first(pg_wchar c) +is_utf16_surrogate_first(char32_t c) { return (c >= 0xD800 && c <= 0xDBFF); } static inline bool -is_utf16_surrogate_second(pg_wchar c) +is_utf16_surrogate_second(char32_t c) { return (c >= 0xDC00 && c <= 0xDFFF); } -static inline pg_wchar -surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second) +static inline char32_t +surrogate_pair_to_codepoint(char16_t first, char16_t second) { return ((first & 0x3FF) << 10) + 0x10000 + (second & 0x3FF); } @@ -561,20 +561,20 @@ surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second) * * No error checks here, c must point to a long-enough string. */ -static inline pg_wchar +static inline char32_t utf8_to_unicode(const unsigned char *c) { if ((*c & 0x80) == 0) - return (pg_wchar) c[0]; + return (char32_t) c[0]; else if ((*c & 0xe0) == 0xc0) - return (pg_wchar) (((c[0] & 0x1f) << 6) | + return (char32_t) (((c[0] & 0x1f) << 6) | (c[1] & 0x3f)); else if ((*c & 0xf0) == 0xe0) - return (pg_wchar) (((c[0] & 0x0f) << 12) | + return (char32_t) (((c[0] & 0x0f) << 12) | ((c[1] & 0x3f) << 6) | (c[2] & 0x3f)); else if ((*c & 0xf8) == 0xf0) - return (pg_wchar) (((c[0] & 0x07) << 18) | + return (char32_t) (((c[0] & 0x07) << 18) | ((c[1] & 0x3f) << 12) | ((c[2] & 0x3f) << 6) | (c[3] & 0x3f)); @@ -588,7 +588,7 @@ utf8_to_unicode(const unsigned char *c) * unicode_utf8len(c) bytes available. */ static inline unsigned char * -unicode_to_utf8(pg_wchar c, unsigned char *utf8string) +unicode_to_utf8(char32_t c, unsigned char *utf8string) { if (c <= 0x7F) { @@ -620,7 +620,7 @@ unicode_to_utf8(pg_wchar c, unsigned char *utf8string) * Number of bytes needed to represent the given char in UTF8. */ static inline int -unicode_utf8len(pg_wchar c) +unicode_utf8len(char32_t c) { if (c <= 0x7F) return 1; @@ -676,8 +676,8 @@ extern int pg_valid_server_encoding(const char *name); extern bool is_encoding_supported_by_icu(int encoding); extern const char *get_encoding_name_for_icu(int encoding); -extern unsigned char *unicode_to_utf8(pg_wchar c, unsigned char *utf8string); -extern pg_wchar utf8_to_unicode(const unsigned char *c); +extern unsigned char *unicode_to_utf8(char32_t c, unsigned char *utf8string); +extern char32_t utf8_to_unicode(const unsigned char *c); extern bool pg_utf8_islegal(const unsigned char *source, int length); extern int pg_utf_mblen(const unsigned char *s); extern int pg_mule_mblen(const unsigned char *s); @@ -739,8 +739,8 @@ extern char *pg_server_to_client(const char *s, int len); extern char *pg_any_to_server(const char *s, int len, int encoding); extern char *pg_server_to_any(const char *s, int len, int encoding); -extern void pg_unicode_to_server(pg_wchar c, unsigned char *s); -extern bool pg_unicode_to_server_noerror(pg_wchar c, unsigned char *s); +extern void pg_unicode_to_server(char32_t c, unsigned char *s); +extern bool pg_unicode_to_server_noerror(char32_t c, unsigned char *s); extern unsigned short BIG5toCNS(unsigned short big5, unsigned char *lc); extern unsigned short CNStoBIG5(unsigned short cns, unsigned char lc); diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index c4dc5d72bdb..f52f14cc566 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -463,6 +463,9 @@ /* Define to 1 if you have the <termios.h> header file. */ #undef HAVE_TERMIOS_H +/* Define to 1 if you have the <uchar.h> header file. */ +#undef HAVE_UCHAR_H + /* Define to 1 if curl_global_init() is guaranteed to be thread-safe. */ #undef HAVE_THREADSAFE_CURL_GLOBAL_INIT @@ -796,10 +799,6 @@ #undef inline #endif -/* Define to keyword to use for C99 restrict support, or to nothing if not - supported */ -#undef pg_restrict - /* Define to the equivalent of the C99 'restrict' keyword, or to nothing if this is not supported. Do not define if restrict is supported directly. */ diff --git a/src/include/pgstat.h b/src/include/pgstat.h index bc8077cbae6..7ae503e71a2 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -212,7 +212,7 @@ typedef struct PgStat_TableXactStatus * ------------------------------------------------------------ */ -#define PGSTAT_FILE_FORMAT_ID 0x01A5BCB9 +#define PGSTAT_FILE_FORMAT_ID 0x01A5BCBA typedef struct PgStat_ArchiverStats { @@ -473,6 +473,7 @@ typedef struct PgStat_WalCounters PgStat_Counter wal_records; PgStat_Counter wal_fpi; uint64 wal_bytes; + uint64 wal_fpi_bytes; PgStat_Counter wal_buffers_full; } PgStat_WalCounters; diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h index ae352f6e691..e23fa9a4514 100644 --- a/src/include/replication/worker_internal.h +++ b/src/include/replication/worker_internal.h @@ -254,7 +254,8 @@ extern PGDLLIMPORT bool InitializingApplyWorker; extern PGDLLIMPORT List *table_states_not_ready; extern void logicalrep_worker_attach(int slot); -extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid, +extern LogicalRepWorker *logicalrep_worker_find(LogicalRepWorkerType wtype, + Oid subid, Oid relid, bool only_running); extern List *logicalrep_workers_find(Oid subid, bool only_running, bool acquire_lock); @@ -263,9 +264,11 @@ extern bool logicalrep_worker_launch(LogicalRepWorkerType wtype, Oid userid, Oid relid, dsm_handle subworker_dsm, bool retain_dead_tuples); -extern void logicalrep_worker_stop(Oid subid, Oid relid); +extern void logicalrep_worker_stop(LogicalRepWorkerType wtype, Oid subid, + Oid relid); extern void logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo); -extern void logicalrep_worker_wakeup(Oid subid, Oid relid); +extern void logicalrep_worker_wakeup(LogicalRepWorkerType wtype, Oid subid, + Oid relid); extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker); extern int logicalrep_sync_worker_count(Oid subid); diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index 3de3d809545..bbfcc633014 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -132,6 +132,84 @@ typedef struct guc_stack config_var_value masked; /* SET value in a GUC_SET_LOCAL entry */ } GucStack; + +/* GUC records for specific variable types */ + +struct config_bool +{ + /* constant fields, must be set correctly in initial value: */ + bool *variable; + bool boot_val; + GucBoolCheckHook check_hook; + GucBoolAssignHook assign_hook; + GucShowHook show_hook; + /* variable fields, initialized at runtime: */ + bool reset_val; +}; + +struct config_int +{ + /* constant fields, must be set correctly in initial value: */ + int *variable; + int boot_val; + int min; + int max; + GucIntCheckHook check_hook; + GucIntAssignHook assign_hook; + GucShowHook show_hook; + /* variable fields, initialized at runtime: */ + int reset_val; +}; + +struct config_real +{ + /* constant fields, must be set correctly in initial value: */ + double *variable; + double boot_val; + double min; + double max; + GucRealCheckHook check_hook; + GucRealAssignHook assign_hook; + GucShowHook show_hook; + /* variable fields, initialized at runtime: */ + double reset_val; +}; + +/* + * A note about string GUCs: the boot_val is allowed to be NULL, which leads + * to the reset_val and the actual variable value (*variable) also being NULL. + * However, there is no way to set a NULL value subsequently using + * set_config_option or any other GUC API. Also, GUC APIs such as SHOW will + * display a NULL value as an empty string. Callers that choose to use a NULL + * boot_val should overwrite the setting later in startup, or else be careful + * that NULL doesn't have semantics that are visibly different from an empty + * string. + */ +struct config_string +{ + /* constant fields, must be set correctly in initial value: */ + char **variable; + const char *boot_val; + GucStringCheckHook check_hook; + GucStringAssignHook assign_hook; + GucShowHook show_hook; + /* variable fields, initialized at runtime: */ + char *reset_val; +}; + +struct config_enum +{ + /* constant fields, must be set correctly in initial value: */ + int *variable; + int boot_val; + const struct config_enum_entry *options; + GucEnumCheckHook check_hook; + GucEnumAssignHook assign_hook; + GucShowHook show_hook; + /* variable fields, initialized at runtime: */ + int reset_val; +}; + /* * Generic fields applicable to all types of variables * @@ -200,6 +278,16 @@ struct config_generic char *sourcefile; /* file current setting is from (NULL if not * set in config file) */ int sourceline; /* line in source file */ + + /* fields for specific variable types */ + union + { + struct config_bool _bool; + struct config_int _int; + struct config_real _real; + struct config_string _string; + struct config_enum _enum; + }; }; /* bit values in status field */ @@ -212,100 +300,14 @@ struct config_generic #define GUC_NEEDS_REPORT 0x0004 /* new value must be reported to client */ -/* GUC records for specific variable types */ - -struct config_bool -{ - struct config_generic gen; - /* constant fields, must be set correctly in initial value: */ - bool *variable; - bool boot_val; - GucBoolCheckHook check_hook; - GucBoolAssignHook assign_hook; - GucShowHook show_hook; - /* variable fields, initialized at runtime: */ - bool reset_val; -}; - -struct config_int -{ - struct config_generic gen; - /* constant fields, must be set correctly in initial value: */ - int *variable; - int boot_val; - int min; - int max; - GucIntCheckHook check_hook; - GucIntAssignHook assign_hook; - GucShowHook show_hook; - /* variable fields, initialized at runtime: */ - int reset_val; -}; - -struct config_real -{ - struct config_generic gen; - /* constant fields, must be set correctly in initial value: */ - double *variable; - double boot_val; - double min; - double max; - GucRealCheckHook check_hook; - GucRealAssignHook assign_hook; - GucShowHook show_hook; - /* variable fields, initialized at runtime: */ - double reset_val; -}; - -/* - * A note about string GUCs: the boot_val is allowed to be NULL, which leads - * to the reset_val and the actual variable value (*variable) also being NULL. - * However, there is no way to set a NULL value subsequently using - * set_config_option or any other GUC API. Also, GUC APIs such as SHOW will - * display a NULL value as an empty string. Callers that choose to use a NULL - * boot_val should overwrite the setting later in startup, or else be careful - * that NULL doesn't have semantics that are visibly different from an empty - * string. - */ -struct config_string -{ - struct config_generic gen; - /* constant fields, must be set correctly in initial value: */ - char **variable; - const char *boot_val; - GucStringCheckHook check_hook; - GucStringAssignHook assign_hook; - GucShowHook show_hook; - /* variable fields, initialized at runtime: */ - char *reset_val; -}; - -struct config_enum -{ - struct config_generic gen; - /* constant fields, must be set correctly in initial value: */ - int *variable; - int boot_val; - const struct config_enum_entry *options; - GucEnumCheckHook check_hook; - GucEnumAssignHook assign_hook; - GucShowHook show_hook; - /* variable fields, initialized at runtime: */ - int reset_val; -}; - /* constant tables corresponding to enums above and in guc.h */ extern PGDLLIMPORT const char *const config_group_names[]; extern PGDLLIMPORT const char *const config_type_names[]; extern PGDLLIMPORT const char *const GucContext_Names[]; extern PGDLLIMPORT const char *const GucSource_Names[]; -/* data arrays defining all the built-in GUC variables */ -extern PGDLLIMPORT struct config_bool ConfigureNamesBool[]; -extern PGDLLIMPORT struct config_int ConfigureNamesInt[]; -extern PGDLLIMPORT struct config_real ConfigureNamesReal[]; -extern PGDLLIMPORT struct config_string ConfigureNamesString[]; -extern PGDLLIMPORT struct config_enum ConfigureNamesEnum[]; +/* data array defining all the built-in GUC variables */ +extern PGDLLIMPORT struct config_generic ConfigureNames[]; /* lookup GUC variables, returning config_generic pointers */ extern struct config_generic *find_option(const char *name, @@ -326,7 +328,7 @@ extern struct config_generic **get_guc_variables(int *num_vars); extern void build_guc_variables(void); /* search in enum options */ -extern const char *config_enum_lookup_by_value(const struct config_enum *record, int val); +extern const char *config_enum_lookup_by_value(const struct config_generic *record, int val); extern bool config_enum_lookup_by_name(const struct config_enum *record, const char *value, int *retval); extern char *config_enum_get_options(const struct config_enum *record, diff --git a/src/interfaces/libpq/t/006_service.pl b/src/interfaces/libpq/t/006_service.pl index 797e6232b8f..29a70629b44 100644 --- a/src/interfaces/libpq/t/006_service.pl +++ b/src/interfaces/libpq/t/006_service.pl @@ -22,18 +22,14 @@ $dummy_node->init; my $td = PostgreSQL::Test::Utils::tempdir; -# Windows vs non-Windows: CRLF vs LF for the file's newline, relying on -# the fact that libpq uses fgets() when reading the lines of a service file. -my $newline = $windows_os ? "\r\n" : "\n"; - # Create the set of service files used in the tests. # File that includes a valid service name, and uses a decomposed connection # string for its contents, split on spaces. my $srvfile_valid = "$td/pg_service_valid.conf"; -append_to_file($srvfile_valid, "[my_srv]" . $newline); +append_to_file($srvfile_valid, "[my_srv]\n"); foreach my $param (split(/\s+/, $node->connstr)) { - append_to_file($srvfile_valid, $param . $newline); + append_to_file($srvfile_valid, $param . "\n"); } # File defined with no contents, used as default value for PGSERVICEFILE, @@ -51,14 +47,14 @@ my $srvfile_missing = "$td/pg_service_missing.conf"; my $srvfile_nested = "$td/pg_service_nested.conf"; copy($srvfile_valid, $srvfile_nested) or die "Could not copy $srvfile_valid to $srvfile_nested: $!"; -append_to_file($srvfile_nested, 'service=invalid_srv' . $newline); +append_to_file($srvfile_nested, "service=invalid_srv\n"); # Service file with nested "servicefile" defined. my $srvfile_nested_2 = "$td/pg_service_nested_2.conf"; copy($srvfile_valid, $srvfile_nested_2) or die "Could not copy $srvfile_valid to $srvfile_nested_2: $!"; append_to_file($srvfile_nested_2, - 'servicefile=' . $srvfile_default . $newline); + 'servicefile=' . $srvfile_default . "\n"); # Set the fallback directory lookup of the service file to the temporary # directory of this test. PGSYSCONFDIR is used if the service file diff --git a/src/test/ldap/t/003_ldap_connection_param_lookup.pl b/src/test/ldap/t/003_ldap_connection_param_lookup.pl index 8c1e1caf992..abcb6d22a8b 100644 --- a/src/test/ldap/t/003_ldap_connection_param_lookup.pl +++ b/src/test/ldap/t/003_ldap_connection_param_lookup.pl @@ -44,31 +44,21 @@ $ldap->ldapadd_file('authdata.ldif'); $ldap->ldapsetpw('uid=test1,dc=example,dc=net', 'secret1'); $ldap->ldapsetpw('uid=test2,dc=example,dc=net', 'secret2'); -# Windows vs non-Windows: CRLF vs LF for the file's newline, relying on -# the fact that libpq uses fgets() when reading the lines of a service file. -my $newline = $windows_os ? "\r\n" : "\n"; - my $td = PostgreSQL::Test::Utils::tempdir; # create ldap file based on postgres connection info my $ldif_valid = "$td/connection_params.ldif"; -append_to_file($ldif_valid, "version:1"); -append_to_file($ldif_valid, $newline); -append_to_file($ldif_valid, "dn:cn=mydatabase,dc=example,dc=net"); -append_to_file($ldif_valid, $newline); -append_to_file($ldif_valid, "changetype:add"); -append_to_file($ldif_valid, $newline); -append_to_file($ldif_valid, "objectclass:top"); -append_to_file($ldif_valid, $newline); -append_to_file($ldif_valid, "objectclass:device"); -append_to_file($ldif_valid, $newline); -append_to_file($ldif_valid, "cn:mydatabase"); -append_to_file($ldif_valid, $newline); -append_to_file($ldif_valid, "description:host="); -append_to_file($ldif_valid, $node->host); -append_to_file($ldif_valid, $newline); -append_to_file($ldif_valid, "description:port="); -append_to_file($ldif_valid, $node->port); +append_to_file( + $ldif_valid, qq{ +version:1 +dn:cn=mydatabase,dc=example,dc=net +changetype:add +objectclass:top +objectclass:device +cn:mydatabase +description:host=} . $node->host . qq{ +description:port=} . $node->port . qq{ +}); $ldap->ldapadd_file($ldif_valid); @@ -86,12 +76,11 @@ note "setting up PostgreSQL instance"; # File that includes a valid service name, that uses a decomposed # connection string for its contents, split on spaces. my $srvfile_valid = "$td/pg_service_valid.conf"; -append_to_file($srvfile_valid, "[my_srv]"); -append_to_file($srvfile_valid, $newline); -append_to_file($srvfile_valid, "ldap://localhost:"); -append_to_file($srvfile_valid, $ldap_port); -append_to_file($srvfile_valid, - "/dc=example,dc=net?description?one?(cn=mydatabase)"); +append_to_file( + $srvfile_valid, qq{ +[my_srv] +ldap://localhost:$ldap_port/dc=example,dc=net?description?one?(cn=mydatabase) +}); # File defined with no contents, used as default value for # PGSERVICEFILE, so that no lookup is attempted in the user's home diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 16753b2e4c0..77e25ca029e 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2306,9 +2306,10 @@ pg_stat_user_tables| SELECT relid, pg_stat_wal| SELECT wal_records, wal_fpi, wal_bytes, + wal_fpi_bytes, wal_buffers_full, stats_reset - FROM pg_stat_get_wal() w(wal_records, wal_fpi, wal_bytes, wal_buffers_full, stats_reset); + FROM pg_stat_get_wal() w(wal_records, wal_fpi, wal_bytes, wal_fpi_bytes, wal_buffers_full, stats_reset); pg_stat_wal_receiver| SELECT pid, status, receive_start_lsn, diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index bb4e1b37005..df88c78fe3a 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -3505,6 +3505,8 @@ cb_cleanup_dir cb_options cb_tablespace cb_tablespace_mapping +char16_t +char32_t check_agg_arguments_context check_function_callback check_network_data @@ -3808,7 +3810,6 @@ memoize_iterator metastring missing_cache_key mix_data_t -mixedStruct mode_t movedb_failure_params multirange_bsearch_comparison |
