Use the "pg_temp" schema alias in EXPLAIN and related output.
This patch causes EXPLAIN output to refer to objects that are in the current session's temp schema with the "pg_temp" schema alias rather than that schema's actual name. This is useful for our own testing purposes since it will stabilize EXPLAIN VERBOSE output for such cases, allowing us to use that in regression tests. It should be less confusing for end users too. Since ruleutils.c needs to change behavior for this, the change also leaks into a few other users of ruleutils.c, for example pg_get_viewdef(). AFAICS that won't cause any problems. We did find that aggressively trying to change this behavior across-the-board would cause issues, but as long as "pg_temp" only appears within generated SQL text, I think it'll be fine. Along the way, make get_namespace_name_or_temp conform to the same API as get_namespace_name, ie that it returns a palloc'd string or NULL. The current behavior hasn't caused any bugs since no callers attempt to pfree the result, but if it gets more widespread usage that could become a problem. Amul Sul, reviewed and extended by me Discussion: https://postgr.es/m/CAAJ_b97W=QaGmag9AhWNbmx3uEYsNkXWL+OVW1_E1D3BtgWvtw@mail.gmail.com
This commit is contained in:
parent
91d76613b7
commit
48c5c90682
|
@ -2854,7 +2854,7 @@ postgresExplainForeignScan(ForeignScanState *node, ExplainState *es)
|
||||||
{
|
{
|
||||||
char *namespace;
|
char *namespace;
|
||||||
|
|
||||||
namespace = get_namespace_name(get_rel_namespace(rte->relid));
|
namespace = get_namespace_name_or_temp(get_rel_namespace(rte->relid));
|
||||||
appendStringInfo(relations, "%s.%s",
|
appendStringInfo(relations, "%s.%s",
|
||||||
quote_identifier(namespace),
|
quote_identifier(namespace),
|
||||||
quote_identifier(relname));
|
quote_identifier(relname));
|
||||||
|
|
|
@ -3747,7 +3747,7 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
|
||||||
Assert(rte->rtekind == RTE_RELATION);
|
Assert(rte->rtekind == RTE_RELATION);
|
||||||
objectname = get_rel_name(rte->relid);
|
objectname = get_rel_name(rte->relid);
|
||||||
if (es->verbose)
|
if (es->verbose)
|
||||||
namespace = get_namespace_name(get_rel_namespace(rte->relid));
|
namespace = get_namespace_name_or_temp(get_rel_namespace(rte->relid));
|
||||||
objecttag = "Relation Name";
|
objecttag = "Relation Name";
|
||||||
break;
|
break;
|
||||||
case T_FunctionScan:
|
case T_FunctionScan:
|
||||||
|
@ -3774,8 +3774,7 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
|
||||||
|
|
||||||
objectname = get_func_name(funcid);
|
objectname = get_func_name(funcid);
|
||||||
if (es->verbose)
|
if (es->verbose)
|
||||||
namespace =
|
namespace = get_namespace_name_or_temp(get_func_namespace(funcid));
|
||||||
get_namespace_name(get_func_namespace(funcid));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
objecttag = "Function Name";
|
objecttag = "Function Name";
|
||||||
|
|
|
@ -1617,7 +1617,7 @@ pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok)
|
||||||
|
|
||||||
if (!columns_only)
|
if (!columns_only)
|
||||||
{
|
{
|
||||||
nsp = get_namespace_name(statextrec->stxnamespace);
|
nsp = get_namespace_name_or_temp(statextrec->stxnamespace);
|
||||||
appendStringInfo(&buf, "CREATE STATISTICS %s",
|
appendStringInfo(&buf, "CREATE STATISTICS %s",
|
||||||
quote_qualified_identifier(nsp,
|
quote_qualified_identifier(nsp,
|
||||||
NameStr(statextrec->stxname)));
|
NameStr(statextrec->stxname)));
|
||||||
|
@ -2811,7 +2811,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
|
||||||
* We always qualify the function name, to ensure the right function gets
|
* We always qualify the function name, to ensure the right function gets
|
||||||
* replaced.
|
* replaced.
|
||||||
*/
|
*/
|
||||||
nsp = get_namespace_name(proc->pronamespace);
|
nsp = get_namespace_name_or_temp(proc->pronamespace);
|
||||||
appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
|
appendStringInfo(&buf, "CREATE OR REPLACE %s %s(",
|
||||||
isfunction ? "FUNCTION" : "PROCEDURE",
|
isfunction ? "FUNCTION" : "PROCEDURE",
|
||||||
quote_qualified_identifier(nsp, name));
|
quote_qualified_identifier(nsp, name));
|
||||||
|
@ -11183,7 +11183,7 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
|
||||||
appendStringInfo(buf, " %s", quote_identifier(opcname));
|
appendStringInfo(buf, " %s", quote_identifier(opcname));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nspname = get_namespace_name(opcrec->opcnamespace);
|
nspname = get_namespace_name_or_temp(opcrec->opcnamespace);
|
||||||
appendStringInfo(buf, " %s.%s",
|
appendStringInfo(buf, " %s.%s",
|
||||||
quote_identifier(nspname),
|
quote_identifier(nspname),
|
||||||
quote_identifier(opcname));
|
quote_identifier(opcname));
|
||||||
|
@ -11495,7 +11495,7 @@ generate_relation_name(Oid relid, List *namespaces)
|
||||||
need_qual = !RelationIsVisible(relid);
|
need_qual = !RelationIsVisible(relid);
|
||||||
|
|
||||||
if (need_qual)
|
if (need_qual)
|
||||||
nspname = get_namespace_name(reltup->relnamespace);
|
nspname = get_namespace_name_or_temp(reltup->relnamespace);
|
||||||
else
|
else
|
||||||
nspname = NULL;
|
nspname = NULL;
|
||||||
|
|
||||||
|
@ -11527,7 +11527,7 @@ generate_qualified_relation_name(Oid relid)
|
||||||
reltup = (Form_pg_class) GETSTRUCT(tp);
|
reltup = (Form_pg_class) GETSTRUCT(tp);
|
||||||
relname = NameStr(reltup->relname);
|
relname = NameStr(reltup->relname);
|
||||||
|
|
||||||
nspname = get_namespace_name(reltup->relnamespace);
|
nspname = get_namespace_name_or_temp(reltup->relnamespace);
|
||||||
if (!nspname)
|
if (!nspname)
|
||||||
elog(ERROR, "cache lookup failed for namespace %u",
|
elog(ERROR, "cache lookup failed for namespace %u",
|
||||||
reltup->relnamespace);
|
reltup->relnamespace);
|
||||||
|
@ -11639,7 +11639,7 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
|
||||||
p_funcid == funcid)
|
p_funcid == funcid)
|
||||||
nspname = NULL;
|
nspname = NULL;
|
||||||
else
|
else
|
||||||
nspname = get_namespace_name(procform->pronamespace);
|
nspname = get_namespace_name_or_temp(procform->pronamespace);
|
||||||
|
|
||||||
result = quote_qualified_identifier(nspname, proname);
|
result = quote_qualified_identifier(nspname, proname);
|
||||||
|
|
||||||
|
@ -11702,7 +11702,7 @@ generate_operator_name(Oid operid, Oid arg1, Oid arg2)
|
||||||
nspname = NULL;
|
nspname = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nspname = get_namespace_name(operform->oprnamespace);
|
nspname = get_namespace_name_or_temp(operform->oprnamespace);
|
||||||
appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
|
appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11790,7 +11790,7 @@ add_cast_to(StringInfo buf, Oid typid)
|
||||||
typform = (Form_pg_type) GETSTRUCT(typetup);
|
typform = (Form_pg_type) GETSTRUCT(typetup);
|
||||||
|
|
||||||
typname = NameStr(typform->typname);
|
typname = NameStr(typform->typname);
|
||||||
nspname = get_namespace_name(typform->typnamespace);
|
nspname = get_namespace_name_or_temp(typform->typnamespace);
|
||||||
|
|
||||||
appendStringInfo(buf, "::%s.%s",
|
appendStringInfo(buf, "::%s.%s",
|
||||||
quote_identifier(nspname), quote_identifier(typname));
|
quote_identifier(nspname), quote_identifier(typname));
|
||||||
|
@ -11822,7 +11822,7 @@ generate_qualified_type_name(Oid typid)
|
||||||
typtup = (Form_pg_type) GETSTRUCT(tp);
|
typtup = (Form_pg_type) GETSTRUCT(tp);
|
||||||
typname = NameStr(typtup->typname);
|
typname = NameStr(typtup->typname);
|
||||||
|
|
||||||
nspname = get_namespace_name(typtup->typnamespace);
|
nspname = get_namespace_name_or_temp(typtup->typnamespace);
|
||||||
if (!nspname)
|
if (!nspname)
|
||||||
elog(ERROR, "cache lookup failed for namespace %u",
|
elog(ERROR, "cache lookup failed for namespace %u",
|
||||||
typtup->typnamespace);
|
typtup->typnamespace);
|
||||||
|
@ -11856,7 +11856,7 @@ generate_collation_name(Oid collid)
|
||||||
collname = NameStr(colltup->collname);
|
collname = NameStr(colltup->collname);
|
||||||
|
|
||||||
if (!CollationIsVisible(collid))
|
if (!CollationIsVisible(collid))
|
||||||
nspname = get_namespace_name(colltup->collnamespace);
|
nspname = get_namespace_name_or_temp(colltup->collnamespace);
|
||||||
else
|
else
|
||||||
nspname = NULL;
|
nspname = NULL;
|
||||||
|
|
||||||
|
|
|
@ -3340,7 +3340,7 @@ char *
|
||||||
get_namespace_name_or_temp(Oid nspid)
|
get_namespace_name_or_temp(Oid nspid)
|
||||||
{
|
{
|
||||||
if (isTempNamespace(nspid))
|
if (isTempNamespace(nspid))
|
||||||
return "pg_temp";
|
return pstrdup("pg_temp");
|
||||||
else
|
else
|
||||||
return get_namespace_name(nspid);
|
return get_namespace_name(nspid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -477,6 +477,19 @@ select jsonb_pretty(
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
rollback;
|
rollback;
|
||||||
|
-- Test display of temporary objects
|
||||||
|
create temp table t1(f1 float8);
|
||||||
|
create function pg_temp.mysin(float8) returns float8 language plpgsql
|
||||||
|
as 'begin return sin($1); end';
|
||||||
|
select explain_filter('explain (verbose) select * from t1 where pg_temp.mysin(f1) < 0.5');
|
||||||
|
explain_filter
|
||||||
|
------------------------------------------------------------
|
||||||
|
Seq Scan on pg_temp.t1 (cost=N.N..N.N rows=N width=N)
|
||||||
|
Output: f1
|
||||||
|
Filter: (pg_temp.mysin(t1.f1) < 'N.N'::double precision)
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
-- Test compute_query_id
|
||||||
set compute_query_id = on;
|
set compute_query_id = on;
|
||||||
select explain_filter('explain (verbose) select * from int8_tbl i8');
|
select explain_filter('explain (verbose) select * from int8_tbl i8');
|
||||||
explain_filter
|
explain_filter
|
||||||
|
|
|
@ -104,5 +104,14 @@ select jsonb_pretty(
|
||||||
|
|
||||||
rollback;
|
rollback;
|
||||||
|
|
||||||
|
-- Test display of temporary objects
|
||||||
|
create temp table t1(f1 float8);
|
||||||
|
|
||||||
|
create function pg_temp.mysin(float8) returns float8 language plpgsql
|
||||||
|
as 'begin return sin($1); end';
|
||||||
|
|
||||||
|
select explain_filter('explain (verbose) select * from t1 where pg_temp.mysin(f1) < 0.5');
|
||||||
|
|
||||||
|
-- Test compute_query_id
|
||||||
set compute_query_id = on;
|
set compute_query_id = on;
|
||||||
select explain_filter('explain (verbose) select * from int8_tbl i8');
|
select explain_filter('explain (verbose) select * from int8_tbl i8');
|
||||||
|
|
Loading…
Reference in New Issue