diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index ee1bcb84e28..18a5af6b919 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1363,6 +1363,96 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used); } +/* + * plan_is_disabled + * Checks if the given plan node type was disabled during query planning. + * This is evident by the disable_node field being higher than the sum of + * the disabled_node field from the plan's children. + */ +static bool +plan_is_disabled(Plan *plan) +{ + int child_disabled_nodes; + + /* The node is certainly not disabled if this is zero */ + if (plan->disabled_nodes == 0) + return false; + + child_disabled_nodes = 0; + + /* + * Handle special nodes first. Children of BitmapOrs and BitmapAnds can't + * be disabled, so no need to handle those specifically. + */ + if (IsA(plan, Append)) + { + ListCell *lc; + Append *aplan = (Append *) plan; + + /* + * Sum the Append childrens' disabled_nodes. This purposefully + * includes any run-time pruned children. Ignoring those could give + * us the incorrect number of disabled nodes. + */ + foreach(lc, aplan->appendplans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else if (IsA(plan, MergeAppend)) + { + ListCell *lc; + MergeAppend *maplan = (MergeAppend *) plan; + + /* + * Sum the MergeAppend childrens' disabled_nodes. This purposefully + * includes any run-time pruned children. Ignoring those could give + * us the incorrect number of disabled nodes. + */ + foreach(lc, maplan->mergeplans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else if (IsA(plan, SubqueryScan)) + child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes; + else if (IsA(plan, CustomScan)) + { + ListCell *lc; + CustomScan *cplan = (CustomScan *) plan; + + foreach(lc, cplan->custom_plans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else + { + /* + * Else, sum up disabled_nodes from the plan's inner and outer side. + */ + if (outerPlan(plan)) + child_disabled_nodes += outerPlan(plan)->disabled_nodes; + if (innerPlan(plan)) + child_disabled_nodes += innerPlan(plan)->disabled_nodes; + } + + /* + * It's disabled if the plan's disable_nodes is higher than the sum of its + * child's plan disabled_nodes. + */ + if (plan->disabled_nodes > child_disabled_nodes) + return true; + + return false; +} + /* * ExplainNode - * Appends a description of a plan tree to es->str @@ -1399,6 +1489,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainWorkersState *save_workers_state = es->workers_state; int save_indent = es->indent; bool haschildren; + bool isdisabled; /* * Prepare per-worker output buffers, if needed. We'll append the data in @@ -1914,9 +2005,10 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->format == EXPLAIN_FORMAT_TEXT) appendStringInfoChar(es->str, '\n'); - if (plan->disabled_nodes != 0) - ExplainPropertyInteger("Disabled Nodes", NULL, plan->disabled_nodes, - es); + + isdisabled = plan_is_disabled(plan); + if (es->format != EXPLAIN_FORMAT_TEXT || isdisabled) + ExplainPropertyBool("Disabled", isdisabled, es); /* prepare per-worker general execution details */ if (es->workers_state && es->verbose) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 0d195a07ffc..c13586c537e 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -6149,6 +6149,7 @@ make_sort(Plan *lefttree, int numCols, plan = &node->plan; plan->targetlist = lefttree->targetlist; + plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 495deb606e2..1e682565d13 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -2944,23 +2944,20 @@ GROUP BY c1.w, c1.z; QUERY PLAN ----------------------------------------------------- GroupAggregate - Disabled Nodes: 2 Group Key: c1.w, c1.z -> Sort - Disabled Nodes: 2 Sort Key: c1.w, c1.z, c1.x, c1.y -> Merge Join - Disabled Nodes: 2 Merge Cond: (c1.x = c2.x) -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 - Disabled Nodes: 1 + Disabled: true -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 - Disabled Nodes: 1 -(17 rows) + Disabled: true +(14 rows) SELECT avg(c1.f ORDER BY c1.x, c1.y) FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x @@ -2982,24 +2979,21 @@ GROUP BY c1.y,c1.x,c2.x; QUERY PLAN ----------------------------------------------------- Group - Disabled Nodes: 2 Group Key: c1.x, c1.y -> Incremental Sort - Disabled Nodes: 2 Sort Key: c1.x, c1.y Presorted Key: c1.x -> Merge Join - Disabled Nodes: 2 Merge Cond: (c1.x = c2.x) -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 - Disabled Nodes: 1 + Disabled: true -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 - Disabled Nodes: 1 -(18 rows) + Disabled: true +(15 rows) EXPLAIN (COSTS OFF) SELECT c1.y,c1.x FROM group_agg_pk c1 @@ -3009,24 +3003,21 @@ GROUP BY c1.y,c2.x,c1.x; QUERY PLAN ----------------------------------------------------- Group - Disabled Nodes: 2 Group Key: c2.x, c1.y -> Incremental Sort - Disabled Nodes: 2 Sort Key: c2.x, c1.y Presorted Key: c2.x -> Merge Join - Disabled Nodes: 2 Merge Cond: (c1.x = c2.x) -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 - Disabled Nodes: 1 + Disabled: true -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 - Disabled Nodes: 1 -(18 rows) + Disabled: true +(15 rows) RESET enable_nestloop; RESET enable_hashjoin; diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out index d3f4c7e08c3..def78ef8583 100644 --- a/src/test/regress/expected/btree_index.out +++ b/src/test/regress/expected/btree_index.out @@ -335,12 +335,11 @@ select proname from pg_proc where proname ilike 'ri%foo' order by 1; QUERY PLAN ---------------------------------------------- Sort - Disabled Nodes: 1 Sort Key: proname -> Seq Scan on pg_proc - Disabled Nodes: 1 + Disabled: true Filter: (proname ~~* 'ri%foo'::text) -(6 rows) +(5 rows) reset enable_seqscan; reset enable_indexscan; diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out index 31345295c11..faa376e060c 100644 --- a/src/test/regress/expected/collate.icu.utf8.out +++ b/src/test/regress/expected/collate.icu.utf8.out @@ -989,7 +989,7 @@ select * from collate_test1 where b ilike 'abc'; QUERY PLAN ------------------------------- Seq Scan on collate_test1 - Disabled Nodes: 1 + Disabled: true Filter: (b ~~* 'abc'::text) (3 rows) @@ -1005,7 +1005,7 @@ select * from collate_test1 where b ilike 'ABC'; QUERY PLAN ------------------------------- Seq Scan on collate_test1 - Disabled Nodes: 1 + Disabled: true Filter: (b ~~* 'ABC'::text) (3 rows) diff --git a/src/test/regress/expected/explain.out b/src/test/regress/expected/explain.out index d01c304c24d..dcbdaa03885 100644 --- a/src/test/regress/expected/explain.out +++ b/src/test/regress/expected/explain.out @@ -104,6 +104,7 @@ select explain_filter('explain (analyze, buffers, format xml) select * from int8 N.N + N + N + + false + N + N + N+ @@ -152,6 +153,7 @@ select explain_filter('explain (analyze, serialize, buffers, format yaml) select Actual Total Time: N.N + Actual Rows: N + Actual Loops: N + + Disabled: false + Shared Hit Blocks: N + Shared Read Blocks: N + Shared Dirtied Blocks: N + @@ -213,6 +215,7 @@ select explain_filter('explain (buffers, format json) select * from int8_tbl i8' "Total Cost": N.N, + "Plan Rows": N, + "Plan Width": N, + + "Disabled": false, + "Shared Hit Blocks": N, + "Shared Read Blocks": N, + "Shared Dirtied Blocks": N, + @@ -262,6 +265,7 @@ select explain_filter('explain (analyze, buffers, format json) select * from int "Actual Total Time": N.N, + "Actual Rows": N, + "Actual Loops": N, + + "Disabled": false, + "Shared Hit Blocks": N, + "Shared Read Blocks": N, + "Shared Dirtied Blocks": N, + @@ -370,6 +374,7 @@ select explain_filter('explain (memory, summary, format yaml) select * from int8 Total Cost: N.N + Plan Rows: N + Plan Width: N + + Disabled: false + Planning: + Memory Used: N + Memory Allocated: N + @@ -394,7 +399,8 @@ select explain_filter('explain (memory, analyze, format json) select * from int8 "Actual Startup Time": N.N, + "Actual Total Time": N.N, + "Actual Rows": N, + - "Actual Loops": N + + "Actual Loops": N, + + "Disabled": false + }, + "Planning": { + "Memory Used": N, + @@ -497,6 +503,7 @@ select jsonb_pretty( "string4" + ], + "Schema": "public", + + "Disabled": false, + "Node Type": "Seq Scan", + "Plan Rows": 0, + "Plan Width": 0, + @@ -540,6 +547,7 @@ select jsonb_pretty( "stringu2", + "string4" + ], + + "Disabled": false, + "Sort Key": [ + "tenk1.tenthous" + ], + @@ -586,6 +594,7 @@ select jsonb_pretty( "stringu2", + "string4" + ], + + "Disabled": false, + "Node Type": "Gather Merge", + "Plan Rows": 0, + "Plan Width": 0, + diff --git a/src/test/regress/expected/incremental_sort.out b/src/test/regress/expected/incremental_sort.out index c561b62b2db..2df7a5db124 100644 --- a/src/test/regress/expected/incremental_sort.out +++ b/src/test/regress/expected/incremental_sort.out @@ -538,6 +538,7 @@ select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from ------------------------------------------------- [ + { + + "Disabled": false, + "Sort Key": [ + "t.a", + "t.b" + @@ -701,19 +702,17 @@ explain (costs off) select * from t left join (select * from (select * from t or QUERY PLAN ------------------------------------------------ Nested Loop Left Join - Disabled Nodes: 1 Join Filter: (t_1.a = t.a) -> Seq Scan on t Filter: (a = ANY ('{1,2}'::integer[])) -> Incremental Sort - Disabled Nodes: 1 Sort Key: t_1.a, t_1.b Presorted Key: t_1.a -> Sort - Disabled Nodes: 1 + Disabled: true Sort Key: t_1.a -> Seq Scan on t t_1 -(13 rows) +(11 rows) select * from t left join (select * from (select * from t order by a) v order by a, b) s on s.a = t.a where t.a in (1, 2); a | b | a | b @@ -744,6 +743,7 @@ select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from ------------------------------------------------- [ + { + + "Disabled": false, + "Sort Key": [ + "t.a", + "t.b" + diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index dbb748a2d2f..c9defd7e9db 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1614,7 +1614,6 @@ explain (verbose, costs off) select * from matest0 order by 1-id; QUERY PLAN ------------------------------------------------------------------------ Merge Append - Disabled Nodes: 1 Sort Key: ((1 - matest0.id)) -> Index Scan using matest0i on public.matest0 matest0_1 Output: matest0_1.id, matest0_1.name, (1 - matest0_1.id) @@ -1624,11 +1623,11 @@ explain (verbose, costs off) select * from matest0 order by 1-id; Output: matest0_3.id, matest0_3.name, ((1 - matest0_3.id)) Sort Key: ((1 - matest0_3.id)) -> Seq Scan on public.matest2 matest0_3 - Disabled Nodes: 1 + Disabled: true Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id) -> Index Scan using matest3i on public.matest3 matest0_4 Output: matest0_4.id, matest0_4.name, (1 - matest0_4.id) -(15 rows) +(14 rows) select * from matest0 order by 1-id; id | name diff --git a/src/test/regress/expected/insert_conflict.out b/src/test/regress/expected/insert_conflict.out index 5cb9cde0305..fdd0f6c8f25 100644 --- a/src/test/regress/expected/insert_conflict.out +++ b/src/test/regress/expected/insert_conflict.out @@ -218,6 +218,7 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb "Async Capable": false, + "Relation Name": "insertconflicttest", + "Alias": "insertconflicttest", + + "Disabled": false, + "Conflict Resolution": "UPDATE", + "Conflict Arbiter Indexes": ["key_index"], + "Conflict Filter": "(insertconflicttest.fruit <> 'Lime'::text)",+ @@ -226,7 +227,8 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb "Node Type": "Result", + "Parent Relationship": "Outer", + "Parallel Aware": false, + - "Async Capable": false + + "Async Capable": false, + + "Disabled": false + } + ] + } + diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 12abd3a0e7a..756c2e24965 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -8010,15 +8010,14 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS QUERY PLAN --------------------------------------------------------- Nested Loop Anti Join - Disabled Nodes: 1 -> Seq Scan on skip_fetch t1 - Disabled Nodes: 1 + Disabled: true -> Materialize -> Bitmap Heap Scan on skip_fetch t2 Recheck Cond: (a = 1) -> Bitmap Index Scan on skip_fetch_a_idx Index Cond: (a = 1) -(9 rows) +(8 rows) SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL; a diff --git a/src/test/regress/expected/memoize.out b/src/test/regress/expected/memoize.out index 9ee09fe2f56..f6b8329cd61 100644 --- a/src/test/regress/expected/memoize.out +++ b/src/test/regress/expected/memoize.out @@ -303,16 +303,15 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.n >= s2.n;', false); explain_memoize ---------------------------------------------------------------------------------- Nested Loop (actual rows=24 loops=N) - Disabled Nodes: 1 -> Seq Scan on strtest s1 (actual rows=6 loops=N) - Disabled Nodes: 1 + Disabled: true -> Memoize (actual rows=4 loops=N) Cache Key: s1.n Cache Mode: binary Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB -> Index Scan using strtest_n_idx on strtest s2 (actual rows=4 loops=N) Index Cond: (n <= s1.n) -(10 rows) +(9 rows) -- Ensure we get 3 hits and 3 misses SELECT explain_memoize(' @@ -320,16 +319,15 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false); explain_memoize ---------------------------------------------------------------------------------- Nested Loop (actual rows=24 loops=N) - Disabled Nodes: 1 -> Seq Scan on strtest s1 (actual rows=6 loops=N) - Disabled Nodes: 1 + Disabled: true -> Memoize (actual rows=4 loops=N) Cache Key: s1.t Cache Mode: binary Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB -> Index Scan using strtest_t_idx on strtest s2 (actual rows=4 loops=N) Index Cond: (t <= s1.t) -(10 rows) +(9 rows) DROP TABLE strtest; -- Ensure memoize works with partitionwise join diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out index 2c63aa85a6e..d17ade278b2 100644 --- a/src/test/regress/expected/select_parallel.out +++ b/src/test/regress/expected/select_parallel.out @@ -537,14 +537,11 @@ explain (costs off) QUERY PLAN ------------------------------------------------------------ Aggregate - Disabled Nodes: 1 -> Nested Loop - Disabled Nodes: 1 -> Gather - Disabled Nodes: 1 Workers Planned: 4 -> Parallel Seq Scan on tenk2 - Disabled Nodes: 1 + Disabled: true Filter: (thousand = 0) -> Gather Workers Planned: 4 @@ -552,7 +549,7 @@ explain (costs off) Recheck Cond: (hundred > 1) -> Bitmap Index Scan on tenk1_hundred Index Cond: (hundred > 1) -(16 rows) +(13 rows) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; count diff --git a/src/test/regress/expected/sqljson_jsontable.out b/src/test/regress/expected/sqljson_jsontable.out index 7a698934ac9..d62d32241d3 100644 --- a/src/test/regress/expected/sqljson_jsontable.out +++ b/src/test/regress/expected/sqljson_jsontable.out @@ -474,6 +474,7 @@ SELECT * FROM "Async Capable": false, + "Table Function Name": "json_table", + "Alias": "json_table_func", + + "Disabled": false, + "Output": ["id", "\"int\"", "text"], + "Table Function Call": "JSON_TABLE('null'::jsonb, '$[*]' AS json_table_path_0 PASSING 3 AS a, '\"foo\"'::jsonb AS \"b c\" COLUMNS (id FOR ORDINALITY, \"int\" integer PATH '$', text text PATH '$'))"+ } + diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out index 0456d48c93a..c73631a9a1d 100644 --- a/src/test/regress/expected/union.out +++ b/src/test/regress/expected/union.out @@ -822,7 +822,7 @@ explain (costs off) select '123'::xid union select '123'::xid; QUERY PLAN --------------------------- HashAggregate - Disabled Nodes: 1 + Disabled: true Group Key: ('123'::xid) -> Append -> Result diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index 361a6f9b27c..fb5f345855c 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -1577,6 +1577,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Parallel Aware": false, + "Async Capable": false, + "Join Type": "Inner", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Inner Unique": false, + "Plans": [ + @@ -1588,6 +1589,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Relation Name": "xmldata", + "Schema": "public", + "Alias": "xmldata", + + "Disabled": false, + "Output": ["xmldata.data"] + }, + { + @@ -1597,6 +1599,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Async Capable": false, + "Table Function Name": "xmltable", + "Alias": "f", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+ "Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" + diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index d26e10441e8..ef7dc03c691 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -1209,6 +1209,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Parallel Aware": false, + "Async Capable": false, + "Join Type": "Inner", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Inner Unique": false, + "Plans": [ + @@ -1220,6 +1221,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Relation Name": "xmldata", + "Schema": "public", + "Alias": "xmldata", + + "Disabled": false, + "Output": ["xmldata.data"] + }, + { + @@ -1229,6 +1231,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Async Capable": false, + "Table Function Name": "xmltable", + "Alias": "f", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+ "Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" + diff --git a/src/test/regress/expected/xml_2.out b/src/test/regress/expected/xml_2.out index 73c2851d3f5..4a9cdd2afe4 100644 --- a/src/test/regress/expected/xml_2.out +++ b/src/test/regress/expected/xml_2.out @@ -1563,6 +1563,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Parallel Aware": false, + "Async Capable": false, + "Join Type": "Inner", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Inner Unique": false, + "Plans": [ + @@ -1574,6 +1575,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Relation Name": "xmldata", + "Schema": "public", + "Alias": "xmldata", + + "Disabled": false, + "Output": ["xmldata.data"] + }, + { + @@ -1583,6 +1585,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Async Capable": false, + "Table Function Name": "xmltable", + "Alias": "f", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+ "Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" +