summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_aggregate.dat10
-rw-r--r--src/include/catalog/pg_proc.dat10
-rw-r--r--src/include/nodes/pathnodes.h140
-rw-r--r--src/include/nodes/plannodes.h9
-rw-r--r--src/include/nodes/primnodes.h1
-rw-r--r--src/include/optimizer/extendplan.h72
-rw-r--r--src/include/optimizer/geqo.h12
-rw-r--r--src/include/optimizer/optimizer.h5
-rw-r--r--src/include/optimizer/pathnode.h4
-rw-r--r--src/include/optimizer/paths.h4
-rw-r--r--src/include/optimizer/planmain.h1
-rw-r--r--src/include/optimizer/planner.h25
-rw-r--r--src/include/pgstat.h4
-rw-r--r--src/include/replication/reorderbuffer.h3
-rw-r--r--src/include/storage/buf_internals.h4
-rw-r--r--src/include/storage/bufmgr.h3
-rw-r--r--src/include/tcop/tcopprot.h4
-rw-r--r--src/include/utils/float.h67
-rw-r--r--src/include/utils/pgstat_internal.h1
20 files changed, 307 insertions, 74 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 642abe5217e..a98c6d6d820 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202510062
+#define CATALOG_VERSION_NO 202510083
#endif
diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat
index d6aa1f6ec47..870769e8f14 100644
--- a/src/include/catalog/pg_aggregate.dat
+++ b/src/include/catalog/pg_aggregate.dat
@@ -558,26 +558,28 @@
aggfinalfn => 'array_agg_finalfn', aggcombinefn => 'array_agg_combine',
aggserialfn => 'array_agg_serialize',
aggdeserialfn => 'array_agg_deserialize', aggfinalextra => 't',
- aggtranstype => 'internal' },
+ aggtranstype => 'internal', aggtransspace => '-1' },
{ aggfnoid => 'array_agg(anyarray)', aggtransfn => 'array_agg_array_transfn',
aggfinalfn => 'array_agg_array_finalfn',
aggcombinefn => 'array_agg_array_combine',
aggserialfn => 'array_agg_array_serialize',
aggdeserialfn => 'array_agg_array_deserialize', aggfinalextra => 't',
- aggtranstype => 'internal' },
+ aggtranstype => 'internal', aggtransspace => '-1' },
# text
{ aggfnoid => 'string_agg(text,text)', aggtransfn => 'string_agg_transfn',
aggfinalfn => 'string_agg_finalfn', aggcombinefn => 'string_agg_combine',
aggserialfn => 'string_agg_serialize',
- aggdeserialfn => 'string_agg_deserialize', aggtranstype => 'internal' },
+ aggdeserialfn => 'string_agg_deserialize',
+ aggtranstype => 'internal', aggtransspace => '-1' },
# bytea
{ aggfnoid => 'string_agg(bytea,bytea)',
aggtransfn => 'bytea_string_agg_transfn',
aggfinalfn => 'bytea_string_agg_finalfn',
aggcombinefn => 'string_agg_combine', aggserialfn => 'string_agg_serialize',
- aggdeserialfn => 'string_agg_deserialize', aggtranstype => 'internal' },
+ aggdeserialfn => 'string_agg_deserialize',
+ aggtranstype => 'internal', aggtransspace => '-1' },
# range
{ aggfnoid => 'range_intersect_agg(anyrange)',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 7c20180637f..25687eaecea 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5691,9 +5691,9 @@
{ oid => '6169', descr => 'statistics: information about replication slot',
proname => 'pg_stat_get_replication_slot', provolatile => 's',
proparallel => 'r', prorettype => 'record', proargtypes => 'text',
- proallargtypes => '{text,text,int8,int8,int8,int8,int8,int8,int8,int8,timestamptz}',
- proargmodes => '{i,o,o,o,o,o,o,o,o,o,o}',
- proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,total_txns,total_bytes,stats_reset}',
+ proallargtypes => '{text,text,int8,int8,int8,int8,int8,int8,int8,int8,int8,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,mem_exceeded_count,total_txns,total_bytes,stats_reset}',
prosrc => 'pg_stat_get_replication_slot' },
{ oid => '6230', descr => 'statistics: check if a stats object exists',
@@ -6071,6 +6071,10 @@
proname => 'pg_stat_get_function_self_time', provolatile => 's',
proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
prosrc => 'pg_stat_get_function_self_time' },
+{ oid => '8745', descr => 'statistics: last reset for a function',
+ proname => 'pg_stat_get_function_stat_reset_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_function_stat_reset_time' },
{ oid => '3037',
descr => 'statistics: number of scans done for table/index in current transaction',
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index b12a2508d8c..79408743166 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -110,6 +110,9 @@ typedef struct PlannerGlobal
/* PlannerInfos for SubPlan nodes */
List *subroots pg_node_attr(read_write_ignore);
+ /* names already used for subplans (list of C strings) */
+ List *subplanNames pg_node_attr(read_write_ignore);
+
/* indices of subplans that require REWIND */
Bitmapset *rewindPlanIDs;
@@ -182,6 +185,10 @@ typedef struct PlannerGlobal
/* hash table for NOT NULL attnums of relations */
struct HTAB *rel_notnullatts_hash pg_node_attr(read_write_ignore);
+
+ /* extension state */
+ void **extension_state pg_node_attr(read_write_ignore);
+ int extension_state_allocated;
} PlannerGlobal;
/* macro for fetching the Plan associated with a SubPlan node */
@@ -228,6 +235,9 @@ struct PlannerInfo
/* NULL at outermost Query */
PlannerInfo *parent_root pg_node_attr(read_write_ignore);
+ /* Subplan name for EXPLAIN and debugging purposes (NULL at top level) */
+ char *plan_name;
+
/*
* plan_params contains the expressions that this query level needs to
* make available to a lower query level that is currently being planned.
@@ -391,6 +401,15 @@ struct PlannerInfo
/* list of PlaceHolderInfos */
List *placeholder_list;
+ /* list of AggClauseInfos */
+ List *agg_clause_list;
+
+ /* list of GroupExprInfos */
+ List *group_expr_list;
+
+ /* list of plain Vars contained in targetlist and havingQual */
+ List *tlist_vars;
+
/* array of PlaceHolderInfos indexed by phid */
struct PlaceHolderInfo **placeholder_array pg_node_attr(read_write_ignore, array_size(placeholder_array_size));
/* allocated size of array */
@@ -526,6 +545,8 @@ struct PlannerInfo
bool placeholdersFrozen;
/* true if planning a recursive WITH item */
bool hasRecursion;
+ /* true if a planner extension may replan this subquery */
+ bool assumeReplanning;
/*
* The rangetable index for the RTE_GROUP RTE, or 0 if there is no
@@ -572,14 +593,15 @@ struct PlannerInfo
bool *isAltSubplan pg_node_attr(read_write_ignore);
bool *isUsedSubplan pg_node_attr(read_write_ignore);
- /* optional private data for join_search_hook, e.g., GEQO */
- void *join_search_private pg_node_attr(read_write_ignore);
-
/* Does this query modify any partition key columns? */
bool partColsUpdated;
/* PartitionPruneInfos added in this query's plan. */
List *partPruneInfos;
+
+ /* extension state */
+ void **extension_state pg_node_attr(read_write_ignore);
+ int extension_state_allocated;
};
@@ -1041,6 +1063,14 @@ typedef struct RelOptInfo
bool consider_partitionwise_join;
/*
+ * used by eager aggregation:
+ */
+ /* information needed to create grouped paths */
+ struct RelAggInfo *agg_info;
+ /* the partially-aggregated version of the relation */
+ struct RelOptInfo *grouped_rel;
+
+ /*
* inheritance links, if this is an otherrel (otherwise NULL):
*/
/* Immediate parent relation (dumping it would be too verbose) */
@@ -1091,6 +1121,10 @@ typedef struct RelOptInfo
List **partexprs pg_node_attr(read_write_ignore);
/* Nullable partition key expressions */
List **nullable_partexprs pg_node_attr(read_write_ignore);
+
+ /* extension state */
+ void **extension_state pg_node_attr(read_write_ignore);
+ int extension_state_allocated;
} RelOptInfo;
/*
@@ -1125,6 +1159,63 @@ typedef struct RelOptInfo
bms_equal((sjinfo)->syn_righthand, (rel)->relids))
/*
+ * Is the given relation a grouped relation?
+ */
+#define IS_GROUPED_REL(rel) \
+ ((rel)->agg_info != NULL)
+
+/*
+ * RelAggInfo
+ * Information needed to create paths for a grouped relation.
+ *
+ * "target" is the default result targetlist for Paths scanning this grouped
+ * relation; list of Vars/Exprs, cost, width.
+ *
+ * "agg_input" is the output tlist for the paths that provide input to the
+ * grouped paths. One difference from the reltarget of the non-grouped
+ * relation is that agg_input has its sortgrouprefs[] initialized.
+ *
+ * "group_clauses" and "group_exprs" are lists of SortGroupClauses and the
+ * corresponding grouping expressions.
+ *
+ * "apply_at" tracks the set of relids at which partial aggregation is applied
+ * in the paths of this grouped relation.
+ *
+ * "grouped_rows" is the estimated number of result tuples of the grouped
+ * relation.
+ *
+ * "agg_useful" is a flag to indicate whether the grouped paths are considered
+ * useful. It is set true if the average partial group size is no less than
+ * min_eager_agg_group_size, suggesting a significant row count reduction.
+ */
+typedef struct RelAggInfo
+{
+ pg_node_attr(no_copy_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* the output tlist for the grouped paths */
+ struct PathTarget *target;
+
+ /* the output tlist for the input paths */
+ struct PathTarget *agg_input;
+
+ /* a list of SortGroupClauses */
+ List *group_clauses;
+ /* a list of grouping expressions */
+ List *group_exprs;
+
+ /* the set of relids partial aggregation is applied at */
+ Relids apply_at;
+
+ /* estimated number of result tuples */
+ Cardinality grouped_rows;
+
+ /* the grouped paths are considered useful? */
+ bool agg_useful;
+} RelAggInfo;
+
+/*
* IndexOptInfo
* Per-index information for planning/optimization
*
@@ -3269,6 +3360,49 @@ typedef struct MinMaxAggInfo
} MinMaxAggInfo;
/*
+ * For each distinct Aggref node that appears in the targetlist and HAVING
+ * clauses, we store an AggClauseInfo node in the PlannerInfo node's
+ * agg_clause_list. Each AggClauseInfo records the set of relations referenced
+ * by the aggregate expression. This information is used to determine how far
+ * the aggregate can be safely pushed down in the join tree.
+ */
+typedef struct AggClauseInfo
+{
+ pg_node_attr(no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* the Aggref expr */
+ Aggref *aggref;
+
+ /* lowest level we can evaluate this aggregate at */
+ Relids agg_eval_at;
+} AggClauseInfo;
+
+/*
+ * For each grouping expression that appears in grouping clauses, we store a
+ * GroupingExprInfo node in the PlannerInfo node's group_expr_list. Each
+ * GroupingExprInfo records the expression being grouped on, its sortgroupref,
+ * and the EquivalenceClass it belongs to. This information is necessary to
+ * reproduce correct grouping semantics at different levels of the join tree.
+ */
+typedef struct GroupingExprInfo
+{
+ pg_node_attr(no_read, no_query_jumble)
+
+ NodeTag type;
+
+ /* the represented expression */
+ Expr *expr;
+
+ /* the tleSortGroupRef of the corresponding SortGroupClause */
+ Index sortgroupref;
+
+ /* the equivalence class the expression belongs to */
+ EquivalenceClass *ec pg_node_attr(copy_as_scalar, equal_as_scalar);
+} GroupingExprInfo;
+
+/*
* At runtime, PARAM_EXEC slots are used to pass values around from one plan
* node to another. They can be used to pass values down into subqueries (for
* outer references in subqueries), or up out of subqueries (for the results
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 3d196f5078e..77ec2bc10b2 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -149,6 +149,15 @@ typedef struct PlannedStmt
/* non-null if this is utility stmt */
Node *utilityStmt;
+ /*
+ * DefElem objects added by extensions, e.g. using planner_shutdown_hook
+ *
+ * Set each DefElem's defname to the name of the plugin or extension, and
+ * the argument to a tree of nodes that all have copy and read/write
+ * support.
+ */
+ List *extension_state;
+
/* statement location in source string (copied from Query) */
/* start location, or -1 if unknown */
ParseLoc stmt_location;
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index e9d8bf74145..1b4436f2ff6 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -1108,6 +1108,7 @@ typedef struct SubPlan
Oid firstColCollation; /* Collation of first column of subplan
* result */
/* Information about execution strategy: */
+ bool isInitPlan; /* true if it's an InitPlan */
bool useHashTable; /* true to store subselect output in a hash
* table (implies we are doing "IN") */
bool unknownEqFalse; /* true if it's okay to return FALSE when the
diff --git a/src/include/optimizer/extendplan.h b/src/include/optimizer/extendplan.h
new file mode 100644
index 00000000000..de9618761dd
--- /dev/null
+++ b/src/include/optimizer/extendplan.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * extendplan.h
+ * Extend core planner objects with additional private state
+ *
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/extendplan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXTENDPLAN_H
+#define EXTENDPLAN_H
+
+#include "nodes/pathnodes.h"
+
+extern int GetPlannerExtensionId(const char *extension_name);
+
+/*
+ * Get extension-specific state from a PlannerGlobal.
+ */
+static inline void *
+GetPlannerGlobalExtensionState(PlannerGlobal *glob, int extension_id)
+{
+ Assert(extension_id >= 0);
+
+ if (extension_id >= glob->extension_state_allocated)
+ return NULL;
+
+ return glob->extension_state[extension_id];
+}
+
+/*
+ * Get extension-specific state from a PlannerInfo.
+ */
+static inline void *
+GetPlannerInfoExtensionState(PlannerInfo *root, int extension_id)
+{
+ Assert(extension_id >= 0);
+
+ if (extension_id >= root->extension_state_allocated)
+ return NULL;
+
+ return root->extension_state[extension_id];
+}
+
+/*
+ * Get extension-specific state from a PlannerInfo.
+ */
+static inline void *
+GetRelOptInfoExtensionState(RelOptInfo *rel, int extension_id)
+{
+ Assert(extension_id >= 0);
+
+ if (extension_id >= rel->extension_state_allocated)
+ return NULL;
+
+ return rel->extension_state[extension_id];
+}
+
+/* Functions to store private state into various planner objects */
+extern void SetPlannerGlobalExtensionState(PlannerGlobal *glob,
+ int extension_id,
+ void *opaque);
+extern void SetPlannerInfoExtensionState(PlannerInfo *root, int extension_id,
+ void *opaque);
+extern void SetRelOptInfoExtensionState(RelOptInfo *rel, int extension_id,
+ void *opaque);
+
+#endif
diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h
index 9f8e0f337aa..b3017dd8ec4 100644
--- a/src/include/optimizer/geqo.h
+++ b/src/include/optimizer/geqo.h
@@ -24,6 +24,7 @@
#include "common/pg_prng.h"
#include "nodes/pathnodes.h"
+#include "optimizer/extendplan.h"
#include "optimizer/geqo_gene.h"
@@ -62,6 +63,8 @@ extern PGDLLIMPORT int Geqo_generations; /* 1 .. inf, or 0 to use default */
extern PGDLLIMPORT double Geqo_selection_bias;
+extern PGDLLIMPORT int Geqo_planner_extension_id;
+
#define DEFAULT_GEQO_SELECTION_BIAS 2.0
#define MIN_GEQO_SELECTION_BIAS 1.5
#define MAX_GEQO_SELECTION_BIAS 2.0
@@ -70,7 +73,7 @@ extern PGDLLIMPORT double Geqo_seed; /* 0 .. 1 */
/*
- * Private state for a GEQO run --- accessible via root->join_search_private
+ * Private state for a GEQO run --- accessible via GetGeqoPrivateData
*/
typedef struct
{
@@ -78,6 +81,13 @@ typedef struct
pg_prng_state random_state; /* PRNG state */
} GeqoPrivateData;
+static inline GeqoPrivateData *
+GetGeqoPrivateData(PlannerInfo *root)
+{
+ /* headers must be C++-compliant, so the cast is required here */
+ return (GeqoPrivateData *)
+ GetPlannerInfoExtensionState(root, Geqo_planner_extension_id);
+}
/* routines in geqo_main.c */
extern RelOptInfo *geqo(PlannerInfo *root,
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index 04878f1f1c2..a34113903c0 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -24,6 +24,8 @@
#include "nodes/parsenodes.h"
+typedef struct ExplainState ExplainState; /* defined in explain_state.h */
+
/*
* We don't want to include nodes/pathnodes.h here, because non-planner
* code should generally treat PlannerInfo as an opaque typedef.
@@ -104,7 +106,8 @@ extern PGDLLIMPORT bool enable_distinct_reordering;
extern PlannedStmt *planner(Query *parse, const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern Expr *expression_planner(Expr *expr);
extern Expr *expression_planner_with_deps(Expr *expr,
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 763cd25bb3c..da60383c2aa 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -312,6 +312,8 @@ extern void setup_simple_rel_arrays(PlannerInfo *root);
extern void expand_planner_arrays(PlannerInfo *root, int add_size);
extern RelOptInfo *build_simple_rel(PlannerInfo *root, int relid,
RelOptInfo *parent);
+extern RelOptInfo *build_simple_grouped_rel(PlannerInfo *root, RelOptInfo *rel);
+extern RelOptInfo *build_grouped_rel(PlannerInfo *root, RelOptInfo *rel);
extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid);
extern RelOptInfo *find_base_rel_noerr(PlannerInfo *root, int relid);
extern RelOptInfo *find_base_rel_ignore_join(PlannerInfo *root, int relid);
@@ -351,4 +353,6 @@ extern RelOptInfo *build_child_join_rel(PlannerInfo *root,
SpecialJoinInfo *sjinfo,
int nappinfos, AppendRelInfo **appinfos);
+extern RelAggInfo *create_rel_agg_info(PlannerInfo *root, RelOptInfo *rel,
+ bool calculate_grouped_rows);
#endif /* PATHNODE_H */
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index cbade77b717..f6a62df0b43 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -21,7 +21,9 @@
* allpaths.c
*/
extern PGDLLIMPORT bool enable_geqo;
+extern PGDLLIMPORT bool enable_eager_aggregate;
extern PGDLLIMPORT int geqo_threshold;
+extern PGDLLIMPORT double min_eager_agg_group_size;
extern PGDLLIMPORT int min_parallel_table_scan_size;
extern PGDLLIMPORT int min_parallel_index_scan_size;
extern PGDLLIMPORT bool enable_group_by_reordering;
@@ -57,6 +59,8 @@ extern void generate_gather_paths(PlannerInfo *root, RelOptInfo *rel,
bool override_rows);
extern void generate_useful_gather_paths(PlannerInfo *root, RelOptInfo *rel,
bool override_rows);
+extern void generate_grouped_paths(PlannerInfo *root, RelOptInfo *grouped_rel,
+ RelOptInfo *rel);
extern int compute_parallel_worker(RelOptInfo *rel, double heap_pages,
double index_pages, int max_workers);
extern void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel,
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index 9d3debcab28..09b48b26f8f 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -76,6 +76,7 @@ extern void add_vars_to_targetlist(PlannerInfo *root, List *vars,
extern void add_vars_to_attr_needed(PlannerInfo *root, List *vars,
Relids where_needed);
extern void remove_useless_groupby_columns(PlannerInfo *root);
+extern void setup_eager_aggregation(PlannerInfo *root);
extern void find_lateral_references(PlannerInfo *root);
extern void rebuild_lateral_attr_needed(PlannerInfo *root);
extern void create_lateral_join_info(PlannerInfo *root);
diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h
index f220e9a270d..55d9b7940aa 100644
--- a/src/include/optimizer/planner.h
+++ b/src/include/optimizer/planner.h
@@ -22,13 +22,29 @@
#include "nodes/plannodes.h"
+typedef struct ExplainState ExplainState; /* defined in explain_state.h */
+
/* Hook for plugins to get control in planner() */
typedef PlannedStmt *(*planner_hook_type) (Query *parse,
const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern PGDLLIMPORT planner_hook_type planner_hook;
+/* Hook for plugins to get control after PlannerGlobal is initialized */
+typedef void (*planner_setup_hook_type) (PlannerGlobal *glob, Query *parse,
+ const char *query_string,
+ double *tuple_fraction,
+ ExplainState *es);
+extern PGDLLIMPORT planner_setup_hook_type planner_setup_hook;
+
+/* Hook for plugins to get control before PlannerGlobal is discarded */
+typedef void (*planner_shutdown_hook_type) (PlannerGlobal *glob, Query *parse,
+ const char *query_string,
+ PlannedStmt *pstmt);
+extern PGDLLIMPORT planner_shutdown_hook_type planner_shutdown_hook;
+
/* Hook for plugins to get control when grouping_planner() plans upper rels */
typedef void (*create_upper_paths_hook_type) (PlannerInfo *root,
UpperRelationKind stage,
@@ -40,9 +56,11 @@ extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook;
extern PlannedStmt *standard_planner(Query *parse, const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern PlannerInfo *subquery_planner(PlannerGlobal *glob, Query *parse,
+ char *plan_name,
PlannerInfo *parent_root,
bool hasRecursion, double tuple_fraction,
SetOperationStmt *setops);
@@ -62,4 +80,7 @@ extern Expr *preprocess_phv_expression(PlannerInfo *root, Expr *expr);
extern RelOptInfo *create_unique_paths(PlannerInfo *root, RelOptInfo *rel,
SpecialJoinInfo *sjinfo);
+extern char *choose_plan_name(PlannerGlobal *glob, const char *name,
+ bool always_number);
+
#endif /* PLANNER_H */
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 8e8adb01176..bc8077cbae6 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -212,7 +212,7 @@ typedef struct PgStat_TableXactStatus
* ------------------------------------------------------------
*/
-#define PGSTAT_FILE_FORMAT_ID 0x01A5BCB8
+#define PGSTAT_FILE_FORMAT_ID 0x01A5BCB9
typedef struct PgStat_ArchiverStats
{
@@ -384,6 +384,7 @@ typedef struct PgStat_StatFuncEntry
PgStat_Counter total_time; /* times in microseconds */
PgStat_Counter self_time;
+ TimestampTz stat_reset_timestamp;
} PgStat_StatFuncEntry;
typedef struct PgStat_StatReplSlotEntry
@@ -394,6 +395,7 @@ typedef struct PgStat_StatReplSlotEntry
PgStat_Counter stream_txns;
PgStat_Counter stream_count;
PgStat_Counter stream_bytes;
+ PgStat_Counter mem_exceeded_count;
PgStat_Counter total_txns;
PgStat_Counter total_bytes;
TimestampTz stat_reset_timestamp;
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index 91dc7e5e448..3cbe106a3c7 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -690,6 +690,9 @@ struct ReorderBuffer
int64 streamCount; /* streaming invocation counter */
int64 streamBytes; /* amount of data decoded */
+ /* Number of times the logical_decoding_work_mem limit has been reached */
+ int64 memExceededCount;
+
/*
* Statistics about all the transactions sent to the decoding output
* plugin
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index dfd614f7ca4..c1206a46aba 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -371,6 +371,8 @@ UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
pg_atomic_write_u32(&desc->state, buf_state & (~BM_LOCKED));
}
+extern uint32 WaitBufHdrUnlocked(BufferDesc *buf);
+
/* in bufmgr.c */
/*
@@ -425,6 +427,8 @@ extern void IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_co
extern void ScheduleBufferTagForWriteback(WritebackContext *wb_context,
IOContext io_context, BufferTag *tag);
+extern void TrackNewBufferPin(Buffer buf);
+
/* solely to make it easier to write tests */
extern bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait);
extern void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits,
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 47360a3d3d8..3f37b294af6 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -230,7 +230,8 @@ extern void WaitReadBuffers(ReadBuffersOperation *operation);
extern void ReleaseBuffer(Buffer buffer);
extern void UnlockReleaseBuffer(Buffer buffer);
-extern bool BufferIsExclusiveLocked(Buffer buffer);
+extern bool BufferIsLockedByMe(Buffer buffer);
+extern bool BufferIsLockedByMeInMode(Buffer buffer, int mode);
extern bool BufferIsDirty(Buffer buffer);
extern void MarkBufferDirty(Buffer buffer);
extern void IncrBufferRefCount(Buffer buffer);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index a83cc4f4850..c1bcfdec673 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -20,6 +20,7 @@
#include "utils/guc.h"
#include "utils/queryenvironment.h"
+typedef struct ExplainState ExplainState; /* defined in explain_state.h */
extern PGDLLIMPORT CommandDest whereToSendOutput;
extern PGDLLIMPORT const char *debug_query_string;
@@ -63,7 +64,8 @@ extern List *pg_analyze_and_rewrite_withcb(RawStmt *parsetree,
QueryEnvironment *queryEnv);
extern PlannedStmt *pg_plan_query(Query *querytree, const char *query_string,
int cursorOptions,
- ParamListInfo boundParams);
+ ParamListInfo boundParams,
+ ExplainState *es);
extern List *pg_plan_queries(List *querytrees, const char *query_string,
int cursorOptions,
ParamListInfo boundParams);
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index 0e2e9ec5347..fc2a9cf6475 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -25,13 +25,6 @@
/* Radians per degree, a.k.a. PI / 180 */
#define RADIANS_PER_DEGREE 0.0174532925199432957692
-/* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */
-#if defined(WIN32) && !defined(NAN)
-static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
-
-#define NAN (*(const float8 *) nan)
-#endif
-
extern PGDLLIMPORT int extra_float_digits;
/*
@@ -52,84 +45,46 @@ extern int float4_cmp_internal(float4 a, float4 b);
extern int float8_cmp_internal(float8 a, float8 b);
/*
- * Routines to provide reasonably platform-independent handling of
- * infinity and NaN
+ * Postgres requires IEEE-standard float arithmetic, including infinities
+ * and NaNs. We used to support pre-C99 compilers on which <math.h> might
+ * not supply the standard macros INFINITY and NAN. We no longer do so,
+ * but these wrapper functions are still preferred over using those macros
+ * directly.
*
- * We assume that isinf() and isnan() are available and work per spec.
- * (On some platforms, we have to supply our own; see src/port.) However,
- * generating an Infinity or NaN in the first place is less well standardized;
- * pre-C99 systems tend not to have C99's INFINITY and NaN macros. We
- * centralize our workarounds for this here.
+ * If you change these functions, see copies in interfaces/ecpg/ecpglib/data.c.
*/
-/*
- * The funny placements of the two #pragmas is necessary because of a
- * long lived bug in the Microsoft compilers.
- * See http://support.microsoft.com/kb/120968/en-us for details
- */
-#ifdef _MSC_VER
-#pragma warning(disable:4756)
-#endif
static inline float4
get_float4_infinity(void)
{
-#ifdef INFINITY
/* C99 standard way */
return (float4) INFINITY;
-#else
-#ifdef _MSC_VER
-#pragma warning(default:4756)
-#endif
-
- /*
- * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
- * largest normal float8. We assume forcing an overflow will get us a
- * true infinity.
- */
- return (float4) (HUGE_VAL * HUGE_VAL);
-#endif
}
static inline float8
get_float8_infinity(void)
{
-#ifdef INFINITY
/* C99 standard way */
return (float8) INFINITY;
-#else
-
- /*
- * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
- * largest normal float8. We assume forcing an overflow will get us a
- * true infinity.
- */
- return (float8) (HUGE_VAL * HUGE_VAL);
-#endif
}
+/* The C standard allows implementations to omit NAN, but we don't */
+#ifndef NAN
+#error "Postgres requires support for IEEE quiet NaNs"
+#endif
+
static inline float4
get_float4_nan(void)
{
-#ifdef NAN
/* C99 standard way */
return (float4) NAN;
-#else
- /* Assume we can get a NAN via zero divide */
- return (float4) (0.0 / 0.0);
-#endif
}
static inline float8
get_float8_nan(void)
{
- /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
-#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
/* C99 standard way */
return (float8) NAN;
-#else
- /* Assume we can get a NaN via zero divide */
- return (float8) (0.0 / 0.0);
-#endif
}
/*
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index dc42d8043b5..4d2b8aa6081 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -691,6 +691,7 @@ extern void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, Time
*/
extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_function_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
/*