Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitda9582b

Browse files
committed
Add 'contrib/pg_execplan/' from commit '1b471f8349e64094c46161758a7ab829b450f99f'
git-subtree-dir: contrib/pg_execplangit-subtree-mainline:8722d2cgit-subtree-split:1b471f8
2 parents8722d2c +1b471f8 commitda9582b

File tree

10 files changed

+732
-0
lines changed

10 files changed

+732
-0
lines changed

‎contrib/pg_execplan/LICENSE

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
ExecPlan is released under the PostgreSQL License, a liberal Open Source license, similar to the BSD or MIT licenses.
2+
3+
Copyright (c) 2018-2019, Postgres Professional
4+
Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
5+
Portions Copyright (c) 1994, The Regents of the University of California
6+
7+
Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.
8+
9+
IN NO EVENT SHALL POSTGRES PROFESSIONAL BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF POSTGRES PROFESSIONAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10+
11+
POSTGRES PROFESSIONAL SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND POSTGRES PROFESSIONAL HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

‎contrib/pg_execplan/Makefile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# contrib/pg_execplan/Makefile
2+
3+
MODULE_big = pg_execplan
4+
EXTENSION = pg_execplan
5+
EXTVERSION = 0.1
6+
PGFILEDESC = "pg_execplan"
7+
MODULES = pg_execplan
8+
OBJS = pg_execplan.o$(WIN32RES)
9+
10+
PG_CPPFLAGS = -I$(libpq_srcdir)
11+
SHLIB_LINK_INTERNAL =$(libpq)
12+
13+
DATA_built =$(EXTENSION)--$(EXTVERSION).sql
14+
15+
ifdefUSE_PGXS
16+
PG_CONFIG = pg_config
17+
PGXS :=$(shell$(PG_CONFIG) --pgxs)
18+
include$(PGXS)
19+
else
20+
SHLIB_PREREQS = submake-libpq
21+
subdir = contrib/pg_execplan
22+
top_builddir = ../..
23+
include$(top_builddir)/src/Makefile.global
24+
include$(top_srcdir)/contrib/contrib-global.mk
25+
endif
26+
27+
$(EXTENSION)--$(EXTVERSION).sql: init.sql
28+
cat$^>$@

‎contrib/pg_execplan/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#execplan
2+
PostgreSQL patch & extension for raw query plan execution
3+
4+
This project dedicated to query execution problem in DBMS for computing systems with cluster architecture.
5+
6+
The DBMS may need to execute an identical query plan at each computing node.
7+
Today PostgreSQL can process only SQL statements. But it is not guaranteed, that the planner at each node will construct same query plan, because different statistics, relation sizes e.t.c.
8+
9+
This solution based on postgres-xl approach: plan tree is serialized by the nodeToString() routine.
10+
During serialization we transform all database object identifiers (oid) in each node field to portable representation.
11+
Further, the serialized plan transfer by new libpq routine called`PQsendPlan`.
12+
In this project we use postgres_fdw connections for management of sessions and remote transactions.
13+
Some`repeater` extension used for the demonstration of plan transfer machinery.
14+
The`pg12_devel.patch` patch contains all core changes.
15+
The`scripts` directory contains some simplistic demo tests.

‎contrib/pg_execplan/init.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
\echo Use"CREATE EXTENSION pg_execplan" to load this file. \quit
2+
3+
-- Store plan of a query into a text file.
4+
-- query - query string which will be parsed and planned.
5+
-- filename - path to the file on a disk.
6+
CREATEOR REPLACE FUNCTION @extschema@.pg_store_query_plan(
7+
filenameTEXT,
8+
queryTEXT
9+
)
10+
RETURNS VOIDAS'pg_execplan'
11+
LANGUAGE C;
12+
13+
CREATEOR REPLACE FUNCTION @extschema@.pg_exec_plan(queryTEXT,
14+
planTEXT
15+
)
16+
RETURNS BOOLAS'pg_execplan'
17+
LANGUAGE C;
18+
19+
CREATEOR REPLACE FUNCTION @extschema@.pg_exec_stored_plan(filenameTEXT)
20+
RETURNS BOOLAS'pg_execplan'
21+
LANGUAGE C;

‎contrib/pg_execplan/pg_execplan.c

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
/*
2+
* pg_execplan.c
3+
*
4+
*/
5+
6+
#include"postgres.h"
7+
8+
#include"access/printtup.h"
9+
#include"commands/extension.h"
10+
#include"commands/prepare.h"
11+
#include"executor/executor.h"
12+
#include"nodes/nodes.h"
13+
#include"nodes/plannodes.h"
14+
#include"tcop/pquery.h"
15+
#include"tcop/utility.h"
16+
#include"utils/builtins.h"
17+
#include"utils/memutils.h"
18+
#include"utils/plancache.h"
19+
#include"utils/snapmgr.h"
20+
21+
22+
#defineEXPLAN_DEBUG_LEVEL 0
23+
24+
PG_MODULE_MAGIC;
25+
26+
PG_FUNCTION_INFO_V1(pg_store_query_plan);
27+
PG_FUNCTION_INFO_V1(pg_exec_plan);
28+
PG_FUNCTION_INFO_V1(pg_exec_stored_plan);
29+
30+
void_PG_init(void);
31+
32+
/*
33+
* Module load/unload callback
34+
*/
35+
void
36+
_PG_init(void)
37+
{
38+
return;
39+
}
40+
41+
Datum
42+
pg_store_query_plan(PG_FUNCTION_ARGS)
43+
{
44+
char*query_string=TextDatumGetCString(PG_GETARG_DATUM(1)),
45+
*filename=TextDatumGetCString(PG_GETARG_DATUM(0)),
46+
*plan_string;
47+
intnstmts;
48+
FILE*fout;
49+
MemoryContextoldcontext;
50+
List*parsetree_list;
51+
RawStmt*parsetree;
52+
List*querytree_list,
53+
*plantree_list;
54+
QueryDesc*queryDesc;
55+
size_tstring_len;
56+
57+
if (EXPLAN_DEBUG_LEVEL>0)
58+
elog(LOG,"Store into %s plan of the query %s.",filename,query_string);
59+
60+
oldcontext=MemoryContextSwitchTo(MessageContext);
61+
62+
parsetree_list=pg_parse_query(query_string);
63+
nstmts=list_length(parsetree_list);
64+
if (nstmts!=1)
65+
elog(ERROR,"Query contains %d elements, but must contain only one.",nstmts);
66+
67+
parsetree= (RawStmt*)linitial(parsetree_list);
68+
querytree_list=pg_analyze_and_rewrite(parsetree,query_string,NULL,0);
69+
plantree_list=pg_plan_queries(querytree_list,CURSOR_OPT_PARALLEL_OK,NULL);
70+
71+
queryDesc=CreateQueryDesc((PlannedStmt*)linitial(plantree_list),
72+
query_string,
73+
InvalidSnapshot,
74+
InvalidSnapshot,
75+
None_Receiver,
76+
0,
77+
0);
78+
79+
if (EXPLAN_DEBUG_LEVEL>0)
80+
elog(INFO,"BEFORE writing %s ...",filename);
81+
82+
fout=fopen(filename,"wb");
83+
Assert(fout!=NULL);
84+
string_len=strlen(query_string);
85+
fwrite(&string_len,sizeof(size_t),1,fout);
86+
fwrite(query_string,sizeof(char),string_len,fout);
87+
88+
set_portable_output(true);
89+
plan_string=nodeToString(queryDesc->plannedstmt);
90+
set_portable_output(false);
91+
string_len=strlen(plan_string);
92+
fwrite(&string_len,sizeof(size_t),1,fout);
93+
fwrite(plan_string,sizeof(char),string_len,fout);
94+
95+
fclose(fout);
96+
MemoryContextSwitchTo(oldcontext);
97+
PG_RETURN_VOID();
98+
}
99+
100+
staticvoid
101+
exec_plan(char*query_string,char*plan_string)
102+
{
103+
PlannedStmt*pstmt;
104+
ParamListInfoparamLI=NULL;
105+
CachedPlanSource*psrc;
106+
CachedPlan*cplan;
107+
QueryDesc*queryDesc;
108+
DestReceiver*receiver;
109+
inteflags=0;
110+
111+
PG_TRY();
112+
{
113+
set_portable_input(true);
114+
pstmt= (PlannedStmt*)stringToNode(plan_string);
115+
set_portable_input(false);
116+
}
117+
PG_CATCH();
118+
{
119+
elog(INFO,"BAD PLAN: %s. Query: %s",plan_string,query_string);
120+
PG_RE_THROW();
121+
}
122+
PG_END_TRY();
123+
124+
if (EXPLAN_DEBUG_LEVEL>0)
125+
elog(INFO,"query: %s\n",query_string);
126+
if (EXPLAN_DEBUG_LEVEL>1)
127+
elog(INFO,"\nplan: %s\n",plan_string);
128+
129+
psrc=CreateCachedPlan(NULL,query_string,NULL);
130+
CompleteCachedPlan(psrc,NIL,NULL,NULL,0,NULL,NULL,
131+
CURSOR_OPT_GENERIC_PLAN, false);
132+
133+
SetRemoteSubplan(psrc,pstmt);
134+
cplan=GetCachedPlan(psrc,paramLI, false);
135+
136+
receiver=CreateDestReceiver(DestLog);
137+
138+
PG_TRY();
139+
{
140+
queryDesc=CreateQueryDesc(pstmt,
141+
query_string,
142+
GetActiveSnapshot(),
143+
InvalidSnapshot,
144+
receiver,
145+
paramLI,
146+
0);
147+
ExecutorStart(queryDesc,eflags);
148+
PushActiveSnapshot(queryDesc->snapshot);
149+
ExecutorRun(queryDesc,ForwardScanDirection,0);
150+
PopActiveSnapshot();
151+
ExecutorFinish(queryDesc);
152+
ExecutorEnd(queryDesc);
153+
FreeQueryDesc(queryDesc);
154+
}
155+
PG_CATCH();
156+
{
157+
elog(INFO,"BAD QUERY: '%s'.",query_string);
158+
ReleaseCachedPlan(cplan, false);
159+
PG_RE_THROW();
160+
}
161+
PG_END_TRY();
162+
163+
receiver->rDestroy(receiver);
164+
ReleaseCachedPlan(cplan, false);
165+
166+
if (EXPLAN_DEBUG_LEVEL>0)
167+
elog(INFO,"query execution finished.\n");
168+
}
169+
170+
Datum
171+
pg_exec_plan(PG_FUNCTION_ARGS)
172+
{
173+
char*query_string=TextDatumGetCString(PG_GETARG_DATUM(0));
174+
char*plan_string=TextDatumGetCString(PG_GETARG_DATUM(1));
175+
176+
char*dec_query,
177+
*dec_plan;
178+
intdec_query_len,
179+
dec_query_len1,
180+
dec_plan_len,
181+
dec_plan_len1;
182+
183+
Assert(query_string!=NULL);
184+
Assert(plan_string!=NULL);
185+
186+
dec_query_len=b64_dec_len(query_string,strlen(query_string)+1)+1;
187+
dec_query=palloc0(dec_query_len+1);
188+
dec_query_len1=b64_decode(query_string,strlen(query_string),dec_query);
189+
Assert(dec_query_len>dec_query_len1);
190+
191+
dec_plan_len=b64_dec_len(plan_string,strlen(plan_string)+1);
192+
dec_plan=palloc0(dec_plan_len+1);
193+
dec_plan_len1=b64_decode(plan_string,strlen(plan_string),dec_plan);
194+
Assert(dec_plan_len>dec_plan_len1);
195+
196+
exec_plan(dec_query,dec_plan);
197+
pfree(dec_query);
198+
pfree(dec_plan);
199+
PG_RETURN_BOOL(true);
200+
}
201+
202+
staticvoid
203+
LoadPlanFromFile(constchar*filename,char**query_string,char**plan_string)
204+
{
205+
FILE*fin;
206+
size_tstring_len;
207+
intnelems;
208+
209+
fin=fopen(filename,"rb");
210+
Assert(fin!=NULL);
211+
212+
nelems=fread(&string_len,sizeof(size_t),1,fin);
213+
Assert(nelems==1);
214+
*query_string=palloc0(string_len+1);
215+
nelems=fread(*query_string,sizeof(char),string_len,fin);
216+
Assert(nelems==string_len);
217+
218+
nelems=fread(&string_len,sizeof(size_t),1,fin);
219+
Assert(nelems==1);
220+
*plan_string=palloc0(string_len+1);
221+
nelems=fread(*plan_string,sizeof(char),string_len,fin);
222+
Assert(nelems==string_len);
223+
224+
fclose(fin);
225+
226+
}
227+
228+
Datum
229+
pg_exec_stored_plan(PG_FUNCTION_ARGS)
230+
{
231+
char*filename=TextDatumGetCString(PG_GETARG_DATUM(0)),
232+
*query_string=NULL,
233+
*plan_string=NULL;
234+
235+
LoadPlanFromFile(filename,&query_string,&plan_string);
236+
exec_plan(query_string,plan_string);
237+
PG_RETURN_BOOL(true);
238+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# pg_execplan extension
2+
comment = 'Execute raw query plan on remote node'
3+
default_version = '0.1'
4+
module_pathname = '$libdir/pg_execplan'
5+
relocatable = false
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
CREATESCHEMAtests;
2+
SET search_path='tests';
3+
4+
CREATETYPEint42;
5+
-- Make dummy I/O routines using the existing internal support for int4, text
6+
CREATEFUNCTIONint42_in(cstring)
7+
RETURNS int42
8+
AS'int4in'
9+
LANGUAGE internal STRICT IMMUTABLE;
10+
CREATEFUNCTIONint42_out(int42)
11+
RETURNS cstring
12+
AS'int4out'
13+
LANGUAGE internal STRICT IMMUTABLE;
14+
15+
CREATETYPEint42 (
16+
internallength=4,
17+
input= int42_in,
18+
output= int42_out,
19+
alignment= int4,
20+
default=42,
21+
passedbyvalue
22+
);
23+
24+
-- RELOID, TYPEOID
25+
CREATETABLEtests.t1 (id int42);
26+
CREATETABLEt2 (idint, payloadTEXT, par1INT);
27+
28+
CREATEFUNCTIONselect1(tidINT) RETURNS VOIDAS $$
29+
BEGIN
30+
INSERT INTOtests.t2 (id, payload, par1)VALUES (1,'qwe',2);
31+
END;
32+
$$ LANGUAGE plpgsql;
33+
34+
-- COLLOID
35+
CREATE COLLATION test1 (locale='en_US.utf8');
36+
CREATETABLEttest1 (
37+
idserial,
38+
atext COLLATE test1,
39+
btext COLLATE test1
40+
);
41+
INSERT INTO ttest1 (a, b)VALUES ('one','one');
42+
INSERT INTO ttest1 (a, b)VALUES ('one','two');
43+
44+
-- OPEROID
45+
CREATEOPERATORpublic.### (
46+
leftarg=numeric,
47+
rightarg=numeric,
48+
procedure= numeric_add
49+
);
50+
51+
-- Different types and parameter types
52+
CREATETYPEbug_statusAS ENUM ('new','open','closed');
53+
54+
CREATETABLEpublic.bug (
55+
idserial,
56+
descriptionTEXT,
57+
status bug_status
58+
);
59+
60+
INSERT INTOpublic.bug (description, status)VALUES ('abc','open');
61+
INSERT INTOpublic.bug (description, status)VALUES ('abc1','closed');
62+
63+
CREATETABLEpublic.bug1 (
64+
idserial,
65+
status bug_status
66+
);
67+
INSERT INTOpublic.bug1 (status)VALUES ('new');
68+
INSERT INTOpublic.bug1 (status)VALUES ('new');
69+
INSERT INTOpublic.bug1 (status)VALUES ('closed');
70+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp