• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

修訂acf1fd47bc3168c9d396da1378fe1e5229b08b39 (tree)
時間2014-12-19 14:15:22
作者Kyotaro Horiguchi <horiguchi.kyotaro@lab....>
CommiterKyotaro Horiguchi

Log Message

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)

FROM dbms_stats.column_stats_locked
WHERE starelid = xxxx AND staattnum = x;
anyarray_basetype

float4

(1 row)
=# SELECT dbms_stats.prepare_statstweak('float4');



(func dbms_stats._realary_anyarray(real[]), cast (real[] AS dbms_stats.anyarra

y))
(1 row)
=# UPDATE dbms_stats.column_stats_locked

SET stavalues1 = '{1.1,2.2,3.3}'::float4[]
WHERE starelid = xxxx AND staattnum = x;

UPDATE 1

Change Summary

差異

--- a/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.1.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.1.sql
@@ -2,3 +2,70 @@
22
33 -- complain if script is sourced in psql, rather than via CREATE EXTENSION
44 \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;
--- a/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.2.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.2.sql
@@ -2,3 +2,70 @@
22
33 -- complain if script is sourced in psql, rather than via CREATE EXTENSION
44 \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;
--- a/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.3.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.3.sql
@@ -2,3 +2,70 @@
22
33 -- complain if script is sourced in psql, rather than via CREATE EXTENSION
44 \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;
--- a/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.4.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.5--1.3.6-9.4.sql
@@ -2,3 +2,70 @@
22
33 -- complain if script is sourced in psql, rather than via CREATE EXTENSION
44 \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;
--- a/ext_scripts/pg_dbms_stats--1.3.6-9.1.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.6-9.1.sql
@@ -152,12 +152,74 @@ CREATE FUNCTION dbms_stats.merge(
152152 'MODULE_PATHNAME', 'dbms_stats_merge'
153153 LANGUAGE C STABLE;
154154
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;
160199
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 */
161223 CREATE VIEW dbms_stats.relation_stats_effective AS
162224 SELECT
163225 c.oid AS relid,
--- a/ext_scripts/pg_dbms_stats--1.3.6-9.2.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.6-9.2.sql
@@ -162,6 +162,74 @@ CREATE FUNCTION dbms_stats.merge(
162162 'MODULE_PATHNAME', 'dbms_stats_merge'
163163 LANGUAGE C STABLE;
164164
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 */
165233 CREATE VIEW dbms_stats.relation_stats_effective AS
166234 SELECT
167235 c.oid AS relid,
--- a/ext_scripts/pg_dbms_stats--1.3.6-9.3.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.6-9.3.sql
@@ -162,6 +162,74 @@ CREATE FUNCTION dbms_stats.merge(
162162 'MODULE_PATHNAME', 'dbms_stats_merge'
163163 LANGUAGE C STABLE;
164164
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 */
165233 CREATE VIEW dbms_stats.relation_stats_effective AS
166234 SELECT
167235 c.oid AS relid,
--- a/ext_scripts/pg_dbms_stats--1.3.6-9.4.sql
+++ b/ext_scripts/pg_dbms_stats--1.3.6-9.4.sql
@@ -162,6 +162,74 @@ CREATE FUNCTION dbms_stats.merge(
162162 'MODULE_PATHNAME', 'dbms_stats_merge'
163163 LANGUAGE C STABLE;
164164
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 */
165233 CREATE VIEW dbms_stats.relation_stats_effective AS
166234 SELECT
167235 c.oid AS relid,
--- a/pg_dbms_stats.c
+++ b/pg_dbms_stats.c
@@ -33,6 +33,7 @@
3333 #include "utils/catcache.h"
3434 #endif
3535
36+#include "parser/parse_oper.h"
3637 #include "pg_dbms_stats.h"
3738
3839 PG_MODULE_MAGIC;
@@ -127,12 +128,18 @@ PG_FUNCTION_INFO_V1(dbms_stats_invalidate_relation_cache);
127128 PG_FUNCTION_INFO_V1(dbms_stats_invalidate_column_cache);
128129 PG_FUNCTION_INFO_V1(dbms_stats_is_system_schema);
129130 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);
130134
131135 extern Datum dbms_stats_merge(PG_FUNCTION_ARGS);
132136 extern Datum dbms_stats_invalidate_relation_cache(PG_FUNCTION_ARGS);
133137 extern Datum dbms_stats_invalidate_column_cache(PG_FUNCTION_ARGS);
134138 extern Datum dbms_stats_is_system_schema(PG_FUNCTION_ARGS);
135139 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);
136143
137144 static HeapTuple dbms_stats_merge_internal(HeapTuple lhs, HeapTuple rhs,
138145 TupleDesc tupledesc);
@@ -181,7 +188,7 @@ extern void test_pg_dbms_stats(int *passed, int *total);
181188
182189 /* SPI_keepplan() is since 9.2 */
183190 #if PG_VERSION_NUM < 90200
184-#define SPI_keepplan(pplan) {\
191+#define SPI_keepplan(pplan) {\
185192 SPIPlanPtr tp = *plan;\
186193 *plan = SPI_saveplan(tp);\
187194 SPI_freeplan(tp);\
@@ -255,6 +262,64 @@ _PG_fini(void)
255262 }
256263
257264 /*
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+/*
258323 * Find and store the owner of the dummy statistics table.
259324 *
260325 * We will access statistics tables using this owner