</programlisting>
</para>
<para>
- For example, to set the <structname>relpages</structname> and
- <structname>reltuples</structname> of the table
+ For example, to set the <structfield>relpages</structfield> and
+ <structfield>reltuples</structfield> values for the table
<structname>mytable</structname>:
<programlisting>
SELECT pg_restore_relation_stats(
<para>
The argument <literal>relation</literal> with a value of type
<type>regclass</type> is required, and specifies the table. Other
- arguments are the names of statistics corresponding to certain
- columns in <link
+ arguments are the names and values of statistics corresponding to
+ certain columns in <link
linkend="catalog-pg-class"><structname>pg_class</structname></link>.
The currently-supported relation statistics are
<literal>relpages</literal> with a value of type
value of type <type>integer</type>.
</para>
<para>
- Additionally, this function supports argument name
+ Additionally, this function accepts argument name
<literal>version</literal> of type <type>integer</type>, which
- specifies the version from which the statistics originated, improving
- interpretation of statistics from older versions of
- <productname>PostgreSQL</productname>.
+ specifies the server version from which the statistics originated.
+ This is anticipated to be helpful in porting statistics from older
+ versions of <productname>PostgreSQL</productname>.
</para>
<para>
Minor errors are reported as a <literal>WARNING</literal> and
ignored, and remaining statistics will still be restored. If all
- specified statistics are successfully restored, return
+ specified statistics are successfully restored, returns
<literal>true</literal>, otherwise <literal>false</literal>.
</para>
<para>
<returnvalue>boolean</returnvalue>
</para>
<para>
- Create or update column-level statistics. Ordinarily, these
+ Creates or updates column-level statistics. Ordinarily, these
statistics are collected automatically or updated as a part of <xref
linkend="sql-vacuum"/> or <xref linkend="sql-analyze"/>, so it's not
necessary to call this function. However, it is useful after a
</programlisting>
</para>
<para>
- For example, to set the <structname>avg_width</structname> and
- <structname>null_frac</structname> for the attribute
- <structname>col1</structname> of the table
+ For example, to set the <structfield>avg_width</structfield> and
+ <structfield>null_frac</structfield> values for the attribute
+ <structfield>col1</structfield> of the table
<structname>mytable</structname>:
<programlisting>
SELECT pg_restore_attribute_stats(
</para>
<para>
The required arguments are <literal>relation</literal> with a value
- of type <type>regclass</type>, which specifies the table;
- <literal>attname</literal> with a value of type <type>name</type>,
+ of type <type>regclass</type>, which specifies the table; either
+ <literal>attname</literal> with a value of type <type>name</type> or
+ <literal>attnum</literal> with a value of type <type>smallint</type>,
which specifies the column; and <literal>inherited</literal>, which
- specifies whether the statistics includes values from child tables.
- Other arguments are the names of statistics corresponding to columns
- in <link
+ specifies whether the statistics include values from child tables.
+ Other arguments are the names and values of statistics corresponding
+ to columns in <link
linkend="view-pg-stats"><structname>pg_stats</structname></link>.
</para>
<para>
- Additionally, this function supports argument name
+ Additionally, this function accepts argument name
<literal>version</literal> of type <type>integer</type>, which
- specifies the version from which the statistics originated, improving
- interpretation of statistics from older versions of
- <productname>PostgreSQL</productname>.
+ specifies the server version from which the statistics originated.
+ This is anticipated to be helpful in porting statistics from older
+ versions of <productname>PostgreSQL</productname>.
</para>
<para>
Minor errors are reported as a <literal>WARNING</literal> and
ignored, and remaining statistics will still be restored. If all
- specified statistics are successfully restored, return
+ specified statistics are successfully restored, returns
<literal>true</literal>, otherwise <literal>false</literal>.
</para>
<para>
{
ATTRELATION_ARG = 0,
ATTNAME_ARG,
+ ATTNUM_ARG,
INHERITED_ARG,
NULL_FRAC_ARG,
AVG_WIDTH_ARG,
{
[ATTRELATION_ARG] = {"relation", REGCLASSOID},
[ATTNAME_ARG] = {"attname", NAMEOID},
+ [ATTNUM_ARG] = {"attnum", INT2OID},
[INHERITED_ARG] = {"inherited", BOOLOID},
[NULL_FRAC_ARG] = {"null_frac", FLOAT4OID},
[AVG_WIDTH_ARG] = {"avg_width", INT4OID},
[NUM_ATTRIBUTE_STATS_ARGS] = {0}
};
+enum clear_attribute_stats_argnum
+{
+ C_ATTRELATION_ARG = 0,
+ C_ATTNAME_ARG,
+ C_INHERITED_ARG,
+ C_NUM_ATTRIBUTE_STATS_ARGS
+};
+
+static struct StatsArgInfo cleararginfo[] =
+{
+ [C_ATTRELATION_ARG] = {"relation", REGCLASSOID},
+ [C_ATTNAME_ARG] = {"attname", NAMEOID},
+ [C_INHERITED_ARG] = {"inherited", BOOLOID},
+ [C_NUM_ATTRIBUTE_STATS_ARGS] = {0}
+};
+
static bool attribute_statistics_update(FunctionCallInfo fcinfo);
static Node *get_attr_expr(Relation rel, int attnum);
static void get_attr_stat_type(Oid reloid, AttrNumber attnum,
attribute_statistics_update(FunctionCallInfo fcinfo)
{
Oid reloid;
- Name attname;
- bool inherited;
+ char *attname;
AttrNumber attnum;
+ bool inherited;
Relation starel;
HeapTuple statup;
/* lock before looking up attribute */
stats_lock_check_privileges(reloid);
- stats_check_required_arg(fcinfo, attarginfo, ATTNAME_ARG);
- attname = PG_GETARG_NAME(ATTNAME_ARG);
- attnum = get_attnum(reloid, NameStr(*attname));
+ /* user can specify either attname or attnum, but not both */
+ if (!PG_ARGISNULL(ATTNAME_ARG))
+ {
+ Name attnamename;
+
+ if (!PG_ARGISNULL(ATTNUM_ARG))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("cannot specify both attname and attnum")));
+ attnamename = PG_GETARG_NAME(ATTNAME_ARG);
+ attname = NameStr(*attnamename);
+ attnum = get_attnum(reloid, attname);
+ /* note that this test covers attisdropped cases too: */
+ if (attnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ attname, get_rel_name(reloid))));
+ }
+ else if (!PG_ARGISNULL(ATTNUM_ARG))
+ {
+ attnum = PG_GETARG_INT16(ATTNUM_ARG);
+ attname = get_attname(reloid, attnum, true);
+ /* annoyingly, get_attname doesn't check attisdropped */
+ if (attname == NULL ||
+ !SearchSysCacheExistsAttName(reloid, attname))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column %d of relation \"%s\" does not exist",
+ attnum, get_rel_name(reloid))));
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("must specify either attname or attnum")));
+ attname = NULL; /* keep compiler quiet */
+ attnum = 0;
+ }
if (attnum < 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot modify statistics on system column \"%s\"",
- NameStr(*attname))));
-
- if (attnum == InvalidAttrNumber)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column \"%s\" of relation \"%s\" does not exist",
- NameStr(*attname), get_rel_name(reloid))));
+ attname)));
stats_check_required_arg(fcinfo, attarginfo, INHERITED_ARG);
inherited = PG_GETARG_BOOL(INHERITED_ARG);
&elemtypid, &elem_eq_opr))
{
ereport(WARNING,
- (errmsg("unable to determine element type of attribute \"%s\"", NameStr(*attname)),
+ (errmsg("unable to determine element type of attribute \"%s\"", attname),
errdetail("Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST.")));
elemtypid = InvalidOid;
elem_eq_opr = InvalidOid;
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("could not determine less-than operator for attribute \"%s\"", NameStr(*attname)),
+ errmsg("could not determine less-than operator for attribute \"%s\"", attname),
errdetail("Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION.")));
do_histogram = false;
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("attribute \"%s\" is not a range type", NameStr(*attname)),
+ errmsg("attribute \"%s\" is not a range type", attname),
errdetail("Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM.")));
do_bounds_histogram = false;
AttrNumber attnum;
bool inherited;
- stats_check_required_arg(fcinfo, attarginfo, ATTRELATION_ARG);
- reloid = PG_GETARG_OID(ATTRELATION_ARG);
+ stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELATION_ARG);
+ reloid = PG_GETARG_OID(C_ATTRELATION_ARG);
if (RecoveryInProgress())
ereport(ERROR,
stats_lock_check_privileges(reloid);
- stats_check_required_arg(fcinfo, attarginfo, ATTNAME_ARG);
- attname = PG_GETARG_NAME(ATTNAME_ARG);
+ stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG);
+ attname = PG_GETARG_NAME(C_ATTNAME_ARG);
attnum = get_attnum(reloid, NameStr(*attname));
if (attnum < 0)
errmsg("column \"%s\" of relation \"%s\" does not exist",
NameStr(*attname), get_rel_name(reloid))));
- stats_check_required_arg(fcinfo, attarginfo, INHERITED_ARG);
- inherited = PG_GETARG_BOOL(INHERITED_ARG);
+ stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG);
+ inherited = PG_GETARG_BOOL(C_INHERITED_ARG);
delete_pg_statistic(reloid, attnum, inherited);
PG_RETURN_VOID();
}
+/*
+ * Import statistics for a given relation attribute.
+ *
+ * Inserts or replaces a row in pg_statistic for the given relation and
+ * attribute name or number. It takes input parameters that correspond to
+ * columns in the view pg_stats.
+ *
+ * Parameters are given in a pseudo named-attribute style: they must be
+ * pairs of parameter names (as text) and values (of appropriate types).
+ * We do that, rather than using regular named-parameter notation, so
+ * that we can add or change parameters without fear of breaking
+ * carelessly-written calls.
+ *
+ * Parameters null_frac, avg_width, and n_distinct all correspond to NOT NULL
+ * columns in pg_statistic. The remaining parameters all belong to a specific
+ * stakind. Some stakinds require multiple parameters, which must be specified
+ * together (or neither specified).
+ *
+ * Parameters are only superficially validated. Omitting a parameter or
+ * passing NULL leaves the statistic unchanged.
+ *
+ * Parameters corresponding to ANYARRAY columns are instead passed in as text
+ * values, which is a valid input string for an array of the type or element
+ * type of the attribute. Any error generated by the array_in() function will
+ * in turn fail the function.
+ */
Datum
pg_restore_attribute_stats(PG_FUNCTION_ARGS)
{
*/
static RelStatsInfo *
getRelationStatistics(Archive *fout, DumpableObject *rel, int32 relpages,
- float reltuples, int32 relallvisible, char relkind)
+ float reltuples, int32 relallvisible, char relkind,
+ char **indAttNames, int nindAttNames)
{
if (!fout->dopt->dumpStatistics)
return NULL;
info->reltuples = reltuples;
info->relallvisible = relallvisible;
info->relkind = relkind;
+ info->indAttNames = indAttNames;
+ info->nindAttNames = nindAttNames;
info->postponed_def = false;
return info;
/* Add statistics */
if (tblinfo[i].interesting)
getRelationStatistics(fout, &tblinfo[i].dobj, tblinfo[i].relpages,
- reltuples, relallvisible, tblinfo[i].relkind);
+ reltuples, relallvisible, tblinfo[i].relkind,
+ NULL, 0);
/*
* Read-lock target tables to make sure they aren't DROPPED or altered
i_contableoid,
i_conoid,
i_condef,
+ i_indattnames,
i_tablespace,
i_indreloptions,
i_indstatcols,
"c.tableoid AS contableoid, "
"c.oid AS conoid, "
"pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
+ "CASE WHEN i.indexprs IS NOT NULL THEN "
+ "(SELECT pg_catalog.array_agg(attname ORDER BY attnum)"
+ " FROM pg_catalog.pg_attribute "
+ " WHERE attrelid = i.indexrelid) "
+ "ELSE NULL END AS indattnames, "
"(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
"t.reloptions AS indreloptions, ");
i_contableoid = PQfnumber(res, "contableoid");
i_conoid = PQfnumber(res, "conoid");
i_condef = PQfnumber(res, "condef");
+ i_indattnames = PQfnumber(res, "indattnames");
i_tablespace = PQfnumber(res, "tablespace");
i_indreloptions = PQfnumber(res, "indreloptions");
i_indstatcols = PQfnumber(res, "indstatcols");
{
Oid indrelid = atooid(PQgetvalue(res, j, i_indrelid));
TableInfo *tbinfo = NULL;
+ char **indAttNames = NULL;
+ int nindAttNames = 0;
int numinds;
/* Count rows for this table */
else
indexkind = RELKIND_PARTITIONED_INDEX;
- contype = *(PQgetvalue(res, j, i_contype));
+ if (!PQgetisnull(res, j, i_indattnames))
+ {
+ if (!parsePGArray(PQgetvalue(res, j, i_indattnames),
+ &indAttNames, &nindAttNames))
+ pg_fatal("could not parse %s array", "indattnames");
+ }
+
relstats = getRelationStatistics(fout, &indxinfo[j].dobj, relpages,
- reltuples, relallvisible, indexkind);
+ reltuples, relallvisible, indexkind,
+ indAttNames, nindAttNames);
+ contype = *(PQgetvalue(res, j, i_contype));
if (contype == 'p' || contype == 'u' || contype == 'x')
{
/*
catalogId, subid, dumpId, NULL);
}
-/*
- * Tabular description of the parameters to pg_restore_attribute_stats()
- * param_name, param_type
- */
-static const char *att_stats_arginfo[][2] = {
- {"attname", "name"},
- {"inherited", "boolean"},
- {"null_frac", "float4"},
- {"avg_width", "integer"},
- {"n_distinct", "float4"},
- {"most_common_vals", "text"},
- {"most_common_freqs", "float4[]"},
- {"histogram_bounds", "text"},
- {"correlation", "float4"},
- {"most_common_elems", "text"},
- {"most_common_elem_freqs", "float4[]"},
- {"elem_count_histogram", "float4[]"},
- {"range_length_histogram", "text"},
- {"range_empty_frac", "float4"},
- {"range_bounds_histogram", "text"},
-};
-
/*
* appendNamedArgument --
*
*/
static void
appendNamedArgument(PQExpBuffer out, Archive *fout, const char *argname,
- const char *argval, const char *argtype)
+ const char *argtype, const char *argval)
{
- appendPQExpBufferStr(out, "\t");
+ appendPQExpBufferStr(out, ",\n\t");
appendStringLiteralAH(out, argname, fout);
appendPQExpBufferStr(out, ", ");
appendPQExpBuffer(out, "::%s", argtype);
}
-/*
- * appendRelStatsImport --
- *
- * Append a formatted pg_restore_relation_stats statement.
- */
-static void
-appendRelStatsImport(PQExpBuffer out, Archive *fout, const RelStatsInfo *rsinfo,
- const char *qualified_name)
-{
- char reltuples_str[FLOAT_SHORTEST_DECIMAL_LEN];
-
- float_to_shortest_decimal_buf(rsinfo->reltuples, reltuples_str);
-
- appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
- appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
- fout->remoteVersion);
- appendPQExpBuffer(out, "\t'relation', '%s'::regclass,\n", qualified_name);
- appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages);
- appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", reltuples_str);
- appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer\n);\n",
- rsinfo->relallvisible);
-}
-
-/*
- * appendAttStatsImport --
- *
- * Append a series of formatted pg_restore_attribute_stats statements.
- */
-static void
-appendAttStatsImport(PQExpBuffer out, Archive *fout, PGresult *res,
- const char *qualified_name)
-{
- for (int rownum = 0; rownum < PQntuples(res); rownum++)
- {
- const char *sep = "";
-
- appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n");
- appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
- fout->remoteVersion);
- appendPQExpBuffer(out, "\t'relation', '%s'::regclass,\n",
- qualified_name);
- for (int argno = 0; argno < lengthof(att_stats_arginfo); argno++)
- {
- const char *argname = att_stats_arginfo[argno][0];
- const char *argtype = att_stats_arginfo[argno][1];
- int fieldno = PQfnumber(res, argname);
-
- if (fieldno < 0)
- pg_fatal("attribute stats export query missing field '%s'",
- argname);
-
- if (PQgetisnull(res, rownum, fieldno))
- continue;
-
- appendPQExpBufferStr(out, sep);
- appendNamedArgument(out, fout, argname, PQgetvalue(res, rownum, fieldno), argtype);
- sep = ",\n";
- }
- appendPQExpBufferStr(out, "\n);\n");
- }
-}
-
/*
* Decide which section to use based on the relkind of the parent object.
*
static void
dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
{
+ const DumpableObject *dobj = &rsinfo->dobj;
PGresult *res;
PQExpBuffer query;
PQExpBuffer out;
PQExpBuffer tag;
- DumpableObject *dobj = (DumpableObject *) &rsinfo->dobj;
DumpId *deps = NULL;
int ndeps = 0;
- const char *qualified_name;
+ char *qualified_name;
+ char reltuples_str[FLOAT_SHORTEST_DECIMAL_LEN];
+ int i_attname;
+ int i_inherited;
+ int i_null_frac;
+ int i_avg_width;
+ int i_n_distinct;
+ int i_most_common_vals;
+ int i_most_common_freqs;
+ int i_histogram_bounds;
+ int i_correlation;
+ int i_most_common_elems;
+ int i_most_common_elem_freqs;
+ int i_elem_count_histogram;
+ int i_range_length_histogram;
+ int i_range_empty_frac;
+ int i_range_bounds_histogram;
/* nothing to do if we are not dumping statistics */
if (!fout->dopt->dumpStatistics)
if (fout->remoteVersion >= 170000)
appendPQExpBufferStr(query,
- "s.range_length_histogram, s.range_empty_frac, "
+ "s.range_length_histogram, "
+ "s.range_empty_frac, "
"s.range_bounds_histogram ");
else
appendPQExpBufferStr(query,
"NULL AS range_bounds_histogram ");
appendPQExpBufferStr(query,
- "FROM pg_stats s "
+ "FROM pg_catalog.pg_stats s "
"WHERE s.schemaname = $1 "
"AND s.tablename = $2 "
"ORDER BY s.attname, s.inherited");
resetPQExpBuffer(query);
}
+ out = createPQExpBuffer();
+
+ qualified_name = pg_strdup(fmtQualifiedDumpable(rsinfo));
+
+ /* restore relation stats */
+ appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
+ appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
+ fout->remoteVersion);
+ appendPQExpBufferStr(out, "\t'relation', ");
+ appendStringLiteralAH(out, qualified_name, fout);
+ appendPQExpBufferStr(out, "::regclass,\n");
+ appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages);
+ float_to_shortest_decimal_buf(rsinfo->reltuples, reltuples_str);
+ appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", reltuples_str);
+ appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer\n);\n",
+ rsinfo->relallvisible);
+
+ /* fetch attribute stats */
appendPQExpBufferStr(query, "EXECUTE getAttributeStats(");
appendStringLiteralAH(query, dobj->namespace->dobj.name, fout);
appendPQExpBufferStr(query, ", ");
appendStringLiteralAH(query, dobj->name, fout);
- appendPQExpBufferStr(query, "); ");
+ appendPQExpBufferStr(query, ");");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- out = createPQExpBuffer();
+ i_attname = PQfnumber(res, "attname");
+ i_inherited = PQfnumber(res, "inherited");
+ i_null_frac = PQfnumber(res, "null_frac");
+ i_avg_width = PQfnumber(res, "avg_width");
+ i_n_distinct = PQfnumber(res, "n_distinct");
+ i_most_common_vals = PQfnumber(res, "most_common_vals");
+ i_most_common_freqs = PQfnumber(res, "most_common_freqs");
+ i_histogram_bounds = PQfnumber(res, "histogram_bounds");
+ i_correlation = PQfnumber(res, "correlation");
+ i_most_common_elems = PQfnumber(res, "most_common_elems");
+ i_most_common_elem_freqs = PQfnumber(res, "most_common_elem_freqs");
+ i_elem_count_histogram = PQfnumber(res, "elem_count_histogram");
+ i_range_length_histogram = PQfnumber(res, "range_length_histogram");
+ i_range_empty_frac = PQfnumber(res, "range_empty_frac");
+ i_range_bounds_histogram = PQfnumber(res, "range_bounds_histogram");
+
+ /* restore attribute stats */
+ for (int rownum = 0; rownum < PQntuples(res); rownum++)
+ {
+ const char *attname;
- qualified_name = fmtQualifiedId(rsinfo->dobj.namespace->dobj.name,
- rsinfo->dobj.name);
+ appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n");
+ appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
+ fout->remoteVersion);
+ appendPQExpBufferStr(out, "\t'relation', ");
+ appendStringLiteralAH(out, qualified_name, fout);
+ appendPQExpBufferStr(out, "::regclass");
+
+ if (PQgetisnull(res, rownum, i_attname))
+ pg_fatal("attname cannot be NULL");
+ attname = PQgetvalue(res, rownum, i_attname);
+
+ /*
+ * Indexes look up attname in indAttNames to derive attnum, all others
+ * use attname directly. We must specify attnum for indexes, since
+ * their attnames are not necessarily stable across dump/reload.
+ */
+ if (rsinfo->nindAttNames == 0)
+ appendNamedArgument(out, fout, "attname", "name", attname);
+ else
+ {
+ bool found = false;
+
+ for (int i = 0; i < rsinfo->nindAttNames; i++)
+ {
+ if (strcmp(attname, rsinfo->indAttNames[i]) == 0)
+ {
+ appendPQExpBuffer(out, ",\n\t'attnum', '%d'::smallint",
+ i + 1);
+ found = true;
+ break;
+ }
+ }
- appendRelStatsImport(out, fout, rsinfo, qualified_name);
- appendAttStatsImport(out, fout, res, qualified_name);
+ if (!found)
+ pg_fatal("could not find index attname \"%s\"", attname);
+ }
+
+ if (!PQgetisnull(res, rownum, i_inherited))
+ appendNamedArgument(out, fout, "inherited", "boolean",
+ PQgetvalue(res, rownum, i_inherited));
+ if (!PQgetisnull(res, rownum, i_null_frac))
+ appendNamedArgument(out, fout, "null_frac", "real",
+ PQgetvalue(res, rownum, i_null_frac));
+ if (!PQgetisnull(res, rownum, i_avg_width))
+ appendNamedArgument(out, fout, "avg_width", "integer",
+ PQgetvalue(res, rownum, i_avg_width));
+ if (!PQgetisnull(res, rownum, i_n_distinct))
+ appendNamedArgument(out, fout, "n_distinct", "real",
+ PQgetvalue(res, rownum, i_n_distinct));
+ if (!PQgetisnull(res, rownum, i_most_common_vals))
+ appendNamedArgument(out, fout, "most_common_vals", "text",
+ PQgetvalue(res, rownum, i_most_common_vals));
+ if (!PQgetisnull(res, rownum, i_most_common_freqs))
+ appendNamedArgument(out, fout, "most_common_freqs", "real[]",
+ PQgetvalue(res, rownum, i_most_common_freqs));
+ if (!PQgetisnull(res, rownum, i_histogram_bounds))
+ appendNamedArgument(out, fout, "histogram_bounds", "text",
+ PQgetvalue(res, rownum, i_histogram_bounds));
+ if (!PQgetisnull(res, rownum, i_correlation))
+ appendNamedArgument(out, fout, "correlation", "real",
+ PQgetvalue(res, rownum, i_correlation));
+ if (!PQgetisnull(res, rownum, i_most_common_elems))
+ appendNamedArgument(out, fout, "most_common_elems", "text",
+ PQgetvalue(res, rownum, i_most_common_elems));
+ if (!PQgetisnull(res, rownum, i_most_common_elem_freqs))
+ appendNamedArgument(out, fout, "most_common_elem_freqs", "real[]",
+ PQgetvalue(res, rownum, i_most_common_elem_freqs));
+ if (!PQgetisnull(res, rownum, i_elem_count_histogram))
+ appendNamedArgument(out, fout, "elem_count_histogram", "real[]",
+ PQgetvalue(res, rownum, i_elem_count_histogram));
+ if (fout->remoteVersion >= 170000)
+ {
+ if (!PQgetisnull(res, rownum, i_range_length_histogram))
+ appendNamedArgument(out, fout, "range_length_histogram", "text",
+ PQgetvalue(res, rownum, i_range_length_histogram));
+ if (!PQgetisnull(res, rownum, i_range_empty_frac))
+ appendNamedArgument(out, fout, "range_empty_frac", "real",
+ PQgetvalue(res, rownum, i_range_empty_frac));
+ if (!PQgetisnull(res, rownum, i_range_bounds_histogram))
+ appendNamedArgument(out, fout, "range_bounds_histogram", "text",
+ PQgetvalue(res, rownum, i_range_bounds_histogram));
+ }
+ appendPQExpBufferStr(out, "\n);\n");
+ }
PQclear(res);
.deps = deps,
.nDeps = ndeps));
- destroyPQExpBuffer(query);
+ free(qualified_name);
destroyPQExpBuffer(out);
+ destroyPQExpBuffer(query);
destroyPQExpBuffer(tag);
}