@@ -16,89 +16,90 @@ declare
16
16
statements text [] = ' {}' ;
17
17
begin
18
18
19
- -- Disallow multiple statements
20
- if query ilike ' %;%' then
21
- raise exception ' query must not contain a semicolon' ;
22
- end if;
19
+ -- Disallow multiple statements
20
+ if query ilike ' %;%' then
21
+ raise exception ' query must not contain a semicolon' ;
22
+ end if;
23
23
24
- -- Create a prepared statement for the given query
25
- execute format(' prepare %I as %s' , prepared_statement_name, query);
24
+ -- Create a prepared statement for the given query
25
+ deallocate all;
26
+ execute format(' prepare %I as %s' , prepared_statement_name, query);
26
27
27
- -- Detect how many arguments are present in the prepared statement
28
- n_args = (
29
- select
30
- coalesce(array_length(parameter_types, 1 ), 0 )
31
- from
32
- pg_prepared_statements
33
- where
34
- name = prepared_statement_name
35
- limit
36
- 1
37
- );
28
+ -- Detect how many arguments are present in the prepared statement
29
+ n_args = (
30
+ select
31
+ coalesce(array_length(parameter_types, 1 ), 0 )
32
+ from
33
+ pg_prepared_statements
34
+ where
35
+ name = prepared_statement_name
36
+ limit
37
+ 1
38
+ );
38
39
39
- -- Create a SQL statement that can be executed to collect the explain plan
40
- explain_plan_statement = format(
41
- ' set local plan_cache_mode = force_generic_plan; explain (format json) execute %I%s' ,
42
- -- 'explain (format json) execute %I%s',
43
- prepared_statement_name,
44
- case
45
- when n_args = 0 then ' '
46
- else format(
47
- ' (%s)' , array_to_string(array_fill(' null' ::text , array[n_args]), ' ,' )
48
- )
49
- end
50
- );
40
+ -- Create a SQL statement that can be executed to collect the explain plan
41
+ explain_plan_statement = format(
42
+ ' set local plan_cache_mode = force_generic_plan; explain (format json) execute %I%s' ,
43
+ -- 'explain (format json) execute %I%s',
44
+ prepared_statement_name,
45
+ case
46
+ when n_args = 0 then ' '
47
+ else format(
48
+ ' (%s)' , array_to_string(array_fill(' null' ::text , array[n_args]), ' ,' )
49
+ )
50
+ end
51
+ );
51
52
52
- -- Store the query plan before any new indexes
53
- execute explain_plan_statement into plan_initial;
53
+ -- Store the query plan before any new indexes
54
+ execute explain_plan_statement into plan_initial;
54
55
55
- -- Create possible indexes
56
- for rec in (
57
- with extension_regclass as (
58
- select
59
- distinct objid as oid
60
- from
61
- pg_depend
62
- where
63
- deptype = ' e'
64
- )
56
+ -- Create possible indexes
57
+ for rec in (
58
+ with extension_regclass as (
65
59
select
66
- pc .relnamespace ::regnamespace::text as schema_name,
67
- pc .relname as table_name,
68
- pa .attname as column_name,
69
- format(
70
- ' select %I.hypopg_create_index($i$create index on %I.%I(%I)$i$)' ,
71
- hypopg_schema_name,
72
- pc .relnamespace ::regnamespace::text ,
73
- pc .relname ,
74
- pa .attname
75
- ) hypopg_statement
60
+ distinct objid as oid
76
61
from
77
- pg_catalog .pg_class pc
78
- join pg_catalog .pg_attribute pa
79
- on pc .oid = pa .attrelid
80
- left join extension_regclass er
81
- on pc .oid = er .oid
82
- left join pg_index pi
83
- on pc .oid = pi .indrelid
84
- and (select array_agg(x) from unnest(pi .indkey ) v(x)) = array[pa .attnum ]
85
- and pi .indexprs is null -- ignore expression indexes
86
- and pi .indpred is null -- ignore partial indexes
62
+ pg_depend
87
63
where
88
- pc .relnamespace ::regnamespace::text not in ( -- ignore schema list
89
- ' pg_catalog' , ' pg_toast' , ' information_schema'
90
- )
91
- and er .oid is null -- ignore entities owned by extensions
92
- and pc .relkind in (' r' , ' m' ) -- regular tables, and materialized views
93
- and pc .relpersistence = ' p' -- permanent tables (not unlogged or temporary)
94
- and pa .attnum > 0
95
- and not pa .attisdropped
96
- and pi .indrelid is null
64
+ deptype = ' e'
65
+ )
66
+ select
67
+ pc .relnamespace ::regnamespace::text as schema_name,
68
+ pc .relname as table_name,
69
+ pa .attname as column_name,
70
+ format(
71
+ ' select %I.hypopg_create_index($i$create index on %I.%I(%I)$i$)' ,
72
+ hypopg_schema_name,
73
+ pc .relnamespace ::regnamespace::text ,
74
+ pc .relname ,
75
+ pa .attname
76
+ ) hypopg_statement
77
+ from
78
+ pg_catalog .pg_class pc
79
+ join pg_catalog .pg_attribute pa
80
+ on pc .oid = pa .attrelid
81
+ left join extension_regclass er
82
+ on pc .oid = er .oid
83
+ left join pg_index pi
84
+ on pc .oid = pi .indrelid
85
+ and (select array_agg(x) from unnest(pi .indkey ) v(x)) = array[pa .attnum ]
86
+ and pi .indexprs is null -- ignore expression indexes
87
+ and pi .indpred is null -- ignore partial indexes
88
+ where
89
+ pc .relnamespace ::regnamespace::text not in ( -- ignore schema list
90
+ ' pg_catalog' , ' pg_toast' , ' information_schema'
97
91
)
98
- loop
99
- -- Create the hypothetical index
100
- execute rec .hypopg_statement ;
101
- end loop;
92
+ and er .oid is null -- ignore entities owned by extensions
93
+ and pc .relkind in (' r' , ' m' ) -- regular tables, and materialized views
94
+ and pc .relpersistence = ' p' -- permanent tables (not unlogged or temporary)
95
+ and pa .attnum > 0
96
+ and not pa .attisdropped
97
+ and pi .indrelid is null
98
+ )
99
+ loop
100
+ -- Create the hypothetical index
101
+ execute rec .hypopg_statement ;
102
+ end loop;
102
103
103
104
/*
104
105
for rec in select * from hypopg()
@@ -132,8 +133,9 @@ begin
132
133
133
134
-- Reset all hypothetical indexes
134
135
perform hypopg_reset();
135
- -- Delete the prepared statement
136
- perform format(' deallocate %I' , prepared_statement_name);
136
+
137
+ -- Reset prepared statements
138
+ deallocate all;
137
139
138
140
return query select * from unnest(statements);
139
141
0 commit comments