mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Add a materialized view relations.
A materialized view has a rule just like a view and a heap and other physical properties like a table. The rule is only used to populate the table, references in queries refer to the materialized data. This is a minimal implementation, but should still be useful in many cases. Currently data is only populated "on demand" by the CREATE MATERIALIZED VIEW and REFRESH MATERIALIZED VIEW statements. It is expected that future releases will add incremental updates with various timings, and that a more refined concept of defining what is "fresh" data will be developed. At some point it may even be possible to have queries use a materialized in place of references to underlying tables, but that requires the other above-mentioned features to be working first. Much of the documentation work by Robert Haas. Review by Noah Misch, Thom Brown, Robert Haas, Marko Tiikkaja Security review by KaiGai Kohei, with a decision on how best to implement sepgsql still pending.
This commit is contained in:
@@ -70,6 +70,7 @@ extern Oid heap_create_with_catalog(const char *relname,
|
||||
bool is_internal);
|
||||
|
||||
extern void heap_create_init_fork(Relation rel);
|
||||
extern bool heap_is_matview_init_state(Relation rel);
|
||||
|
||||
extern void heap_drop_with_catalog(Oid relid);
|
||||
|
||||
|
@@ -153,6 +153,7 @@ DESCR("");
|
||||
#define RELKIND_VIEW 'v' /* view */
|
||||
#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
|
||||
#define RELKIND_FOREIGN_TABLE 'f' /* foreign table */
|
||||
#define RELKIND_MATVIEW 'm' /* materialized view */
|
||||
|
||||
#define RELPERSISTENCE_PERMANENT 'p' /* regular table */
|
||||
#define RELPERSISTENCE_UNLOGGED 'u' /* unlogged permanent table */
|
||||
|
@@ -1980,6 +1980,8 @@ DATA(insert OID = 3842 ( pg_view_is_insertable PGNSP PGUID 12 10 0 0 0 f f f f
|
||||
DESCR("is a view insertable-into");
|
||||
DATA(insert OID = 3843 ( pg_view_is_updatable PGNSP PGUID 12 10 0 0 0 f f f f t f s 1 0 16 "26" _null_ _null_ _null_ _null_ pg_view_is_updatable _null_ _null_ _null_ ));
|
||||
DESCR("is a view updatable");
|
||||
DATA(insert OID = 3846 ( pg_relation_is_scannable PGNSP PGUID 12 10 0 0 0 f f f f t f s 1 0 16 "26" _null_ _null_ _null_ _null_ pg_relation_is_scannable _null_ _null_ _null_ ));
|
||||
DESCR("is a relation scannable");
|
||||
|
||||
/* Deferrable unique constraint trigger */
|
||||
DATA(insert OID = 1250 ( unique_key_recheck PGNSP PGUID 12 1 0 0 0 f f f f t f v 0 0 2279 "" _null_ _null_ _null_ _null_ unique_key_recheck _null_ _null_ _null_ ));
|
||||
|
@@ -19,6 +19,10 @@
|
||||
#include "tcop/dest.h"
|
||||
|
||||
|
||||
extern Query *SetupForCreateTableAs(Query *query, IntoClause *into,
|
||||
const char *queryString,
|
||||
ParamListInfo params, DestReceiver *dest);
|
||||
|
||||
extern void ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
|
||||
ParamListInfo params, char *completionTag);
|
||||
|
||||
|
@@ -67,8 +67,8 @@ extern void ExplainOneUtility(Node *utilityStmt, IntoClause *into,
|
||||
const char *queryString, ParamListInfo params);
|
||||
|
||||
extern void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into,
|
||||
ExplainState *es,
|
||||
const char *queryString, ParamListInfo params);
|
||||
ExplainState *es, const char *queryString,
|
||||
DestReceiver *dest, ParamListInfo params);
|
||||
|
||||
extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc);
|
||||
|
||||
|
28
src/include/commands/matview.h
Normal file
28
src/include/commands/matview.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* matview.h
|
||||
* prototypes for matview.c.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* src/include/commands/matview.h
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef MATVIEW_H
|
||||
#define MATVIEW_H
|
||||
|
||||
#include "nodes/params.h"
|
||||
#include "tcop/dest.h"
|
||||
#include "utils/relcache.h"
|
||||
|
||||
extern void SetRelationIsScannable(Relation relation);
|
||||
|
||||
extern void ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
|
||||
ParamListInfo params, char *completionTag);
|
||||
|
||||
extern DestReceiver *CreateTransientRelDestReceiver(Oid oid);
|
||||
|
||||
#endif /* MATVIEW_H */
|
@@ -78,4 +78,6 @@ extern void AtEOSubXact_on_commit_actions(bool isCommit,
|
||||
extern void RangeVarCallbackOwnsTable(const RangeVar *relation,
|
||||
Oid relId, Oid oldRelId, void *arg);
|
||||
|
||||
extern bool isQueryUsingTempRelation(Query *query);
|
||||
|
||||
#endif /* TABLECMDS_H */
|
||||
|
@@ -18,4 +18,6 @@
|
||||
|
||||
extern Oid DefineView(ViewStmt *stmt, const char *queryString);
|
||||
|
||||
extern void StoreViewQuery(Oid viewOid, Query *viewParse, bool replace);
|
||||
|
||||
#endif /* VIEW_H */
|
||||
|
@@ -61,6 +61,7 @@
|
||||
#define EXEC_FLAG_SKIP_TRIGGERS 0x0010 /* skip AfterTrigger calls */
|
||||
#define EXEC_FLAG_WITH_OIDS 0x0020 /* force OIDs in returned tuples */
|
||||
#define EXEC_FLAG_WITHOUT_OIDS 0x0040 /* force no OIDs in returned tuples */
|
||||
#define EXEC_FLAG_WITH_NO_DATA 0x0080 /* rel scannability doesn't matter */
|
||||
|
||||
|
||||
/*
|
||||
|
@@ -361,6 +361,7 @@ typedef enum NodeTag
|
||||
T_AlterExtensionContentsStmt,
|
||||
T_CreateEventTrigStmt,
|
||||
T_AlterEventTrigStmt,
|
||||
T_RefreshMatViewStmt,
|
||||
|
||||
/*
|
||||
* TAGS FOR PARSE TREE NODES (parsenodes.h)
|
||||
|
@@ -713,6 +713,7 @@ typedef struct RangeTblEntry
|
||||
*/
|
||||
Oid relid; /* OID of the relation */
|
||||
char relkind; /* relation kind (see pg_class.relkind) */
|
||||
bool isResultRel; /* used in target of SELECT INTO or similar */
|
||||
|
||||
/*
|
||||
* Fields valid for a subquery RTE (else NULL):
|
||||
@@ -1135,6 +1136,7 @@ typedef enum ObjectType
|
||||
OBJECT_INDEX,
|
||||
OBJECT_LANGUAGE,
|
||||
OBJECT_LARGEOBJECT,
|
||||
OBJECT_MATVIEW,
|
||||
OBJECT_OPCLASS,
|
||||
OBJECT_OPERATOR,
|
||||
OBJECT_OPFAMILY,
|
||||
@@ -2447,6 +2449,8 @@ typedef struct ExplainStmt
|
||||
* A query written as CREATE TABLE AS will produce this node type natively.
|
||||
* A query written as SELECT ... INTO will be transformed to this form during
|
||||
* parse analysis.
|
||||
* A query written as CREATE MATERIALIZED view will produce this node type,
|
||||
* during parse analysis, since it needs all the same data.
|
||||
*
|
||||
* The "query" field is handled similarly to EXPLAIN, though note that it
|
||||
* can be a SELECT or an EXECUTE, but not other DML statements.
|
||||
@@ -2457,9 +2461,21 @@ typedef struct CreateTableAsStmt
|
||||
NodeTag type;
|
||||
Node *query; /* the query (see comments above) */
|
||||
IntoClause *into; /* destination table */
|
||||
ObjectType relkind; /* type of object */
|
||||
bool is_select_into; /* it was written as SELECT INTO */
|
||||
} CreateTableAsStmt;
|
||||
|
||||
/* ----------------------
|
||||
* REFRESH MATERIALIZED VIEW Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RefreshMatViewStmt
|
||||
{
|
||||
NodeTag type;
|
||||
bool skipData; /* true for WITH NO DATA */
|
||||
RangeVar *relation; /* relation to insert into */
|
||||
} RefreshMatViewStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Checkpoint Statement
|
||||
* ----------------------
|
||||
@@ -2517,7 +2533,7 @@ typedef struct ConstraintsSetStmt
|
||||
typedef struct ReindexStmt
|
||||
{
|
||||
NodeTag type;
|
||||
ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, OBJECT_DATABASE */
|
||||
ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, etc. */
|
||||
RangeVar *relation; /* Table or index to reindex */
|
||||
const char *name; /* name of database to reindex */
|
||||
bool do_system; /* include system tables in database case */
|
||||
|
@@ -80,7 +80,8 @@ typedef struct RangeVar
|
||||
} RangeVar;
|
||||
|
||||
/*
|
||||
* IntoClause - target information for SELECT INTO and CREATE TABLE AS
|
||||
* IntoClause - target information for SELECT INTO, CREATE TABLE AS, and
|
||||
* CREATE MATERIALIZED VIEW
|
||||
*/
|
||||
typedef struct IntoClause
|
||||
{
|
||||
@@ -92,6 +93,7 @@ typedef struct IntoClause
|
||||
OnCommitAction onCommit; /* what do we do at COMMIT? */
|
||||
char *tableSpaceName; /* table space to use, or NULL */
|
||||
bool skipData; /* true for WITH NO DATA */
|
||||
char relkind; /* RELKIND_RELATION or RELKIND_MATVIEW */
|
||||
} IntoClause;
|
||||
|
||||
|
||||
|
@@ -232,6 +232,7 @@ PG_KEYWORD("location", LOCATION, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("lock", LOCK_P, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD)
|
||||
@@ -302,6 +303,7 @@ PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("ref", REF, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD)
|
||||
PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD)
|
||||
PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD)
|
||||
|
@@ -93,7 +93,8 @@ typedef enum
|
||||
DestTuplestore, /* results sent to Tuplestore */
|
||||
DestIntoRel, /* results sent to relation (SELECT INTO) */
|
||||
DestCopyOut, /* results sent to COPY TO code */
|
||||
DestSQLFunction /* results sent to SQL-language func mgr */
|
||||
DestSQLFunction, /* results sent to SQL-language func mgr */
|
||||
DestTransientRel /* results sent to transient relation */
|
||||
} CommandDest;
|
||||
|
||||
/* ----------------
|
||||
|
@@ -461,6 +461,7 @@ extern Datum pg_table_size(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_indexes_size(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_relation_filenode(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_relation_filepath(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_relation_is_scannable(PG_FUNCTION_ARGS);
|
||||
|
||||
/* genfile.c */
|
||||
extern bytea *read_binary_file(const char *filename,
|
||||
|
@@ -83,6 +83,7 @@ typedef struct RelationData
|
||||
BackendId rd_backend; /* owning backend id, if temporary relation */
|
||||
bool rd_islocaltemp; /* rel is a temp rel of this session */
|
||||
bool rd_isnailed; /* rel is nailed in cache */
|
||||
bool rd_isscannable; /* rel can be scanned */
|
||||
bool rd_isvalid; /* relcache entry is valid */
|
||||
char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, 1 =
|
||||
* valid, 2 = temporarily forced */
|
||||
|
Reference in New Issue
Block a user