修訂 | acf1fd47bc3168c9d396da1378fe1e5229b08b39 (tree) |
---|---|
時間 | 2014-12-19 14:15:22 |
作者 | Kyotaro Horiguchi <horiguchi.kyotaro@lab....> |
Commiter | Kyotaro Horiguchi |
Add subsidiary functions to tweak dummy statistics.
pg_statictics has some columns of anyarray which cannot be updated
through ordinary SQL statements and dbms_stats.column_stats_locked
inherits the characteristic. Though, it is inconvenient for those who
wants to tweak statistics, especially MCV, HISTOGRAM and like which
are of anyarray type.
This commit adds some functions to handle dbms_stats.anyarray to
enable them to write dummy (locked) statistics by hand.
Anyarray values can be updated by steps like following.
=# SELECT dbms_stats.anyarray_basetype(stavalues1)
(1 row)
=# SELECT dbms_stats.prepare_statstweak('float4');
y))
(1 row)
=# UPDATE dbms_stats.column_stats_locked
UPDATE 1
@@ -2,3 +2,70 @@ | ||
2 | 2 | |
3 | 3 | -- complain if script is sourced in psql, rather than via CREATE EXTENSION |
4 | 4 | \echo Use "ALTER EXTENSION pg_dbms_stats UPDATE TO '1.3.6'" to load this file. \quit |
5 | + | |
6 | +/* Primitive functions for tweaking statistics */ | |
7 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
8 | + RETURNS name | |
9 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
10 | + LANGUAGE C STABLE; | |
11 | + | |
12 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
13 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
14 | + LANGUAGE C STRICT STABLE; | |
15 | + | |
16 | +/* | |
17 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
18 | + * type. | |
19 | + */ | |
20 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
21 | +RETURNS text AS $$ | |
22 | +DECLARE | |
23 | + srctypname varchar; | |
24 | + funcname varchar; | |
25 | + funcdef varchar; | |
26 | + castdef varchar; | |
27 | +BEGIN | |
28 | + srctypname := $1 || '[]'; | |
29 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
30 | + funcdef := funcname || '(' || srctypname || ')'; | |
31 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
32 | + | |
33 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
34 | + RAISE 'the type can not have statistics'; | |
35 | + END IF; | |
36 | + | |
37 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
38 | + ' RETURNS dbms_stats.anyarray ' || | |
39 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
40 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
41 | + EXECUTE 'CREATE CAST '|| castdef || | |
42 | + ' WITH FUNCTION ' || funcdef || | |
43 | + ' AS ASSIGNMENT'; | |
44 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
45 | +EXCEPTION | |
46 | + WHEN duplicate_function THEN | |
47 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
48 | +END; | |
49 | +$$ LANGUAGE plpgsql; | |
50 | + | |
51 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
52 | +RETURNS text AS $$ | |
53 | +DECLARE | |
54 | + srctypname varchar; | |
55 | + funcname varchar; | |
56 | + funcdef varchar; | |
57 | + castdef varchar; | |
58 | +BEGIN | |
59 | + srctypname := $1 || '[]'; | |
60 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
61 | + funcdef := funcname || '(' || srctypname || ')'; | |
62 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
63 | + | |
64 | + EXECUTE 'DROP CAST ' || castdef; | |
65 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
66 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
67 | +EXCEPTION | |
68 | + WHEN undefined_function OR undefined_object THEN | |
69 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
70 | +END; | |
71 | +$$ LANGUAGE plpgsql; |
@@ -2,3 +2,70 @@ | ||
2 | 2 | |
3 | 3 | -- complain if script is sourced in psql, rather than via CREATE EXTENSION |
4 | 4 | \echo Use "ALTER EXTENSION pg_dbms_stats UPDATE TO '1.3.6'" to load this file. \quit |
5 | + | |
6 | +/* Primitive functions for tweaking statistics */ | |
7 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
8 | + RETURNS name | |
9 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
10 | + LANGUAGE C STABLE; | |
11 | + | |
12 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
13 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
14 | + LANGUAGE C STRICT STABLE; | |
15 | + | |
16 | +/* | |
17 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
18 | + * type. | |
19 | + */ | |
20 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
21 | +RETURNS text AS $$ | |
22 | +DECLARE | |
23 | + srctypname varchar; | |
24 | + funcname varchar; | |
25 | + funcdef varchar; | |
26 | + castdef varchar; | |
27 | +BEGIN | |
28 | + srctypname := $1 || '[]'; | |
29 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
30 | + funcdef := funcname || '(' || srctypname || ')'; | |
31 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
32 | + | |
33 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
34 | + RAISE 'the type can not have statistics'; | |
35 | + END IF; | |
36 | + | |
37 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
38 | + ' RETURNS dbms_stats.anyarray ' || | |
39 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
40 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
41 | + EXECUTE 'CREATE CAST '|| castdef || | |
42 | + ' WITH FUNCTION ' || funcdef || | |
43 | + ' AS ASSIGNMENT'; | |
44 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
45 | +EXCEPTION | |
46 | + WHEN duplicate_function THEN | |
47 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
48 | +END; | |
49 | +$$ LANGUAGE plpgsql; | |
50 | + | |
51 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
52 | +RETURNS text AS $$ | |
53 | +DECLARE | |
54 | + srctypname varchar; | |
55 | + funcname varchar; | |
56 | + funcdef varchar; | |
57 | + castdef varchar; | |
58 | +BEGIN | |
59 | + srctypname := $1 || '[]'; | |
60 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
61 | + funcdef := funcname || '(' || srctypname || ')'; | |
62 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
63 | + | |
64 | + EXECUTE 'DROP CAST ' || castdef; | |
65 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
66 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
67 | +EXCEPTION | |
68 | + WHEN undefined_function OR undefined_object THEN | |
69 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
70 | +END; | |
71 | +$$ LANGUAGE plpgsql; |
@@ -2,3 +2,70 @@ | ||
2 | 2 | |
3 | 3 | -- complain if script is sourced in psql, rather than via CREATE EXTENSION |
4 | 4 | \echo Use "ALTER EXTENSION pg_dbms_stats UPDATE TO '1.3.6'" to load this file. \quit |
5 | + | |
6 | +/* Primitive functions for tweaking statistics */ | |
7 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
8 | + RETURNS name | |
9 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
10 | + LANGUAGE C STABLE; | |
11 | + | |
12 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
13 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
14 | + LANGUAGE C STRICT STABLE; | |
15 | + | |
16 | +/* | |
17 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
18 | + * type. | |
19 | + */ | |
20 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
21 | +RETURNS text AS $$ | |
22 | +DECLARE | |
23 | + srctypname varchar; | |
24 | + funcname varchar; | |
25 | + funcdef varchar; | |
26 | + castdef varchar; | |
27 | +BEGIN | |
28 | + srctypname := $1 || '[]'; | |
29 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
30 | + funcdef := funcname || '(' || srctypname || ')'; | |
31 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
32 | + | |
33 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
34 | + RAISE 'the type can not have statistics'; | |
35 | + END IF; | |
36 | + | |
37 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
38 | + ' RETURNS dbms_stats.anyarray ' || | |
39 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
40 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
41 | + EXECUTE 'CREATE CAST '|| castdef || | |
42 | + ' WITH FUNCTION ' || funcdef || | |
43 | + ' AS ASSIGNMENT'; | |
44 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
45 | +EXCEPTION | |
46 | + WHEN duplicate_function THEN | |
47 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
48 | +END; | |
49 | +$$ LANGUAGE plpgsql; | |
50 | + | |
51 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
52 | +RETURNS text AS $$ | |
53 | +DECLARE | |
54 | + srctypname varchar; | |
55 | + funcname varchar; | |
56 | + funcdef varchar; | |
57 | + castdef varchar; | |
58 | +BEGIN | |
59 | + srctypname := $1 || '[]'; | |
60 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
61 | + funcdef := funcname || '(' || srctypname || ')'; | |
62 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
63 | + | |
64 | + EXECUTE 'DROP CAST ' || castdef; | |
65 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
66 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
67 | +EXCEPTION | |
68 | + WHEN undefined_function OR undefined_object THEN | |
69 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
70 | +END; | |
71 | +$$ LANGUAGE plpgsql; |
@@ -2,3 +2,70 @@ | ||
2 | 2 | |
3 | 3 | -- complain if script is sourced in psql, rather than via CREATE EXTENSION |
4 | 4 | \echo Use "ALTER EXTENSION pg_dbms_stats UPDATE TO '1.3.6'" to load this file. \quit |
5 | + | |
6 | +/* Primitive functions for tweaking statistics */ | |
7 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
8 | + RETURNS name | |
9 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
10 | + LANGUAGE C STABLE; | |
11 | + | |
12 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
13 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
14 | + LANGUAGE C STRICT STABLE; | |
15 | + | |
16 | +/* | |
17 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
18 | + * type. | |
19 | + */ | |
20 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
21 | +RETURNS text AS $$ | |
22 | +DECLARE | |
23 | + srctypname varchar; | |
24 | + funcname varchar; | |
25 | + funcdef varchar; | |
26 | + castdef varchar; | |
27 | +BEGIN | |
28 | + srctypname := $1 || '[]'; | |
29 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
30 | + funcdef := funcname || '(' || srctypname || ')'; | |
31 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
32 | + | |
33 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
34 | + RAISE 'the type can not have statistics'; | |
35 | + END IF; | |
36 | + | |
37 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
38 | + ' RETURNS dbms_stats.anyarray ' || | |
39 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
40 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
41 | + EXECUTE 'CREATE CAST '|| castdef || | |
42 | + ' WITH FUNCTION ' || funcdef || | |
43 | + ' AS ASSIGNMENT'; | |
44 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
45 | +EXCEPTION | |
46 | + WHEN duplicate_function THEN | |
47 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
48 | +END; | |
49 | +$$ LANGUAGE plpgsql; | |
50 | + | |
51 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
52 | +RETURNS text AS $$ | |
53 | +DECLARE | |
54 | + srctypname varchar; | |
55 | + funcname varchar; | |
56 | + funcdef varchar; | |
57 | + castdef varchar; | |
58 | +BEGIN | |
59 | + srctypname := $1 || '[]'; | |
60 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
61 | + funcdef := funcname || '(' || srctypname || ')'; | |
62 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
63 | + | |
64 | + EXECUTE 'DROP CAST ' || castdef; | |
65 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
66 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
67 | +EXCEPTION | |
68 | + WHEN undefined_function OR undefined_object THEN | |
69 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
70 | +END; | |
71 | +$$ LANGUAGE plpgsql; |
@@ -152,12 +152,74 @@ CREATE FUNCTION dbms_stats.merge( | ||
152 | 152 | 'MODULE_PATHNAME', 'dbms_stats_merge' |
153 | 153 | LANGUAGE C STABLE; |
154 | 154 | |
155 | --- | |
156 | --- Statistics views for internal use | |
157 | --- These views are used to merge authentic stats and dummy stats by hook | |
158 | --- function. | |
159 | --- | |
155 | +/* Primitive functions for tweaking statistics */ | |
156 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
157 | + RETURNS name | |
158 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
159 | + LANGUAGE C STABLE; | |
160 | + | |
161 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
162 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
163 | + LANGUAGE C STRICT STABLE; | |
164 | + | |
165 | +/* | |
166 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
167 | + * type. | |
168 | + */ | |
169 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
170 | +RETURNS text AS $$ | |
171 | +DECLARE | |
172 | + srctypname varchar; | |
173 | + funcname varchar; | |
174 | + funcdef varchar; | |
175 | + castdef varchar; | |
176 | +BEGIN | |
177 | + srctypname := $1 || '[]'; | |
178 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
179 | + funcdef := funcname || '(' || srctypname || ')'; | |
180 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
181 | + | |
182 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
183 | + RAISE 'the type can not have statistics'; | |
184 | + END IF; | |
185 | + | |
186 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
187 | + ' RETURNS dbms_stats.anyarray ' || | |
188 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
189 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
190 | + EXECUTE 'CREATE CAST '|| castdef || | |
191 | + ' WITH FUNCTION ' || funcdef || | |
192 | + ' AS ASSIGNMENT'; | |
193 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
194 | +EXCEPTION | |
195 | + WHEN duplicate_function THEN | |
196 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
197 | +END; | |
198 | +$$ LANGUAGE plpgsql; | |
160 | 199 | |
200 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
201 | +RETURNS text AS $$ | |
202 | +DECLARE | |
203 | + srctypname varchar; | |
204 | + funcname varchar; | |
205 | + funcdef varchar; | |
206 | + castdef varchar; | |
207 | +BEGIN | |
208 | + srctypname := $1 || '[]'; | |
209 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
210 | + funcdef := funcname || '(' || srctypname || ')'; | |
211 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
212 | + | |
213 | + EXECUTE 'DROP CAST ' || castdef; | |
214 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
215 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
216 | +EXCEPTION | |
217 | + WHEN undefined_function OR undefined_object THEN | |
218 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
219 | +END; | |
220 | +$$ LANGUAGE plpgsql; | |
221 | + | |
222 | +/* Views to show merged statistics */ | |
161 | 223 | CREATE VIEW dbms_stats.relation_stats_effective AS |
162 | 224 | SELECT |
163 | 225 | c.oid AS relid, |
@@ -162,6 +162,74 @@ CREATE FUNCTION dbms_stats.merge( | ||
162 | 162 | 'MODULE_PATHNAME', 'dbms_stats_merge' |
163 | 163 | LANGUAGE C STABLE; |
164 | 164 | |
165 | +/* Primitive functions for tweaking statistics */ | |
166 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
167 | + RETURNS name | |
168 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
169 | + LANGUAGE C STABLE; | |
170 | + | |
171 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
172 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
173 | + LANGUAGE C STRICT STABLE; | |
174 | + | |
175 | +/* | |
176 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
177 | + * type. | |
178 | + */ | |
179 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
180 | +RETURNS text AS $$ | |
181 | +DECLARE | |
182 | + srctypname varchar; | |
183 | + funcname varchar; | |
184 | + funcdef varchar; | |
185 | + castdef varchar; | |
186 | +BEGIN | |
187 | + srctypname := $1 || '[]'; | |
188 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
189 | + funcdef := funcname || '(' || srctypname || ')'; | |
190 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
191 | + | |
192 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
193 | + RAISE 'the type can not have statistics'; | |
194 | + END IF; | |
195 | + | |
196 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
197 | + ' RETURNS dbms_stats.anyarray ' || | |
198 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
199 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
200 | + EXECUTE 'CREATE CAST '|| castdef || | |
201 | + ' WITH FUNCTION ' || funcdef || | |
202 | + ' AS ASSIGNMENT'; | |
203 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
204 | +EXCEPTION | |
205 | + WHEN duplicate_function THEN | |
206 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
207 | +END; | |
208 | +$$ LANGUAGE plpgsql; | |
209 | + | |
210 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
211 | +RETURNS text AS $$ | |
212 | +DECLARE | |
213 | + srctypname varchar; | |
214 | + funcname varchar; | |
215 | + funcdef varchar; | |
216 | + castdef varchar; | |
217 | +BEGIN | |
218 | + srctypname := $1 || '[]'; | |
219 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
220 | + funcdef := funcname || '(' || srctypname || ')'; | |
221 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
222 | + | |
223 | + EXECUTE 'DROP CAST ' || castdef; | |
224 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
225 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
226 | +EXCEPTION | |
227 | + WHEN undefined_function OR undefined_object THEN | |
228 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
229 | +END; | |
230 | +$$ LANGUAGE plpgsql; | |
231 | + | |
232 | +/* Views to show merged statistics */ | |
165 | 233 | CREATE VIEW dbms_stats.relation_stats_effective AS |
166 | 234 | SELECT |
167 | 235 | c.oid AS relid, |
@@ -162,6 +162,74 @@ CREATE FUNCTION dbms_stats.merge( | ||
162 | 162 | 'MODULE_PATHNAME', 'dbms_stats_merge' |
163 | 163 | LANGUAGE C STABLE; |
164 | 164 | |
165 | +/* Primitive functions for tweaking statistics */ | |
166 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
167 | + RETURNS name | |
168 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
169 | + LANGUAGE C STABLE; | |
170 | + | |
171 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
172 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
173 | + LANGUAGE C STRICT STABLE; | |
174 | + | |
175 | +/* | |
176 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
177 | + * type. | |
178 | + */ | |
179 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
180 | +RETURNS text AS $$ | |
181 | +DECLARE | |
182 | + srctypname varchar; | |
183 | + funcname varchar; | |
184 | + funcdef varchar; | |
185 | + castdef varchar; | |
186 | +BEGIN | |
187 | + srctypname := $1 || '[]'; | |
188 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
189 | + funcdef := funcname || '(' || srctypname || ')'; | |
190 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
191 | + | |
192 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
193 | + RAISE 'the type can not have statistics'; | |
194 | + END IF; | |
195 | + | |
196 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
197 | + ' RETURNS dbms_stats.anyarray ' || | |
198 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
199 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
200 | + EXECUTE 'CREATE CAST '|| castdef || | |
201 | + ' WITH FUNCTION ' || funcdef || | |
202 | + ' AS ASSIGNMENT'; | |
203 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
204 | +EXCEPTION | |
205 | + WHEN duplicate_function THEN | |
206 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
207 | +END; | |
208 | +$$ LANGUAGE plpgsql; | |
209 | + | |
210 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
211 | +RETURNS text AS $$ | |
212 | +DECLARE | |
213 | + srctypname varchar; | |
214 | + funcname varchar; | |
215 | + funcdef varchar; | |
216 | + castdef varchar; | |
217 | +BEGIN | |
218 | + srctypname := $1 || '[]'; | |
219 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
220 | + funcdef := funcname || '(' || srctypname || ')'; | |
221 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
222 | + | |
223 | + EXECUTE 'DROP CAST ' || castdef; | |
224 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
225 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
226 | +EXCEPTION | |
227 | + WHEN undefined_function OR undefined_object THEN | |
228 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
229 | +END; | |
230 | +$$ LANGUAGE plpgsql; | |
231 | + | |
232 | +/* Views to show merged statistics */ | |
165 | 233 | CREATE VIEW dbms_stats.relation_stats_effective AS |
166 | 234 | SELECT |
167 | 235 | c.oid AS relid, |
@@ -162,6 +162,74 @@ CREATE FUNCTION dbms_stats.merge( | ||
162 | 162 | 'MODULE_PATHNAME', 'dbms_stats_merge' |
163 | 163 | LANGUAGE C STABLE; |
164 | 164 | |
165 | +/* Primitive functions for tweaking statistics */ | |
166 | +CREATE FUNCTION dbms_stats.anyarray_basetype(dbms_stats.anyarray) | |
167 | + RETURNS name | |
168 | + AS 'MODULE_PATHNAME', 'dbms_stats_anyarray_basetype' | |
169 | + LANGUAGE C STABLE; | |
170 | + | |
171 | +CREATE FUNCTION dbms_stats.type_is_analyzable(oid) returns bool | |
172 | + AS 'MODULE_PATHNAME', 'dbms_stats_type_is_analyzable' | |
173 | + LANGUAGE C STRICT STABLE; | |
174 | + | |
175 | +/* | |
176 | + * Create and drop a cast necessary to set column values of dbms_stats.anyarray | |
177 | + * type. | |
178 | + */ | |
179 | +CREATE OR REPLACE FUNCTION dbms_stats.prepare_statstweak(regtype) | |
180 | +RETURNS text AS $$ | |
181 | +DECLARE | |
182 | + srctypname varchar; | |
183 | + funcname varchar; | |
184 | + funcdef varchar; | |
185 | + castdef varchar; | |
186 | +BEGIN | |
187 | + srctypname := $1 || '[]'; | |
188 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
189 | + funcdef := funcname || '(' || srctypname || ')'; | |
190 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
191 | + | |
192 | + IF (NOT dbms_stats.type_is_analyzable($1::regtype)) THEN | |
193 | + RAISE 'the type can not have statistics'; | |
194 | + END IF; | |
195 | + | |
196 | + EXECUTE 'CREATE FUNCTION ' || funcdef || | |
197 | + ' RETURNS dbms_stats.anyarray ' || | |
198 | + ' AS ''pg_dbms_stats'', ''dbms_stats_anyary_anyary'''|| | |
199 | + ' LANGUAGE C STRICT IMMUTABLE'; | |
200 | + EXECUTE 'CREATE CAST '|| castdef || | |
201 | + ' WITH FUNCTION ' || funcdef || | |
202 | + ' AS ASSIGNMENT'; | |
203 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
204 | +EXCEPTION | |
205 | + WHEN duplicate_function THEN | |
206 | + RAISE 'run dbms_stats.drop_statstweak() for the type before this'; | |
207 | +END; | |
208 | +$$ LANGUAGE plpgsql; | |
209 | + | |
210 | +CREATE OR REPLACE FUNCTION dbms_stats.drop_statstweak(regtype) | |
211 | +RETURNS text AS $$ | |
212 | +DECLARE | |
213 | + srctypname varchar; | |
214 | + funcname varchar; | |
215 | + funcdef varchar; | |
216 | + castdef varchar; | |
217 | +BEGIN | |
218 | + srctypname := $1 || '[]'; | |
219 | + funcname := 'dbms_stats._' || $1 || 'ary_anyarray'; | |
220 | + funcdef := funcname || '(' || srctypname || ')'; | |
221 | + castdef := '(' || srctypname || ' AS dbms_stats.anyarray)'; | |
222 | + | |
223 | + EXECUTE 'DROP CAST ' || castdef; | |
224 | + EXECUTE 'DROP FUNCTION ' || funcdef; | |
225 | + RETURN '(func ' || funcdef || ', cast ' || castdef || ')'; | |
226 | +EXCEPTION | |
227 | + WHEN undefined_function OR undefined_object THEN | |
228 | + RAISE 'function % or cast % does not exist', funcdef, castdef; | |
229 | +END; | |
230 | +$$ LANGUAGE plpgsql; | |
231 | + | |
232 | +/* Views to show merged statistics */ | |
165 | 233 | CREATE VIEW dbms_stats.relation_stats_effective AS |
166 | 234 | SELECT |
167 | 235 | c.oid AS relid, |
@@ -33,6 +33,7 @@ | ||
33 | 33 | #include "utils/catcache.h" |
34 | 34 | #endif |
35 | 35 | |
36 | +#include "parser/parse_oper.h" | |
36 | 37 | #include "pg_dbms_stats.h" |
37 | 38 | |
38 | 39 | PG_MODULE_MAGIC; |
@@ -127,12 +128,18 @@ PG_FUNCTION_INFO_V1(dbms_stats_invalidate_relation_cache); | ||
127 | 128 | PG_FUNCTION_INFO_V1(dbms_stats_invalidate_column_cache); |
128 | 129 | PG_FUNCTION_INFO_V1(dbms_stats_is_system_schema); |
129 | 130 | PG_FUNCTION_INFO_V1(dbms_stats_is_system_catalog); |
131 | +PG_FUNCTION_INFO_V1(dbms_stats_anyary_anyary); | |
132 | +PG_FUNCTION_INFO_V1(dbms_stats_type_is_analyzable); | |
133 | +PG_FUNCTION_INFO_V1(dbms_stats_anyarray_basetype); | |
130 | 134 | |
131 | 135 | extern Datum dbms_stats_merge(PG_FUNCTION_ARGS); |
132 | 136 | extern Datum dbms_stats_invalidate_relation_cache(PG_FUNCTION_ARGS); |
133 | 137 | extern Datum dbms_stats_invalidate_column_cache(PG_FUNCTION_ARGS); |
134 | 138 | extern Datum dbms_stats_is_system_schema(PG_FUNCTION_ARGS); |
135 | 139 | extern Datum dbms_stats_is_system_catalog(PG_FUNCTION_ARGS); |
140 | +extern Datum dbms_stats_anyary_anyary(PG_FUNCTION_ARGS); | |
141 | +extern Datum dbms_stats_type_is_analyzable(PG_FUNCTION_ARGS); | |
142 | +extern Datum dbms_stats_anyarray_basetype(PG_FUNCTION_ARGS); | |
136 | 143 | |
137 | 144 | static HeapTuple dbms_stats_merge_internal(HeapTuple lhs, HeapTuple rhs, |
138 | 145 | TupleDesc tupledesc); |
@@ -181,7 +188,7 @@ extern void test_pg_dbms_stats(int *passed, int *total); | ||
181 | 188 | |
182 | 189 | /* SPI_keepplan() is since 9.2 */ |
183 | 190 | #if PG_VERSION_NUM < 90200 |
184 | -#define SPI_keepplan(pplan) {\ | |
191 | +#define SPI_keepplan(pplan) {\ | |
185 | 192 | SPIPlanPtr tp = *plan;\ |
186 | 193 | *plan = SPI_saveplan(tp);\ |
187 | 194 | SPI_freeplan(tp);\ |
@@ -255,6 +262,64 @@ _PG_fini(void) | ||
255 | 262 | } |
256 | 263 | |
257 | 264 | /* |
265 | + * Function to convert from any array from dbms_stats.anyarray. | |
266 | + */ | |
267 | +Datum | |
268 | +dbms_stats_anyary_anyary(PG_FUNCTION_ARGS) | |
269 | +{ | |
270 | + ArrayType *arr = PG_GETARG_ARRAYTYPE_P(0); | |
271 | + if (ARR_NDIM(arr) != 1) | |
272 | + elog(ERROR, "array must be one-dimentional."); | |
273 | + | |
274 | + PG_RETURN_ARRAYTYPE_P(arr); | |
275 | +} | |
276 | + | |
277 | +/* | |
278 | + * Function to check if the type can have statistics. | |
279 | + */ | |
280 | +Datum | |
281 | +dbms_stats_type_is_analyzable(PG_FUNCTION_ARGS) | |
282 | +{ | |
283 | + Oid typid = PG_GETARG_OID(0); | |
284 | + Oid eqopr; | |
285 | + | |
286 | + if (!OidIsValid(typid)) | |
287 | + PG_RETURN_BOOL(false); | |
288 | + | |
289 | + get_sort_group_operators(typid, false, false, false, | |
290 | + NULL, &eqopr, NULL, | |
291 | + NULL); | |
292 | + PG_RETURN_BOOL(OidIsValid(eqopr)); | |
293 | +} | |
294 | + | |
295 | +/* | |
296 | + * Function to get base type of the value of the type dbms_stats.anyarray. | |
297 | + */ | |
298 | +Datum | |
299 | +dbms_stats_anyarray_basetype(PG_FUNCTION_ARGS) | |
300 | +{ | |
301 | + ArrayType *arr = PG_GETARG_ARRAYTYPE_P(0); | |
302 | + Oid elemtype = arr->elemtype; | |
303 | + HeapTuple tp; | |
304 | + Form_pg_type typtup; | |
305 | + Name result; | |
306 | + | |
307 | + if (!OidIsValid(elemtype)) | |
308 | + elog(ERROR, "invalid base type oid: %u", elemtype); | |
309 | + | |
310 | + tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elemtype)); | |
311 | + if (!HeapTupleIsValid(tp)) /* I trust you. */ | |
312 | + elog(ERROR, "invalid base type oid: %u", elemtype); | |
313 | + | |
314 | + typtup = (Form_pg_type) GETSTRUCT(tp); | |
315 | + result = (Name) palloc0(NAMEDATALEN); | |
316 | + StrNCpy(NameStr(*result), NameStr(typtup->typname), NAMEDATALEN); | |
317 | + | |
318 | + ReleaseSysCache(tp); | |
319 | + PG_RETURN_NAME(result); | |
320 | +} | |
321 | + | |
322 | +/* | |
258 | 323 | * Find and store the owner of the dummy statistics table. |
259 | 324 | * |
260 | 325 | * We will access statistics tables using this owner |