postgrespro.git / summary / log / commit / refs

commit    3824ca30d162611fdaade403d3aec449fecd0924
Author:   Tomas Vondra <tomas.vondra@postgresql.org>
Date:     Mon Apr 15 22:01:39 2019 +0000

    Fix pg_mcv_list deserialization
    
    The memcpy() was copying type OIDs in the wrong direction, so the
    deserialized MCV list always had them as 0. This is mostly harmless
    except when printing the data in pg_mcv_list_items(), in which case
    it reported
    
        ERROR:  cache lookup failed for type 0
    
    Also added a simple regression test for pg_mcv_list_items() function,
    printing a single-item MCV list.
    
    Reported-By: Dean Rasheed
    Discussion: https://postgr.es/m/CAEZATCX6T0iDTTZrqyec4Cd6b4yuL7euu4=rQRXaVBAVrUi1Cg@mail.gmail.com


src/backend/statistics/mcv.c | 2 +- src/test/regress/expected/stats_ext.out | 11 +++++++++++ src/test/regress/sql/stats_ext.sql | 8 ++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c index 2daefb2686..05ab6c9bb7 100644 --- a/src/backend/statistics/mcv.c +++ b/src/backend/statistics/mcv.c @@ -905,7 +905,7 @@ statext_mcv_deserialize(bytea *data) VARSIZE_ANY(data), expected_size); /* Now copy the array of type Oids. */ - memcpy(ptr, mcvlist->types, sizeof(Oid) * ndims); + memcpy(mcvlist->types, ptr, sizeof(Oid) * ndims); ptr += (sizeof(Oid) * ndims); /* ensure alignment of the pointer (after the header fields) */ diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out index b32663459d..add968abec 100644 --- a/src/test/regress/expected/stats_ext.out +++ b/src/test/regress/expected/stats_ext.out @@ -717,6 +717,17 @@ SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a IS NULL AND 50 | 50 (1 row) +-- test pg_mcv_list_items with a very simple (single item) MCV list +TRUNCATE mcv_lists; +INSERT INTO mcv_lists (a, b, c) SELECT 1, 2, 3 FROM generate_series(1,1000) s(i); +ANALYZE mcv_lists; +SELECT m.* FROM pg_statistic_ext, + pg_mcv_list_items(stxmcv) m WHERE stxname = 'mcv_lists_stats'; + index | values | nulls | frequency | base_frequency +-------+-----------+---------+-----------+---------------- + 0 | {1, 2, 3} | {f,f,f} | 1 | 1 +(1 row) + RESET random_page_cost; -- mcv with arrays CREATE TABLE mcv_lists_arrays ( diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql index 2a6a23c06d..d4b2732493 100644 --- a/src/test/regress/sql/stats_ext.sql +++ b/src/test/regress/sql/stats_ext.sql @@ -411,6 +411,14 @@ SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a IS NULL AND SELECT * FROM check_estimated_rows('SELECT * FROM mcv_lists WHERE a IS NULL AND b IS NULL AND c IS NULL'); +-- test pg_mcv_list_items with a very simple (single item) MCV list +TRUNCATE mcv_lists; +INSERT INTO mcv_lists (a, b, c) SELECT 1, 2, 3 FROM generate_series(1,1000) s(i); +ANALYZE mcv_lists; + +SELECT m.* FROM pg_statistic_ext, + pg_mcv_list_items(stxmcv) m WHERE stxname = 'mcv_lists_stats'; + RESET random_page_cost; -- mcv with arrays [parent: 4b40e44f07c7]