|
11 | 11 | #include <access/stratnum.h>
|
12 | 12 | #include <access/tupdesc.h>
|
13 | 13 | #include <catalog/pg_collation.h>
|
| 14 | +#include <executor/spi.h> |
14 | 15 | #include <executor/tuptable.h>
|
15 | 16 | #include <funcapi.h>
|
16 | 17 | #include <nodes/makefuncs.h>
|
|
22 | 23 | #include <rewrite/rewriteManip.h>
|
23 | 24 | #include <storage/lmgr.h>
|
24 | 25 | #include <storage/lockdefs.h>
|
| 26 | +#include <utils/datum.h> |
25 | 27 | #include <utils/syscache.h>
|
26 | 28 |
|
27 | 29 | #include "chunk.h"
|
@@ -781,6 +783,76 @@ ts_chunk_column_stats_lookup(int32 hypertable_id, int32 chunk_id, const char *co
|
781 | 783 | return form_range;
|
782 | 784 | }
|
783 | 785 |
|
| 786 | +static bool |
| 787 | +chunk_get_minmax(const Chunk *chunk, Oid col_type, const char *col_name, Datum *minmax) |
| 788 | +{ |
| 789 | + StringInfoData command; |
| 790 | + int res; |
| 791 | + |
| 792 | + /* Lock down search_path */ |
| 793 | + int save_nestlevel = NewGUCNestLevel(); |
| 794 | + RestrictSearchPath(); |
| 795 | + |
| 796 | + initStringInfo(&command); |
| 797 | + appendStringInfo(&command, |
| 798 | + "SELECT pg_catalog.min(%s), pg_catalog.max(%s) FROM %s.%s", |
| 799 | + quote_identifier(col_name), |
| 800 | + quote_identifier(col_name), |
| 801 | + quote_identifier(NameStr(chunk->fd.schema_name)), |
| 802 | + quote_identifier(NameStr(chunk->fd.table_name))); |
| 803 | + |
| 804 | + /* |
| 805 | + * SPI_connect will switch MemoryContext so we need to keep track |
| 806 | + * of caller context as we need to copy the values into caller |
| 807 | + * context. |
| 808 | + */ |
| 809 | + MemoryContext caller = CurrentMemoryContext; |
| 810 | + |
| 811 | + if (SPI_connect() != SPI_OK_CONNECT) |
| 812 | + elog(ERROR, "could not connect to SPI"); |
| 813 | + |
| 814 | + res = SPI_execute(command.data, true /* read_only */, 0 /*count*/); |
| 815 | + if (res < 0) |
| 816 | + ereport(ERROR, |
| 817 | + (errcode(ERRCODE_INTERNAL_ERROR), |
| 818 | + (errmsg("could not get the min/max values for column \"%s\" of chunk \"%s.%s\"", |
| 819 | + col_name, |
| 820 | + chunk->fd.schema_name.data, |
| 821 | + chunk->fd.table_name.data)))); |
| 822 | + |
| 823 | + pfree(command.data); |
| 824 | + |
| 825 | + Datum min, max; |
| 826 | + bool isnull_min = false, isnull_max = false; |
| 827 | + min = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull_min); |
| 828 | + max = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, &isnull_max); |
| 829 | + Assert(SPI_gettypeid(SPI_tuptable->tupdesc, 1) == col_type); |
| 830 | + Assert(SPI_gettypeid(SPI_tuptable->tupdesc, 2) == col_type); |
| 831 | + |
| 832 | + bool found = !isnull_min && !isnull_max; |
| 833 | + if (found) |
| 834 | + { |
| 835 | + bool typbyval; |
| 836 | + int16 typlen; |
| 837 | + get_typlenbyval(col_type, &typlen, &typbyval); |
| 838 | + |
| 839 | + /* Copy the values into caller context */ |
| 840 | + MemoryContext spi = MemoryContextSwitchTo(caller); |
| 841 | + minmax[0] = datumCopy(min, typbyval, typlen); |
| 842 | + minmax[1] = datumCopy(max, typbyval, typlen); |
| 843 | + MemoryContextSwitchTo(spi); |
| 844 | + } |
| 845 | + |
| 846 | + /* Restore search_path */ |
| 847 | + AtEOXact_GUC(false, save_nestlevel); |
| 848 | + |
| 849 | + res = SPI_finish(); |
| 850 | + if (res != SPI_OK_FINISH) |
| 851 | + elog(ERROR, "SPI_finish failed: %s", SPI_result_code_string(res)); |
| 852 | + |
| 853 | + return found; |
| 854 | +} |
| 855 | + |
784 | 856 | /*
|
785 | 857 | * Update column dimension ranges in the catalog for the
|
786 | 858 | * provided chunk (it's assumed that the chunk is locked
|
@@ -821,7 +893,7 @@ ts_chunk_column_stats_calculate(const Hypertable *ht, const Chunk *chunk)
|
821 | 893 | col_type = get_atttype(chunk->table_id, attno);
|
822 | 894 |
|
823 | 895 | /* calculate the min/max range for this column on this chunk */
|
824 |
| - if (ts_chunk_get_minmax(chunk->table_id, col_type, attno, "column range", minmax)) |
| 896 | + if (chunk_get_minmax(chunk, col_type, col_name, minmax)) |
825 | 897 | {
|
826 | 898 | Form_chunk_column_stats range;
|
827 | 899 | int64 min = ts_time_value_to_internal(minmax[0], col_type);
|
|
0 commit comments