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

Commit84682ff

Browse files
committed
Add support for ALTER TABLE .. ATTACH PARTITION
1 parent50c078b commit84682ff

File tree

7 files changed

+324
-3
lines changed

7 files changed

+324
-3
lines changed

‎Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ OBJS = src/init.o src/relation_info.o src/utils.o src/partition_filter.o \
88
src/hooks.o src/nodes_common.o src/xact_handling.o src/utility_stmt_hooking.o\
99
src/planner_tree_modification.o src/debug_print.o src/partition_creation.o\
1010
src/compat/pg_compat.o src/compat/rowmarks_fix.o src/partition_router.o\
11-
src/partition_overseer.o$(WIN32RES)
11+
src/partition_overseer.osrc/declarative.o$(WIN32RES)
1212

1313
ifdefUSE_PGXS
1414
overridePG_CPPFLAGS += -I$(CURDIR)/src/include

‎src/declarative.c

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#include"declarative.h"
2+
#include"utils.h"
3+
4+
#include"fmgr.h"
5+
#include"access/htup_details.h"
6+
#include"catalog/namespace.h"
7+
#include"catalog/pg_type.h"
8+
#include"catalog/pg_proc.h"
9+
#include"nodes/nodeFuncs.h"
10+
#include"parser/parse_func.h"
11+
#include"parser/parse_coerce.h"
12+
#include"utils/int8.h"
13+
#include"utils/lsyscache.h"
14+
#include"utils/builtins.h"
15+
#include"utils/int8.h"
16+
#include"utils/lsyscache.h"
17+
#include"utils/syscache.h"
18+
#include"utils/varbit.h"
19+
20+
/*
21+
* Modifies query of declarative partitioning commands,
22+
* There is a little hack here, ATTACH PARTITION command
23+
* expects relation with REL_PARTITIONED_TABLE relkind.
24+
* To avoid this check we negate subtype, and then after the checks
25+
* we set it back (look `is_pathman_related_partitioning_cmd`)
26+
*/
27+
void
28+
modify_declative_partitioning_query(Query*query)
29+
{
30+
if (query->commandType!=CMD_UTILITY)
31+
return;
32+
33+
if (IsA(query->utilityStmt,AlterTableStmt))
34+
{
35+
ListCell*lcmd;
36+
Oidrelid;
37+
38+
AlterTableStmt*stmt= (AlterTableStmt*)query->utilityStmt;
39+
relid=RangeVarGetRelid(stmt->relation,NoLock, true);
40+
if (get_pathman_relation_info(relid)!=NULL)
41+
{
42+
foreach(lcmd,stmt->cmds)
43+
{
44+
AlterTableCmd*cmd= (AlterTableCmd*)lfirst(lcmd);
45+
switch (cmd->subtype)
46+
{
47+
caseAT_AttachPartition:
48+
caseAT_DetachPartition:
49+
cmd->subtype=-cmd->subtype;
50+
break;
51+
default:
52+
break;
53+
}
54+
}
55+
}
56+
}
57+
}
58+
59+
/* is it one of declarative partitioning commands? */
60+
boolis_pathman_related_partitioning_cmd(Node*parsetree)
61+
{
62+
if (IsA(parsetree,AlterTableStmt))
63+
{
64+
ListCell*lc;
65+
AlterTableStmt*stmt= (AlterTableStmt*)parsetree;
66+
intcnt=0;
67+
68+
foreach(lc,stmt->cmds)
69+
{
70+
AlterTableCmd*cmd= (AlterTableCmd*)lfirst(lc);
71+
intsubtype=cmd->subtype;
72+
73+
if (subtype<0)
74+
subtype=-subtype;
75+
76+
switch (subtype)
77+
{
78+
caseAT_AttachPartition:
79+
caseAT_DetachPartition:
80+
/*
81+
* we need to fix all subtypes,
82+
* possibly we're not going to handle this
83+
*/
84+
cmd->subtype=-(cmd->subtype);
85+
continue;
86+
default:
87+
cnt++;
88+
}
89+
}
90+
91+
return (cnt==0);
92+
}
93+
return false;
94+
}
95+
96+
staticFuncExpr*
97+
make_fn_expr(OidfuncOid,List*args)
98+
{
99+
FuncExpr*fn_expr;
100+
HeapTupleprocTup;
101+
Form_pg_procprocStruct;
102+
103+
procTup=SearchSysCache1(PROCOID,ObjectIdGetDatum(funcOid));
104+
if (!HeapTupleIsValid(procTup))
105+
elog(ERROR,"cache lookup failed for function %u",funcOid);
106+
procStruct= (Form_pg_proc)GETSTRUCT(procTup);
107+
108+
fn_expr=makeFuncExpr(funcOid,procStruct->prorettype,args,
109+
InvalidOid,InvalidOid,COERCE_EXPLICIT_CALL);
110+
ReleaseSysCache(procTup);
111+
returnfn_expr;
112+
}
113+
114+
/*
115+
* Transform one constant in a partition bound spec
116+
*/
117+
staticConst*
118+
transform_bound_value(ParseState*pstate,A_Const*con,
119+
OidcolType,int32colTypmod)
120+
{
121+
Node*value;
122+
123+
/* Make it into a Const */
124+
value= (Node*)make_const(pstate,&con->val,con->location);
125+
126+
/* Coerce to correct type */
127+
value=coerce_to_target_type(pstate,
128+
value,exprType(value),
129+
colType,
130+
colTypmod,
131+
COERCION_ASSIGNMENT,
132+
COERCE_IMPLICIT_CAST,
133+
-1);
134+
135+
if (value==NULL)
136+
ereport(ERROR,
137+
(errcode(ERRCODE_DATATYPE_MISMATCH),
138+
errmsg("specified value cannot be cast to type %s",
139+
format_type_be(colType)),
140+
parser_errposition(pstate,con->location)));
141+
142+
/* Simplify the expression, in case we had a coercion */
143+
if (!IsA(value,Const))
144+
value= (Node*)expression_planner((Expr*)value);
145+
146+
/* Fail if we don't have a constant (i.e., non-immutable coercion) */
147+
if (!IsA(value,Const))
148+
ereport(ERROR,
149+
(errcode(ERRCODE_DATATYPE_MISMATCH),
150+
errmsg("specified value cannot be cast to type %s",
151+
format_type_be(colType)),
152+
errdetail("The cast requires a non-immutable conversion."),
153+
errhint("Try putting the literal value in single quotes."),
154+
parser_errposition(pstate,con->location)));
155+
156+
return (Const*)value;
157+
}
158+
159+
/* handle ALTER TABLE .. ATTACH PARTITION command */
160+
voidhandle_attach_partition(AlterTableStmt*stmt,AlterTableCmd*cmd)
161+
{
162+
Oidparent_relid,
163+
partition_relid,
164+
proc_args[]= {REGCLASSOID,REGCLASSOID,
165+
ANYELEMENTOID,ANYELEMENTOID };
166+
167+
List*proc_name;
168+
FmgrInfoproc_flinfo;
169+
FunctionCallInfoDataproc_fcinfo;
170+
char*pathman_schema;
171+
PartitionRangeDatum*ldatum,
172+
*rdatum;
173+
Const*lval,
174+
*rval;
175+
A_Const*con;
176+
List*fn_args;
177+
ParseState*pstate=make_parsestate(NULL);
178+
constPartRelationInfo*prel;
179+
180+
PartitionCmd*pcmd= (PartitionCmd*)cmd->def;
181+
182+
Assert(cmd->subtype==AT_AttachPartition);
183+
184+
parent_relid=RangeVarGetRelid(stmt->relation,NoLock, false);
185+
if ((prel=get_pathman_relation_info(parent_relid))==NULL)
186+
elog(ERROR,"relation is not partitioned");
187+
188+
partition_relid=RangeVarGetRelid(pcmd->name,NoLock, false);
189+
190+
/* Fetch pg_pathman's schema */
191+
pathman_schema=get_namespace_name(get_pathman_schema());
192+
193+
/* Build function's name */
194+
proc_name=list_make2(makeString(pathman_schema),
195+
makeString(CppAsString(attach_range_partition)));
196+
197+
ldatum= (PartitionRangeDatum*)linitial(pcmd->bound->lowerdatums);
198+
con=castNode(A_Const,ldatum->value);
199+
lval=transform_bound_value(pstate,con,prel->ev_type,prel->ev_typmod);
200+
201+
rdatum= (PartitionRangeDatum*)linitial(pcmd->bound->upperdatums);
202+
con=castNode(A_Const,rdatum->value);
203+
rval=transform_bound_value(pstate,con,prel->ev_type,prel->ev_typmod);
204+
205+
/* Lookup function's Oid and get FmgrInfo */
206+
fmgr_info(LookupFuncName(proc_name,4,proc_args, false),&proc_flinfo);
207+
208+
InitFunctionCallInfoData(proc_fcinfo,&proc_flinfo,
209+
4,InvalidOid,NULL,NULL);
210+
proc_fcinfo.arg[0]=ObjectIdGetDatum(parent_relid);
211+
proc_fcinfo.argnull[0]= false;
212+
proc_fcinfo.arg[1]=ObjectIdGetDatum(partition_relid);
213+
proc_fcinfo.argnull[1]= false;
214+
215+
/* Make function expression, we will need it to determine argument types */
216+
fn_args=list_make4(NULL,NULL,lval,rval);
217+
proc_fcinfo.flinfo->fn_expr=
218+
(Node*)make_fn_expr(proc_fcinfo.flinfo->fn_oid,fn_args);
219+
220+
if ((!list_length(pcmd->bound->lowerdatums))||
221+
(!list_length(pcmd->bound->upperdatums)))
222+
elog(ERROR,"provide start and end value for range partition");
223+
224+
proc_fcinfo.arg[2]=lval->constvalue;
225+
proc_fcinfo.argnull[2]=ldatum->infinite||lval->constisnull;
226+
proc_fcinfo.arg[3]=rval->constvalue;
227+
proc_fcinfo.argnull[3]=rdatum->infinite||rval->constisnull;
228+
229+
/* Invoke the callback */
230+
FunctionCallInvoke(&proc_fcinfo);
231+
}
232+
233+
/* handle ALTER TABLE .. DETACH PARTITION command */
234+
voidhandle_detach_partition(AlterTableStmt*stmt,AlterTableCmd*cmd)
235+
{
236+
Assert(cmd->subtype==AT_DetachPartition);
237+
}

‎src/hooks.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include"compat/pg_compat.h"
1414
#include"compat/rowmarks_fix.h"
1515

16+
#include"declarative.h"
1617
#include"hooks.h"
1718
#include"init.h"
1819
#include"partition_filter.h"
@@ -766,6 +767,8 @@ pathman_post_parse_analyze_hook(ParseState *pstate, Query *query)
766767
{
767768
load_config();/* perform main cache initialization */
768769
}
770+
if (!IsPathmanReady())
771+
return;
769772

770773
/* Process inlined SQL functions (we've already entered planning stage) */
771774
if (IsPathmanReady()&&get_planner_calls_count()>0)
@@ -812,7 +815,10 @@ pathman_post_parse_analyze_hook(ParseState *pstate, Query *query)
812815

813816
/* Modify query tree if needed */
814817
pathman_transform_query(query,NULL);
818+
return;
815819
}
820+
821+
pathman_post_analyze_query(query);
816822
}
817823

818824
/*
@@ -950,6 +956,31 @@ pathman_process_utility_hook(Node *first_arg,
950956
get_attname_compat(relation_oid,attr_number),
951957
get_rel_name(relation_oid))));
952958
}
959+
elseif (is_pathman_related_partitioning_cmd(parsetree))
960+
{
961+
/* we can handle all the partitioning commands */
962+
if (IsA(parsetree,AlterTableStmt))
963+
{
964+
ListCell*lc;
965+
AlterTableStmt*stmt= (AlterTableStmt*)parsetree;
966+
967+
foreach(lc,stmt->cmds)
968+
{
969+
AlterTableCmd*cmd= (AlterTableCmd*)lfirst(lc);
970+
switch (cmd->subtype)
971+
{
972+
caseAT_AttachPartition:
973+
handle_attach_partition(stmt,cmd);
974+
return;
975+
caseAT_DetachPartition:
976+
handle_detach_partition(stmt,cmd);
977+
return;
978+
default:
979+
elog(ERROR,"can't handle this command");
980+
}
981+
}
982+
}
983+
}
953984
}
954985

955986
/* Finally call process_utility_hook_next or standard_ProcessUtility */

‎src/include/declarative.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndefDECLARATIVE_H
2+
#defineDECLARATIVE_H
3+
4+
#include"postgres.h"
5+
#include"nodes/nodes.h"
6+
#include"nodes/parsenodes.h"
7+
8+
typedefenumDeclarativeCommandType {
9+
DP_ATTACH,/* ALTER TABLE .. ATTACH PARTITION */
10+
DP_DETACH/* ALTER TABLE .. DETACH PARTITION */
11+
}DeclarativeCommandType;
12+
13+
voidmodify_declative_partitioning_query(Query*query);
14+
boolis_pathman_related_partitioning_cmd(Node*parsetree);
15+
16+
/* actual actions */
17+
voidhandle_attach_partition(AlterTableStmt*stmt,AlterTableCmd*cmd);
18+
voidhandle_detach_partition(AlterTableStmt*stmt,AlterTableCmd*cmd);
19+
20+
#endif/* DECLARATIVE_H */

‎src/include/planner_tree_modification.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ void state_tree_visitor(PlanState *state,
3434
void (*visitor) (PlanState*state,void*context),
3535
void*context);
3636

37-
/* Query tree rewritingutility */
37+
/* Query tree rewritingutilities */
3838
voidpathman_transform_query(Query*parse,ParamListInfoparams);
39+
voidpathman_post_analyze_query(Query*parse);
3940

4041
/* These functions scribble on Plan tree */
4142
Plan*add_partition_filters(List*rtable,Plan*plan);

‎src/planner_tree_modification.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include"compat/rowmarks_fix.h"
1414

15+
#include"declarative.h"
1516
#include"partition_filter.h"
1617
#include"partition_router.h"
1718
#include"partition_overseer.h"
@@ -107,6 +108,7 @@ typedef struct
107108
}adjust_appendrel_varnos_cxt;
108109

109110
staticboolpathman_transform_query_walker(Node*node,void*context);
111+
staticboolpathman_post_analyze_query_walker(Node*node,void*context);
110112

111113
staticvoiddisable_standard_inheritance(Query*parse,transform_query_cxt*context);
112114
staticvoidhandle_modification_query(Query*parse,transform_query_cxt*context);
@@ -337,6 +339,12 @@ pathman_transform_query(Query *parse, ParamListInfo params)
337339
pathman_transform_query_walker((Node*)parse, (void*)&context);
338340
}
339341

342+
void
343+
pathman_post_analyze_query(Query*parse)
344+
{
345+
pathman_post_analyze_query_walker((Node*)parse,NULL);
346+
}
347+
340348
/* Walker for pathman_transform_query() */
341349
staticbool
342350
pathman_transform_query_walker(Node*node,void*context)
@@ -410,6 +418,31 @@ pathman_transform_query_walker(Node *node, void *context)
410418
context);
411419
}
412420

421+
staticbool
422+
pathman_post_analyze_query_walker(Node*node,void*context)
423+
{
424+
if (node==NULL)
425+
return false;
426+
427+
elseif (IsA(node,Query))
428+
{
429+
Query*query= (Query*)node;
430+
431+
/* Make changes for declarative syntax */
432+
modify_declative_partitioning_query(query);
433+
434+
/* Handle Query node */
435+
returnquery_tree_walker(query,
436+
pathman_post_analyze_query_walker,
437+
context,
438+
0);
439+
}
440+
441+
/* Handle expression subtree */
442+
returnexpression_tree_walker(node,
443+
pathman_post_analyze_query_walker,
444+
context);
445+
}
413446

414447
/*
415448
* ----------------------

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp