2002-04-25 04:56:56 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* regproc.c
|
2002-04-25 04:56:56 +02:00
|
|
|
* Functions for the built-in types regproc, regclass, regtype, etc.
|
|
|
|
*
|
|
|
|
* These types are all binary-compatible with type Oid, and rely on Oid
|
|
|
|
* for comparison and so forth. Their only interesting behavior is in
|
|
|
|
* special I/O conversion routines.
|
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2020-01-01 18:21:45 +01:00
|
|
|
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/utils/adt/regproc.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
#include <ctype.h>
|
|
|
|
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
2002-04-25 04:56:56 +02:00
|
|
|
#include "catalog/namespace.h"
|
2008-06-19 02:46:06 +02:00
|
|
|
#include "catalog/pg_class.h"
|
2020-03-18 21:20:01 +01:00
|
|
|
#include "catalog/pg_collation.h"
|
2002-04-25 04:56:56 +02:00
|
|
|
#include "catalog/pg_operator.h"
|
1998-08-19 04:04:17 +02:00
|
|
|
#include "catalog/pg_proc.h"
|
2007-08-21 03:11:32 +02:00
|
|
|
#include "catalog/pg_ts_config.h"
|
|
|
|
#include "catalog/pg_ts_dict.h"
|
2002-04-25 04:56:56 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2012-08-29 01:02:00 +02:00
|
|
|
#include "lib/stringinfo.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "miscadmin.h"
|
2002-04-25 04:56:56 +02:00
|
|
|
#include "parser/parse_type.h"
|
2017-05-24 21:28:34 +02:00
|
|
|
#include "parser/scansup.h"
|
2019-11-12 04:00:16 +01:00
|
|
|
#include "utils/acl.h"
|
1999-07-16 05:14:30 +02:00
|
|
|
#include "utils/builtins.h"
|
2002-04-25 04:56:56 +02:00
|
|
|
#include "utils/lsyscache.h"
|
2017-01-21 02:29:53 +01:00
|
|
|
#include "utils/regproc.h"
|
2019-11-12 04:00:16 +01:00
|
|
|
#include "utils/syscache.h"
|
2017-01-21 02:29:53 +01:00
|
|
|
#include "utils/varlena.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2013-03-20 22:19:19 +01:00
|
|
|
static char *format_operator_internal(Oid operator_oid, bool force_qualify);
|
|
|
|
static char *format_procedure_internal(Oid procedure_oid, bool force_qualify);
|
2007-06-26 18:48:09 +02:00
|
|
|
static void parseNameAndArgTypes(const char *string, bool allowNone,
|
2019-05-22 19:04:48 +02:00
|
|
|
List **names, int *nargs, Oid *argtypes);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* USER I/O ROUTINES *
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
1998-09-01 06:40:42 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2002-04-25 04:56:56 +02:00
|
|
|
* regprocin - converts "proname" to proc OID
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
2001-08-21 18:36:06 +02:00
|
|
|
*
|
2002-04-25 04:56:56 +02:00
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_proc entry.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
regprocin(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
char *pro_name_or_oid = PG_GETARG_CSTRING(0);
|
1999-05-25 18:15:34 +02:00
|
|
|
RegProcedure result = InvalidOid;
|
2002-04-25 04:56:56 +02:00
|
|
|
List *names;
|
|
|
|
FuncCandidateList clist;
|
1998-08-19 04:04:17 +02:00
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(pro_name_or_oid, "-") == 0)
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_OID(InvalidOid);
|
1998-08-19 04:04:17 +02:00
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/* Numeric OID? */
|
2001-08-21 18:36:06 +02:00
|
|
|
if (pro_name_or_oid[0] >= '0' &&
|
2002-04-05 02:31:36 +02:00
|
|
|
pro_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(pro_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
PG_RETURN_OID(result);
|
2001-08-21 18:36:06 +02:00
|
|
|
}
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/* Else it's a name, possibly schema-qualified */
|
|
|
|
|
|
|
|
/*
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
* We should never get here in bootstrap mode, as all references should
|
|
|
|
* have been resolved by genbki.pl.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
|
|
|
if (IsBootstrapProcessingMode())
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
elog(ERROR, "regproc values must be OIDs in bootstrap mode");
|
1998-08-19 04:04:17 +02:00
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Normal case: parse the name into components and see if it matches any
|
|
|
|
* pg_proc entries in the current search path.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2007-06-26 18:48:09 +02:00
|
|
|
names = stringToQualifiedNameList(pro_name_or_oid);
|
2014-01-23 18:40:29 +01:00
|
|
|
clist = FuncnameGetCandidates(names, -1, NIL, false, false, false);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (clist == NULL)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
else if (clist->next != NULL)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("more than one function named \"%s\"",
|
2003-08-04 02:43:34 +02:00
|
|
|
pro_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
result = clist->oid;
|
2001-08-21 18:36:06 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_OID(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2014-04-08 16:27:56 +02:00
|
|
|
/*
|
|
|
|
* to_regproc - converts "proname" to proc OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regproc(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *pro_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2014-04-08 16:27:56 +02:00
|
|
|
List *names;
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Parse the name into components and see if it matches any pg_proc
|
|
|
|
* entries in the current search path.
|
2014-04-08 16:27:56 +02:00
|
|
|
*/
|
|
|
|
names = stringToQualifiedNameList(pro_name);
|
|
|
|
clist = FuncnameGetCandidates(names, -1, NIL, false, false, true);
|
|
|
|
|
|
|
|
if (clist == NULL || clist->next != NULL)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
|
|
|
PG_RETURN_OID(clist->oid);
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2002-04-25 04:56:56 +02:00
|
|
|
* regprocout - converts proc OID to "pro_name"
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
regprocout(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
RegProcedure proid = PG_GETARG_OID(0);
|
1997-09-08 04:41:22 +02:00
|
|
|
char *result;
|
2002-04-25 04:56:56 +02:00
|
|
|
HeapTuple proctup;
|
|
|
|
|
|
|
|
if (proid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(proid));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(proctup))
|
|
|
|
{
|
|
|
|
Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
|
|
|
|
char *proname = NameStr(procform->proname);
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* In bootstrap mode, skip the fancy namespace stuff and just return
|
|
|
|
* the proc name. (This path is only needed for debugging output
|
|
|
|
* anyway.)
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
result = pstrdup(proname);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *nspname;
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
/*
|
2002-09-04 22:31:48 +02:00
|
|
|
* Would this proc be found (uniquely!) by regprocin? If not,
|
|
|
|
* qualify it.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2008-07-16 03:30:23 +02:00
|
|
|
clist = FuncnameGetCandidates(list_make1(makeString(proname)),
|
2014-01-23 18:40:29 +01:00
|
|
|
-1, NIL, false, false, false);
|
2002-04-25 04:56:56 +02:00
|
|
|
if (clist != NULL && clist->next == NULL &&
|
|
|
|
clist->oid == proid)
|
|
|
|
nspname = NULL;
|
|
|
|
else
|
|
|
|
nspname = get_namespace_name(procform->pronamespace);
|
|
|
|
|
|
|
|
result = quote_qualified_identifier(nspname, proname);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(proctup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If OID doesn't match any pg_proc entry, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", proid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* regprocrecv - converts external binary format to regproc
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regprocrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regprocsend - converts regproc to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regprocsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* regprocedurein - converts "proname(args)" to proc OID
|
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
2002-04-25 04:56:56 +02:00
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_proc entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regprocedurein(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *pro_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
RegProcedure result = InvalidOid;
|
|
|
|
List *names;
|
|
|
|
int nargs;
|
|
|
|
Oid argtypes[FUNC_MAX_ARGS];
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(pro_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (pro_name_or_oid[0] >= '0' &&
|
|
|
|
pro_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
|
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(pro_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
elog(ERROR, "regprocedure values must be OIDs in bootstrap mode");
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Else it's a name and arguments. Parse the name and arguments, look up
|
|
|
|
* potential matches in the current namespace search list, and scan to see
|
2014-05-06 18:12:18 +02:00
|
|
|
* which one exactly matches the given argument types. (There will not be
|
2005-10-15 04:49:52 +02:00
|
|
|
* more than one match.)
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2007-06-26 18:48:09 +02:00
|
|
|
parseNameAndArgTypes(pro_name_or_oid, false, &names, &nargs, argtypes);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2014-01-23 18:40:29 +01:00
|
|
|
clist = FuncnameGetCandidates(names, nargs, NIL, false, false, false);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
for (; clist; clist = clist->next)
|
|
|
|
{
|
|
|
|
if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clist == NULL)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("function \"%s\" does not exist", pro_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
result = clist->oid;
|
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
2014-04-16 18:21:43 +02:00
|
|
|
/*
|
|
|
|
* to_regprocedure - converts "proname(args)" to proc OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regprocedure(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *pro_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2014-04-16 18:21:43 +02:00
|
|
|
List *names;
|
|
|
|
int nargs;
|
|
|
|
Oid argtypes[FUNC_MAX_ARGS];
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the name and arguments, look up potential matches in the current
|
|
|
|
* namespace search list, and scan to see which one exactly matches the
|
2014-05-06 18:12:18 +02:00
|
|
|
* given argument types. (There will not be more than one match.)
|
2014-04-16 18:21:43 +02:00
|
|
|
*/
|
|
|
|
parseNameAndArgTypes(pro_name, false, &names, &nargs, argtypes);
|
|
|
|
|
|
|
|
clist = FuncnameGetCandidates(names, nargs, NIL, false, false, true);
|
|
|
|
|
|
|
|
for (; clist; clist = clist->next)
|
|
|
|
{
|
|
|
|
if (memcmp(clist->args, argtypes, nargs * sizeof(Oid)) == 0)
|
|
|
|
PG_RETURN_OID(clist->oid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
2002-07-30 00:14:11 +02:00
|
|
|
* format_procedure - converts proc OID to "pro_name(args)"
|
|
|
|
*
|
|
|
|
* This exports the useful functionality of regprocedureout for use
|
|
|
|
* in other backend modules. The result is a palloc'd string.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2002-07-30 00:14:11 +02:00
|
|
|
char *
|
|
|
|
format_procedure(Oid procedure_oid)
|
2013-03-20 22:19:19 +01:00
|
|
|
{
|
|
|
|
return format_procedure_internal(procedure_oid, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
format_procedure_qualified(Oid procedure_oid)
|
|
|
|
{
|
|
|
|
return format_procedure_internal(procedure_oid, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Routine to produce regprocedure names; see format_procedure above.
|
|
|
|
*
|
|
|
|
* force_qualify says whether to schema-qualify; if true, the name is always
|
2014-05-06 18:12:18 +02:00
|
|
|
* qualified regardless of search_path visibility. Otherwise the name is only
|
2013-03-20 22:19:19 +01:00
|
|
|
* qualified if the function is not in path.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
format_procedure_internal(Oid procedure_oid, bool force_qualify)
|
2002-04-25 04:56:56 +02:00
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
HeapTuple proctup;
|
1998-08-19 04:04:17 +02:00
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid));
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2001-08-21 18:36:06 +02:00
|
|
|
if (HeapTupleIsValid(proctup))
|
|
|
|
{
|
2002-04-25 04:56:56 +02:00
|
|
|
Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
|
|
|
|
char *proname = NameStr(procform->proname);
|
|
|
|
int nargs = procform->pronargs;
|
|
|
|
int i;
|
|
|
|
char *nspname;
|
|
|
|
StringInfoData buf;
|
|
|
|
|
|
|
|
/* XXX no support here for bootstrap mode */
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
Assert(!IsBootstrapProcessingMode());
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
initStringInfo(&buf);
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Would this proc be found (given the right args) by regprocedurein?
|
Add sql_drop event for event triggers
This event takes place just before ddl_command_end, and is fired if and
only if at least one object has been dropped by the command. (For
instance, DROP TABLE IF EXISTS of a table that does not in fact exist
will not lead to such a trigger firing). Commands that drop multiple
objects (such as DROP SCHEMA or DROP OWNED BY) will cause a single event
to fire. Some firings might be surprising, such as
ALTER TABLE DROP COLUMN.
The trigger is fired after the drop has taken place, because that has
been deemed the safest design, to avoid exposing possibly-inconsistent
internal state (system catalogs as well as current transaction) to the
user function code. This means that careful tracking of object
identification is required during the object removal phase.
Like other currently existing events, there is support for tag
filtering.
To support the new event, add a new pg_event_trigger_dropped_objects()
set-returning function, which returns a set of rows comprising the
objects affected by the command. This is to be used within the user
function code, and is mostly modelled after the recently introduced
pg_identify_object() function.
Catalog version bumped due to the new function.
Dimitri Fontaine and Álvaro Herrera
Review by Robert Haas, Tom Lane
2013-03-27 20:02:10 +01:00
|
|
|
* If not, or if caller requests it, we need to qualify it.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2013-03-20 22:19:19 +01:00
|
|
|
if (!force_qualify && FunctionIsVisible(procedure_oid))
|
2002-04-25 04:56:56 +02:00
|
|
|
nspname = NULL;
|
|
|
|
else
|
|
|
|
nspname = get_namespace_name(procform->pronamespace);
|
|
|
|
|
|
|
|
appendStringInfo(&buf, "%s(",
|
|
|
|
quote_qualified_identifier(nspname, proname));
|
|
|
|
for (i = 0; i < nargs; i++)
|
|
|
|
{
|
2005-03-29 02:17:27 +02:00
|
|
|
Oid thisargtype = procform->proargtypes.values[i];
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2002-05-11 02:24:16 +02:00
|
|
|
if (i > 0)
|
|
|
|
appendStringInfoChar(&buf, ',');
|
2013-03-20 22:19:19 +01:00
|
|
|
appendStringInfoString(&buf,
|
|
|
|
force_qualify ?
|
|
|
|
format_type_be_qualified(thisargtype) :
|
|
|
|
format_type_be(thisargtype));
|
2002-05-11 02:24:16 +02:00
|
|
|
}
|
|
|
|
appendStringInfoChar(&buf, ')');
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
result = buf.data;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2001-08-21 18:36:06 +02:00
|
|
|
ReleaseSysCache(proctup);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1998-08-19 04:04:17 +02:00
|
|
|
else
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2002-04-25 04:56:56 +02:00
|
|
|
/* If OID doesn't match any pg_proc entry, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
2002-07-30 00:14:11 +02:00
|
|
|
snprintf(result, NAMEDATALEN, "%u", procedure_oid);
|
2002-04-25 04:56:56 +02:00
|
|
|
}
|
|
|
|
|
2002-07-30 00:14:11 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-12-30 19:41:50 +01:00
|
|
|
/*
|
2015-05-20 15:18:11 +02:00
|
|
|
* Output an objname/objargs representation for the procedure with the
|
2014-12-30 19:41:50 +01:00
|
|
|
* given OID. If it doesn't exist, an error is thrown.
|
|
|
|
*
|
|
|
|
* This can be used to feed get_object_address.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs)
|
|
|
|
{
|
|
|
|
HeapTuple proctup;
|
|
|
|
Form_pg_proc procform;
|
|
|
|
int nargs;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid));
|
|
|
|
|
|
|
|
if (!HeapTupleIsValid(proctup))
|
|
|
|
elog(ERROR, "cache lookup failed for procedure with OID %u", procedure_oid);
|
|
|
|
|
|
|
|
procform = (Form_pg_proc) GETSTRUCT(proctup);
|
|
|
|
nargs = procform->pronargs;
|
|
|
|
|
2015-04-06 16:40:55 +02:00
|
|
|
*objnames = list_make2(get_namespace_name_or_temp(procform->pronamespace),
|
2014-12-30 19:41:50 +01:00
|
|
|
pstrdup(NameStr(procform->proname)));
|
|
|
|
*objargs = NIL;
|
|
|
|
for (i = 0; i < nargs; i++)
|
|
|
|
{
|
2015-05-24 03:35:49 +02:00
|
|
|
Oid thisargtype = procform->proargtypes.values[i];
|
2014-12-30 19:41:50 +01:00
|
|
|
|
|
|
|
*objargs = lappend(*objargs, format_type_be_qualified(thisargtype));
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(proctup);
|
|
|
|
}
|
|
|
|
|
2002-07-30 00:14:11 +02:00
|
|
|
/*
|
|
|
|
* regprocedureout - converts proc OID to "pro_name(args)"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regprocedureout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
RegProcedure proid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
if (proid == InvalidOid)
|
|
|
|
result = pstrdup("-");
|
|
|
|
else
|
|
|
|
result = format_procedure(proid);
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* regprocedurerecv - converts external binary format to regprocedure
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regprocedurerecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regproceduresend - converts regprocedure to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regproceduresend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* regoperin - converts "oprname" to operator OID
|
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
2002-04-25 04:56:56 +02:00
|
|
|
*
|
|
|
|
* '0' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_operator entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regoperin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *opr_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
Oid result = InvalidOid;
|
|
|
|
List *names;
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
/* '0' ? */
|
|
|
|
if (strcmp(opr_name_or_oid, "0") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (opr_name_or_oid[0] >= '0' &&
|
|
|
|
opr_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
|
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(opr_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Else it's a name, possibly schema-qualified */
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
2002-04-25 04:56:56 +02:00
|
|
|
if (IsBootstrapProcessingMode())
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
elog(ERROR, "regoper values must be OIDs in bootstrap mode");
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Normal case: parse the name into components and see if it matches any
|
|
|
|
* pg_operator entries in the current search path.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2007-06-26 18:48:09 +02:00
|
|
|
names = stringToQualifiedNameList(opr_name_or_oid);
|
2014-04-08 16:27:56 +02:00
|
|
|
clist = OpernameGetCandidates(names, '\0', false);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (clist == NULL)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("operator does not exist: %s", opr_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
else if (clist->next != NULL)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
|
|
|
|
errmsg("more than one operator named %s",
|
2003-08-04 02:43:34 +02:00
|
|
|
opr_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
result = clist->oid;
|
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
2014-04-08 16:27:56 +02:00
|
|
|
/*
|
|
|
|
* to_regoper - converts "oprname" to operator OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regoper(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *opr_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2014-04-08 16:27:56 +02:00
|
|
|
List *names;
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the name into components and see if it matches any pg_operator
|
|
|
|
* entries in the current search path.
|
|
|
|
*/
|
|
|
|
names = stringToQualifiedNameList(opr_name);
|
|
|
|
clist = OpernameGetCandidates(names, '\0', true);
|
|
|
|
|
|
|
|
if (clist == NULL || clist->next != NULL)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
|
|
|
PG_RETURN_OID(clist->oid);
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
|
|
|
* regoperout - converts operator OID to "opr_name"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regoperout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oprid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
HeapTuple opertup;
|
|
|
|
|
|
|
|
if (oprid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("0");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(opertup))
|
|
|
|
{
|
|
|
|
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
|
|
|
|
char *oprname = NameStr(operform->oprname);
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* In bootstrap mode, skip the fancy namespace stuff and just return
|
|
|
|
* the oper name. (This path is only needed for debugging output
|
|
|
|
* anyway.)
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
result = pstrdup(oprname);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FuncCandidateList clist;
|
|
|
|
|
|
|
|
/*
|
2002-09-04 22:31:48 +02:00
|
|
|
* Would this oper be found (uniquely!) by regoperin? If not,
|
|
|
|
* qualify it.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2004-05-31 01:40:41 +02:00
|
|
|
clist = OpernameGetCandidates(list_make1(makeString(oprname)),
|
2014-04-08 16:27:56 +02:00
|
|
|
'\0', false);
|
2002-04-25 04:56:56 +02:00
|
|
|
if (clist != NULL && clist->next == NULL &&
|
|
|
|
clist->oid == oprid)
|
|
|
|
result = pstrdup(oprname);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const char *nspname;
|
|
|
|
|
|
|
|
nspname = get_namespace_name(operform->oprnamespace);
|
|
|
|
nspname = quote_identifier(nspname);
|
2002-09-04 22:31:48 +02:00
|
|
|
result = (char *) palloc(strlen(nspname) + strlen(oprname) + 2);
|
2002-04-25 04:56:56 +02:00
|
|
|
sprintf(result, "%s.%s", nspname, oprname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(opertup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If OID doesn't match any pg_operator entry, return it numerically
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2002-04-25 04:56:56 +02:00
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", oprid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* regoperrecv - converts external binary format to regoper
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regoperrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regopersend - converts regoper to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regopersend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* regoperatorin - converts "oprname(args)" to operator OID
|
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
2002-04-25 04:56:56 +02:00
|
|
|
*
|
|
|
|
* '0' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_operator entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regoperatorin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *opr_name_or_oid = PG_GETARG_CSTRING(0);
|
2006-05-02 01:22:43 +02:00
|
|
|
Oid result;
|
2002-04-25 04:56:56 +02:00
|
|
|
List *names;
|
|
|
|
int nargs;
|
|
|
|
Oid argtypes[FUNC_MAX_ARGS];
|
|
|
|
|
|
|
|
/* '0' ? */
|
|
|
|
if (strcmp(opr_name_or_oid, "0") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (opr_name_or_oid[0] >= '0' &&
|
|
|
|
opr_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
|
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(opr_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
elog(ERROR, "regoperator values must be OIDs in bootstrap mode");
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Else it's a name and arguments. Parse the name and arguments, look up
|
|
|
|
* potential matches in the current namespace search list, and scan to see
|
2014-05-06 18:12:18 +02:00
|
|
|
* which one exactly matches the given argument types. (There will not be
|
2005-10-15 04:49:52 +02:00
|
|
|
* more than one match.)
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2007-06-26 18:48:09 +02:00
|
|
|
parseNameAndArgTypes(opr_name_or_oid, true, &names, &nargs, argtypes);
|
2002-04-25 04:56:56 +02:00
|
|
|
if (nargs == 1)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
|
|
|
errmsg("missing argument"),
|
|
|
|
errhint("Use NONE to denote the missing argument of a unary operator.")));
|
2002-04-25 04:56:56 +02:00
|
|
|
if (nargs != 2)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
|
|
|
|
errmsg("too many arguments"),
|
|
|
|
errhint("Provide two argument types for operator.")));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2006-05-02 01:22:43 +02:00
|
|
|
result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2006-05-02 01:22:43 +02:00
|
|
|
if (!OidIsValid(result))
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
2003-09-25 08:58:07 +02:00
|
|
|
errmsg("operator does not exist: %s", opr_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
2014-04-16 18:21:43 +02:00
|
|
|
/*
|
|
|
|
* to_regoperator - converts "oprname(args)" to operator OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regoperator(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *opr_name_or_oid = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2014-04-16 18:21:43 +02:00
|
|
|
Oid result;
|
|
|
|
List *names;
|
|
|
|
int nargs;
|
|
|
|
Oid argtypes[FUNC_MAX_ARGS];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the name and arguments, look up potential matches in the current
|
|
|
|
* namespace search list, and scan to see which one exactly matches the
|
2014-05-06 18:12:18 +02:00
|
|
|
* given argument types. (There will not be more than one match.)
|
2014-04-16 18:21:43 +02:00
|
|
|
*/
|
|
|
|
parseNameAndArgTypes(opr_name_or_oid, true, &names, &nargs, argtypes);
|
|
|
|
if (nargs == 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_PARAMETER),
|
|
|
|
errmsg("missing argument"),
|
|
|
|
errhint("Use NONE to denote the missing argument of a unary operator.")));
|
|
|
|
if (nargs != 2)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
|
|
|
|
errmsg("too many arguments"),
|
|
|
|
errhint("Provide two argument types for operator.")));
|
|
|
|
|
|
|
|
result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
|
|
|
|
|
|
|
|
if (!OidIsValid(result))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
2002-07-30 00:14:11 +02:00
|
|
|
* format_operator - converts operator OID to "opr_name(args)"
|
|
|
|
*
|
|
|
|
* This exports the useful functionality of regoperatorout for use
|
|
|
|
* in other backend modules. The result is a palloc'd string.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2013-03-20 22:19:19 +01:00
|
|
|
static char *
|
|
|
|
format_operator_internal(Oid operator_oid, bool force_qualify)
|
2002-04-25 04:56:56 +02:00
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
HeapTuple opertup;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operator_oid));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(opertup))
|
|
|
|
{
|
|
|
|
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
|
|
|
|
char *oprname = NameStr(operform->oprname);
|
|
|
|
char *nspname;
|
|
|
|
StringInfoData buf;
|
|
|
|
|
|
|
|
/* XXX no support here for bootstrap mode */
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
Assert(!IsBootstrapProcessingMode());
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2002-05-02 01:06:41 +02:00
|
|
|
initStringInfo(&buf);
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Would this oper be found (given the right args) by regoperatorin?
|
2016-01-04 07:03:53 +01:00
|
|
|
* If not, or if caller explicitly requests it, we need to qualify it.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2013-03-20 22:19:19 +01:00
|
|
|
if (force_qualify || !OperatorIsVisible(operator_oid))
|
2002-04-25 04:56:56 +02:00
|
|
|
{
|
|
|
|
nspname = get_namespace_name(operform->oprnamespace);
|
|
|
|
appendStringInfo(&buf, "%s.",
|
|
|
|
quote_identifier(nspname));
|
|
|
|
}
|
|
|
|
|
|
|
|
appendStringInfo(&buf, "%s(", oprname);
|
|
|
|
|
|
|
|
if (operform->oprleft)
|
|
|
|
appendStringInfo(&buf, "%s,",
|
2013-03-20 22:19:19 +01:00
|
|
|
force_qualify ?
|
|
|
|
format_type_be_qualified(operform->oprleft) :
|
2002-04-25 04:56:56 +02:00
|
|
|
format_type_be(operform->oprleft));
|
|
|
|
else
|
2013-10-31 15:55:59 +01:00
|
|
|
appendStringInfoString(&buf, "NONE,");
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (operform->oprright)
|
|
|
|
appendStringInfo(&buf, "%s)",
|
2013-03-20 22:19:19 +01:00
|
|
|
force_qualify ?
|
|
|
|
format_type_be_qualified(operform->oprright) :
|
2002-04-25 04:56:56 +02:00
|
|
|
format_type_be(operform->oprright));
|
|
|
|
else
|
2013-10-31 15:55:59 +01:00
|
|
|
appendStringInfoString(&buf, "NONE)");
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
result = buf.data;
|
|
|
|
|
|
|
|
ReleaseSysCache(opertup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If OID doesn't match any pg_operator entry, return it numerically
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2002-04-25 04:56:56 +02:00
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
2002-07-30 00:14:11 +02:00
|
|
|
snprintf(result, NAMEDATALEN, "%u", operator_oid);
|
1998-08-19 04:04:17 +02:00
|
|
|
}
|
|
|
|
|
2002-07-30 00:14:11 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-03-20 22:19:19 +01:00
|
|
|
char *
|
|
|
|
format_operator(Oid operator_oid)
|
|
|
|
{
|
|
|
|
return format_operator_internal(operator_oid, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
format_operator_qualified(Oid operator_oid)
|
|
|
|
{
|
|
|
|
return format_operator_internal(operator_oid, true);
|
|
|
|
}
|
|
|
|
|
2014-12-30 19:41:50 +01:00
|
|
|
void
|
|
|
|
format_operator_parts(Oid operator_oid, List **objnames, List **objargs)
|
|
|
|
{
|
|
|
|
HeapTuple opertup;
|
|
|
|
Form_pg_operator oprForm;
|
|
|
|
|
|
|
|
opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operator_oid));
|
|
|
|
if (!HeapTupleIsValid(opertup))
|
|
|
|
elog(ERROR, "cache lookup failed for operator with OID %u",
|
|
|
|
operator_oid);
|
|
|
|
|
|
|
|
oprForm = (Form_pg_operator) GETSTRUCT(opertup);
|
2015-04-06 16:40:55 +02:00
|
|
|
*objnames = list_make2(get_namespace_name_or_temp(oprForm->oprnamespace),
|
2014-12-30 19:41:50 +01:00
|
|
|
pstrdup(NameStr(oprForm->oprname)));
|
|
|
|
*objargs = NIL;
|
|
|
|
if (oprForm->oprleft)
|
|
|
|
*objargs = lappend(*objargs,
|
|
|
|
format_type_be_qualified(oprForm->oprleft));
|
|
|
|
if (oprForm->oprright)
|
|
|
|
*objargs = lappend(*objargs,
|
|
|
|
format_type_be_qualified(oprForm->oprright));
|
|
|
|
|
|
|
|
ReleaseSysCache(opertup);
|
|
|
|
}
|
|
|
|
|
2002-07-30 00:14:11 +02:00
|
|
|
/*
|
|
|
|
* regoperatorout - converts operator OID to "opr_name(args)"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regoperatorout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid oprid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
if (oprid == InvalidOid)
|
|
|
|
result = pstrdup("0");
|
|
|
|
else
|
|
|
|
result = format_operator(oprid);
|
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* regoperatorrecv - converts external binary format to regoperator
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regoperatorrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regoperatorsend - converts regoperator to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regoperatorsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
1997-11-15 17:32:25 +01:00
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
|
|
|
* regclassin - converts "classname" to class OID
|
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
2002-04-25 04:56:56 +02:00
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_class entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regclassin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *class_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
Oid result = InvalidOid;
|
|
|
|
List *names;
|
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(class_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (class_name_or_oid[0] >= '0' &&
|
|
|
|
class_name_or_oid[0] <= '9' &&
|
2005-10-15 04:49:52 +02:00
|
|
|
strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
|
2002-04-25 04:56:56 +02:00
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(class_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Else it's a name, possibly schema-qualified */
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
2002-04-25 04:56:56 +02:00
|
|
|
if (IsBootstrapProcessingMode())
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
elog(ERROR, "regclass values must be OIDs in bootstrap mode");
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Normal case: parse the name into components and see if it matches any
|
|
|
|
* pg_class entries in the current search path.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2007-06-26 18:48:09 +02:00
|
|
|
names = stringToQualifiedNameList(class_name_or_oid);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
/* We might not even have permissions on this relation; don't lock it. */
|
Improve table locking behavior in the face of current DDL.
In the previous coding, callers were faced with an awkward choice:
look up the name, do permissions checks, and then lock the table; or
look up the name, lock the table, and then do permissions checks.
The first choice was wrong because the results of the name lookup
and permissions checks might be out-of-date by the time the table
lock was acquired, while the second allowed a user with no privileges
to interfere with access to a table by users who do have privileges
(e.g. if a malicious backend queues up for an AccessExclusiveLock on
a table on which AccessShareLock is already held, further attempts
to access the table will be blocked until the AccessExclusiveLock
is obtained and the malicious backend's transaction rolls back).
To fix, allow callers of RangeVarGetRelid() to pass a callback which
gets executed after performing the name lookup but before acquiring
the relation lock. If the name lookup is retried (because
invalidation messages are received), the callback will be re-executed
as well, so we get the best of both worlds. RangeVarGetRelid() is
renamed to RangeVarGetRelidExtended(); callers not wishing to supply
a callback can continue to invoke it as RangeVarGetRelid(), which is
now a macro. Since the only one caller that uses nowait = true now
passes a callback anyway, the RangeVarGetRelid() macro defaults nowait
as well. The callback can also be used for supplemental locking - for
example, REINDEX INDEX needs to acquire the table lock before the index
lock to reduce deadlock possibilities.
There's a lot more work to be done here to fix all the cases where this
can be a problem, but this commit provides the general infrastructure
and fixes the following specific cases: REINDEX INDEX, REINDEX TABLE,
LOCK TABLE, and and DROP TABLE/INDEX/SEQUENCE/VIEW/FOREIGN TABLE.
Per discussion with Noah Misch and Alvaro Herrera.
2011-11-30 16:12:27 +01:00
|
|
|
result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, false);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
2014-04-08 16:27:56 +02:00
|
|
|
/*
|
|
|
|
* to_regclass - converts "classname" to class OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regclass(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *class_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2014-04-08 16:27:56 +02:00
|
|
|
Oid result;
|
|
|
|
List *names;
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Parse the name into components and see if it matches any pg_class
|
|
|
|
* entries in the current search path.
|
2014-04-08 16:27:56 +02:00
|
|
|
*/
|
|
|
|
names = stringToQualifiedNameList(class_name);
|
|
|
|
|
|
|
|
/* We might not even have permissions on this relation; don't lock it. */
|
|
|
|
result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
|
|
|
|
|
|
|
|
if (OidIsValid(result))
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
else
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
|
|
|
* regclassout - converts class OID to "class_name"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regclassout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid classid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
HeapTuple classtup;
|
|
|
|
|
|
|
|
if (classid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classid));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(classtup))
|
|
|
|
{
|
|
|
|
Form_pg_class classform = (Form_pg_class) GETSTRUCT(classtup);
|
|
|
|
char *classname = NameStr(classform->relname);
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* In bootstrap mode, skip the fancy namespace stuff and just return
|
2014-05-06 18:12:18 +02:00
|
|
|
* the class name. (This path is only needed for debugging output
|
2005-10-15 04:49:52 +02:00
|
|
|
* anyway.)
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
result = pstrdup(classname);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *nspname;
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Would this class be found by regclassin? If not, qualify it.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2002-05-02 01:06:41 +02:00
|
|
|
if (RelationIsVisible(classid))
|
2002-04-25 04:56:56 +02:00
|
|
|
nspname = NULL;
|
|
|
|
else
|
|
|
|
nspname = get_namespace_name(classform->relnamespace);
|
|
|
|
|
|
|
|
result = quote_qualified_identifier(nspname, classname);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(classtup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If OID doesn't match any pg_class entry, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", classid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* regclassrecv - converts external binary format to regclass
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regclassrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regclasssend - converts regclass to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regclasssend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
|
2020-03-18 21:20:01 +01:00
|
|
|
/*
|
|
|
|
* regcollationin - converts "collationname" to collation OID
|
|
|
|
*
|
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_collation entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regcollationin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *collation_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
Oid result = InvalidOid;
|
|
|
|
List *names;
|
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(collation_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (collation_name_or_oid[0] >= '0' &&
|
|
|
|
collation_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(collation_name_or_oid, "0123456789") == strlen(collation_name_or_oid))
|
|
|
|
{
|
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
|
|
|
CStringGetDatum(collation_name_or_oid)));
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Else it's a name, possibly schema-qualified */
|
|
|
|
|
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
elog(ERROR, "regcollation values must be OIDs in bootstrap mode");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Normal case: parse the name into components and see if it matches any
|
|
|
|
* pg_collation entries in the current search path.
|
|
|
|
*/
|
|
|
|
names = stringToQualifiedNameList(collation_name_or_oid);
|
|
|
|
|
|
|
|
result = get_collation_oid(names, false);
|
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to_regcollation - converts "collationname" to collation OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regcollation(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *collation_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
|
|
|
Oid result;
|
|
|
|
List *names;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the name into components and see if it matches any pg_collation
|
|
|
|
* entries in the current search path.
|
|
|
|
*/
|
|
|
|
names = stringToQualifiedNameList(collation_name);
|
|
|
|
|
|
|
|
/* We might not even have permissions on this relation; don't lock it. */
|
|
|
|
result = get_collation_oid(names, true);
|
|
|
|
|
|
|
|
if (OidIsValid(result))
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
else
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regcollationout - converts collation OID to "collation_name"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regcollationout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid collationid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
HeapTuple collationtup;
|
|
|
|
|
|
|
|
if (collationid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
collationtup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collationid));
|
|
|
|
|
|
|
|
if (HeapTupleIsValid(collationtup))
|
|
|
|
{
|
|
|
|
Form_pg_collation collationform = (Form_pg_collation) GETSTRUCT(collationtup);
|
|
|
|
char *collationname = NameStr(collationform->collname);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In bootstrap mode, skip the fancy namespace stuff and just return
|
|
|
|
* the collation name. (This path is only needed for debugging output
|
|
|
|
* anyway.)
|
|
|
|
*/
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
result = pstrdup(collationname);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *nspname;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Would this collation be found by regcollationin? If not, qualify it.
|
|
|
|
*/
|
|
|
|
if (CollationIsVisible(collationid))
|
|
|
|
nspname = NULL;
|
|
|
|
else
|
|
|
|
nspname = get_namespace_name(collationform->collnamespace);
|
|
|
|
|
|
|
|
result = quote_qualified_identifier(nspname, collationname);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(collationtup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If OID doesn't match any pg_collation entry, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", collationid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regcollationrecv - converts external binary format to regcollation
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regcollationrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regcollationsend - converts regcollation to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regcollationsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
|
|
|
* regtypein - converts "typename" to type OID
|
|
|
|
*
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
* The type name can be specified using the full type syntax recognized by
|
|
|
|
* the parser; for example, DOUBLE PRECISION and INTEGER[] will work and be
|
|
|
|
* translated to the correct type names. (We ignore any typmod info
|
|
|
|
* generated by the parser, however.)
|
|
|
|
*
|
|
|
|
* We also accept a numeric OID, for symmetry with the output routine,
|
|
|
|
* and for possible use in bootstrap mode.
|
2002-04-25 04:56:56 +02:00
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_type entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regtypein(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *typ_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
Oid result = InvalidOid;
|
|
|
|
int32 typmod;
|
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(typ_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (typ_name_or_oid[0] >= '0' &&
|
|
|
|
typ_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid))
|
|
|
|
{
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(typ_name_or_oid)));
|
2002-04-25 04:56:56 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Else it's a type name, possibly schema-qualified or decorated */
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
2002-04-25 04:56:56 +02:00
|
|
|
if (IsBootstrapProcessingMode())
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
elog(ERROR, "regtype values must be OIDs in bootstrap mode");
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Normal case: invoke the full parser to deal with special cases such as
|
|
|
|
* array syntax.
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
2014-04-08 16:27:56 +02:00
|
|
|
parseTypeString(typ_name_or_oid, &result, &typmod, false);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
2014-04-08 16:27:56 +02:00
|
|
|
/*
|
|
|
|
* to_regtype - converts "typename" to type OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regtype(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *typ_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2014-04-08 16:27:56 +02:00
|
|
|
Oid result;
|
|
|
|
int32 typmod;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Invoke the full parser to deal with special cases such as array syntax.
|
|
|
|
*/
|
|
|
|
parseTypeString(typ_name, &result, &typmod, true);
|
|
|
|
|
|
|
|
if (OidIsValid(result))
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
else
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
|
|
|
* regtypeout - converts type OID to "typ_name"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regtypeout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid typid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
HeapTuple typetup;
|
|
|
|
|
|
|
|
if (typid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
typetup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(typetup))
|
|
|
|
{
|
|
|
|
Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* In bootstrap mode, skip the fancy namespace stuff and just return
|
|
|
|
* the type name. (This path is only needed for debugging output
|
|
|
|
* anyway.)
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
{
|
2002-05-02 01:06:41 +02:00
|
|
|
char *typname = NameStr(typeform->typname);
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
result = pstrdup(typname);
|
|
|
|
}
|
|
|
|
else
|
2002-05-02 01:06:41 +02:00
|
|
|
result = format_type_be(typid);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
ReleaseSysCache(typetup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If OID doesn't match any pg_type entry, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", typid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* regtyperecv - converts external binary format to regtype
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regtyperecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regtypesend - converts regtype to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regtypesend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
/*
|
|
|
|
* regconfigin - converts "tsconfigname" to tsconfig OID
|
|
|
|
*
|
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_ts_config entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regconfigin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *cfg_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
Oid result;
|
|
|
|
List *names;
|
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(cfg_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (cfg_name_or_oid[0] >= '0' &&
|
|
|
|
cfg_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(cfg_name_or_oid, "0123456789") == strlen(cfg_name_or_oid))
|
|
|
|
{
|
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(cfg_name_or_oid)));
|
2007-08-21 03:11:32 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
elog(ERROR, "regconfig values must be OIDs in bootstrap mode");
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
/*
|
|
|
|
* Normal case: parse the name into components and see if it matches any
|
|
|
|
* pg_ts_config entries in the current search path.
|
|
|
|
*/
|
|
|
|
names = stringToQualifiedNameList(cfg_name_or_oid);
|
|
|
|
|
2010-08-05 17:25:36 +02:00
|
|
|
result = get_ts_config_oid(names, false);
|
2007-08-21 03:11:32 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regconfigout - converts tsconfig OID to "tsconfigname"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regconfigout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid cfgid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
HeapTuple cfgtup;
|
|
|
|
|
|
|
|
if (cfgid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
cfgtup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
|
2007-08-21 03:11:32 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(cfgtup))
|
|
|
|
{
|
|
|
|
Form_pg_ts_config cfgform = (Form_pg_ts_config) GETSTRUCT(cfgtup);
|
|
|
|
char *cfgname = NameStr(cfgform->cfgname);
|
|
|
|
char *nspname;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Would this config be found by regconfigin? If not, qualify it.
|
|
|
|
*/
|
|
|
|
if (TSConfigIsVisible(cfgid))
|
|
|
|
nspname = NULL;
|
|
|
|
else
|
|
|
|
nspname = get_namespace_name(cfgform->cfgnamespace);
|
|
|
|
|
|
|
|
result = quote_qualified_identifier(nspname, cfgname);
|
|
|
|
|
|
|
|
ReleaseSysCache(cfgtup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If OID doesn't match any pg_ts_config row, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", cfgid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regconfigrecv - converts external binary format to regconfig
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regconfigrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regconfigsend - converts regconfig to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regconfigsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regdictionaryin - converts "tsdictionaryname" to tsdictionary OID
|
|
|
|
*
|
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_ts_dict entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regdictionaryin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *dict_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
Oid result;
|
|
|
|
List *names;
|
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(dict_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (dict_name_or_oid[0] >= '0' &&
|
|
|
|
dict_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(dict_name_or_oid, "0123456789") == strlen(dict_name_or_oid))
|
|
|
|
{
|
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(dict_name_or_oid)));
|
2007-08-21 03:11:32 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
elog(ERROR, "regdictionary values must be OIDs in bootstrap mode");
|
|
|
|
|
2007-08-21 03:11:32 +02:00
|
|
|
/*
|
|
|
|
* Normal case: parse the name into components and see if it matches any
|
|
|
|
* pg_ts_dict entries in the current search path.
|
|
|
|
*/
|
|
|
|
names = stringToQualifiedNameList(dict_name_or_oid);
|
|
|
|
|
2010-08-05 17:25:36 +02:00
|
|
|
result = get_ts_dict_oid(names, false);
|
2007-08-21 03:11:32 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regdictionaryout - converts tsdictionary OID to "tsdictionaryname"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regdictionaryout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid dictid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
HeapTuple dicttup;
|
|
|
|
|
|
|
|
if (dictid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
dicttup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictid));
|
2007-08-21 03:11:32 +02:00
|
|
|
|
|
|
|
if (HeapTupleIsValid(dicttup))
|
|
|
|
{
|
|
|
|
Form_pg_ts_dict dictform = (Form_pg_ts_dict) GETSTRUCT(dicttup);
|
|
|
|
char *dictname = NameStr(dictform->dictname);
|
|
|
|
char *nspname;
|
|
|
|
|
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* Would this dictionary be found by regdictionaryin? If not, qualify
|
|
|
|
* it.
|
2007-08-21 03:11:32 +02:00
|
|
|
*/
|
|
|
|
if (TSDictionaryIsVisible(dictid))
|
|
|
|
nspname = NULL;
|
|
|
|
else
|
|
|
|
nspname = get_namespace_name(dictform->dictnamespace);
|
|
|
|
|
|
|
|
result = quote_qualified_identifier(nspname, dictname);
|
|
|
|
|
|
|
|
ReleaseSysCache(dicttup);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If OID doesn't match any pg_ts_dict row, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", dictid);
|
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regdictionaryrecv - converts external binary format to regdictionary
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regdictionaryrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regdictionarysend - converts regdictionary to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regdictionarysend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2015-05-09 19:06:49 +02:00
|
|
|
/*
|
|
|
|
* regrolein - converts "rolename" to role OID
|
|
|
|
*
|
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_authid entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regrolein(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *role_name_or_oid = PG_GETARG_CSTRING(0);
|
|
|
|
Oid result;
|
2016-01-04 07:03:53 +01:00
|
|
|
List *names;
|
2015-05-09 19:06:49 +02:00
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(role_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (role_name_or_oid[0] >= '0' &&
|
|
|
|
role_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(role_name_or_oid, "0123456789") == strlen(role_name_or_oid))
|
|
|
|
{
|
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(role_name_or_oid)));
|
2015-05-09 19:06:49 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
elog(ERROR, "regrole values must be OIDs in bootstrap mode");
|
|
|
|
|
2015-05-09 19:06:49 +02:00
|
|
|
/* Normal case: see if the name matches any pg_authid entry. */
|
2016-01-04 07:03:53 +01:00
|
|
|
names = stringToQualifiedNameList(role_name_or_oid);
|
|
|
|
|
|
|
|
if (list_length(names) != 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_NAME),
|
|
|
|
errmsg("invalid name syntax")));
|
|
|
|
|
|
|
|
result = get_role_oid(strVal(linitial(names)), false);
|
2015-05-09 19:06:49 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to_regrole - converts "rolename" to role OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regrole(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *role_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2015-05-09 19:06:49 +02:00
|
|
|
Oid result;
|
2016-01-04 07:03:53 +01:00
|
|
|
List *names;
|
2015-05-09 19:06:49 +02:00
|
|
|
|
2016-01-04 07:03:53 +01:00
|
|
|
names = stringToQualifiedNameList(role_name);
|
|
|
|
|
|
|
|
if (list_length(names) != 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_NAME),
|
|
|
|
errmsg("invalid name syntax")));
|
|
|
|
|
|
|
|
result = get_role_oid(strVal(linitial(names)), true);
|
2015-05-09 19:06:49 +02:00
|
|
|
|
|
|
|
if (OidIsValid(result))
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
else
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regroleout - converts role OID to "role_name"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regroleout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid roleoid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
if (roleoid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = GetUserNameFromId(roleoid, true);
|
2016-01-04 07:03:53 +01:00
|
|
|
|
2016-01-04 07:53:24 +01:00
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
/* pstrdup is not really necessary, but it avoids a compiler warning */
|
|
|
|
result = pstrdup(quote_identifier(result));
|
|
|
|
}
|
|
|
|
else
|
2015-05-09 19:06:49 +02:00
|
|
|
{
|
|
|
|
/* If OID doesn't match any role, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", roleoid);
|
|
|
|
}
|
2016-01-04 07:53:24 +01:00
|
|
|
|
2015-05-09 19:06:49 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-05-24 03:35:49 +02:00
|
|
|
* regrolerecv - converts external binary format to regrole
|
2015-05-09 19:06:49 +02:00
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regrolerecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-05-24 03:35:49 +02:00
|
|
|
* regrolesend - converts regrole to binary format
|
2015-05-09 19:06:49 +02:00
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regrolesend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2015-05-09 19:36:52 +02:00
|
|
|
/*
|
|
|
|
* regnamespacein - converts "nspname" to namespace OID
|
|
|
|
*
|
|
|
|
* We also accept a numeric OID, for symmetry with the output routine.
|
|
|
|
*
|
|
|
|
* '-' signifies unknown (OID 0). In all other cases, the input must
|
|
|
|
* match an existing pg_namespace entry.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regnamespacein(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *nsp_name_or_oid = PG_GETARG_CSTRING(0);
|
2016-01-04 07:03:53 +01:00
|
|
|
Oid result;
|
|
|
|
List *names;
|
2015-05-09 19:36:52 +02:00
|
|
|
|
|
|
|
/* '-' ? */
|
|
|
|
if (strcmp(nsp_name_or_oid, "-") == 0)
|
|
|
|
PG_RETURN_OID(InvalidOid);
|
|
|
|
|
|
|
|
/* Numeric OID? */
|
|
|
|
if (nsp_name_or_oid[0] >= '0' &&
|
|
|
|
nsp_name_or_oid[0] <= '9' &&
|
|
|
|
strspn(nsp_name_or_oid, "0123456789") == strlen(nsp_name_or_oid))
|
|
|
|
{
|
|
|
|
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
CStringGetDatum(nsp_name_or_oid)));
|
2015-05-09 19:36:52 +02:00
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
Move bootstrap-time lookup of regproc OIDs into genbki.pl.
Formerly, the bootstrap backend looked up the OIDs corresponding to
names in regproc catalog entries using brute-force searches of pg_proc.
It was somewhat remarkable that that worked at all, since it was used
while populating other pretty-fundamental catalogs like pg_operator.
And it was also quite slow, and getting slower as pg_proc gets bigger.
This patch moves the lookup work into genbki.pl, so that the values in
postgres.bki for regproc columns are always numeric OIDs, an option
that regprocin() already supported. Perl isn't the world's speediest
language, so this about doubles the time needed to run genbki.pl (from
0.3 to 0.6 sec on my machine). But we only do that at most once per
build. The time needed to run initdb drops significantly --- on my
machine, initdb --no-sync goes from 1.8 to 1.3 seconds. So this is
a small net win even for just one initdb per build, and it becomes
quite a nice win for test sequences requiring many initdb runs.
Strip out the now-dead code for brute-force catalog searching in
regprocin. We'd also cargo-culted similar logic into regoperin
and some (not all) of the other reg*in functions. That is all
dead code too since we currently have no need to load such values
during bootstrap. I removed it all, reasoning that if we ever
need such functionality it'd be much better to do it in a similar
way to this patch.
There might be some simplifications possible in the backend now that
regprocin doesn't require doing catalog reads so early in bootstrap.
I've not looked into that, though.
Andreas Karlsson, with some small adjustments by me
Discussion: https://postgr.es/m/30896.1492006367@sss.pgh.pa.us
2017-04-13 18:07:47 +02:00
|
|
|
/* The rest of this wouldn't work in bootstrap mode */
|
|
|
|
if (IsBootstrapProcessingMode())
|
|
|
|
elog(ERROR, "regnamespace values must be OIDs in bootstrap mode");
|
|
|
|
|
2015-05-09 19:36:52 +02:00
|
|
|
/* Normal case: see if the name matches any pg_namespace entry. */
|
2016-01-04 07:03:53 +01:00
|
|
|
names = stringToQualifiedNameList(nsp_name_or_oid);
|
|
|
|
|
|
|
|
if (list_length(names) != 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_NAME),
|
|
|
|
errmsg("invalid name syntax")));
|
|
|
|
|
|
|
|
result = get_namespace_oid(strVal(linitial(names)), false);
|
2015-05-09 19:36:52 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to_regnamespace - converts "nspname" to namespace OID
|
|
|
|
*
|
|
|
|
* If the name is not found, we return NULL.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
to_regnamespace(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2016-01-05 19:02:43 +01:00
|
|
|
char *nsp_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
2015-05-09 19:36:52 +02:00
|
|
|
Oid result;
|
2016-01-04 07:03:53 +01:00
|
|
|
List *names;
|
|
|
|
|
|
|
|
names = stringToQualifiedNameList(nsp_name);
|
2015-05-09 19:36:52 +02:00
|
|
|
|
2016-01-04 07:03:53 +01:00
|
|
|
if (list_length(names) != 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_NAME),
|
|
|
|
errmsg("invalid name syntax")));
|
|
|
|
|
|
|
|
result = get_namespace_oid(strVal(linitial(names)), true);
|
2015-05-09 19:36:52 +02:00
|
|
|
|
|
|
|
if (OidIsValid(result))
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
else
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regnamespaceout - converts namespace OID to "nsp_name"
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regnamespaceout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
Oid nspid = PG_GETARG_OID(0);
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
if (nspid == InvalidOid)
|
|
|
|
{
|
|
|
|
result = pstrdup("-");
|
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
2015-05-09 19:06:49 +02:00
|
|
|
|
2015-05-09 19:36:52 +02:00
|
|
|
result = get_namespace_name(nspid);
|
2016-01-04 07:03:53 +01:00
|
|
|
|
2016-01-04 07:53:24 +01:00
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
/* pstrdup is not really necessary, but it avoids a compiler warning */
|
|
|
|
result = pstrdup(quote_identifier(result));
|
|
|
|
}
|
|
|
|
else
|
2015-05-09 19:36:52 +02:00
|
|
|
{
|
|
|
|
/* If OID doesn't match any namespace, return it numerically */
|
|
|
|
result = (char *) palloc(NAMEDATALEN);
|
|
|
|
snprintf(result, NAMEDATALEN, "%u", nspid);
|
|
|
|
}
|
2016-01-04 07:53:24 +01:00
|
|
|
|
2015-05-09 19:36:52 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regnamespacerecv - converts external binary format to regnamespace
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regnamespacerecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidrecv, so share code */
|
|
|
|
return oidrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* regnamespacesend - converts regnamespace to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
regnamespacesend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as oidsend, so share code */
|
|
|
|
return oidsend(fcinfo);
|
|
|
|
}
|
2007-08-21 03:11:32 +02:00
|
|
|
|
2005-10-03 01:50:16 +02:00
|
|
|
/*
|
|
|
|
* text_regclass: convert text to regclass
|
2007-06-05 23:31:09 +02:00
|
|
|
*
|
|
|
|
* This could be replaced by CoerceViaIO, except that we need to treat
|
|
|
|
* text-to-regclass as an implicit cast to support legacy forms of nextval()
|
|
|
|
* and related functions.
|
2005-10-03 01:50:16 +02:00
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
text_regclass(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2017-03-13 00:35:34 +01:00
|
|
|
text *relname = PG_GETARG_TEXT_PP(0);
|
2005-10-03 01:50:16 +02:00
|
|
|
Oid result;
|
|
|
|
RangeVar *rv;
|
|
|
|
|
|
|
|
rv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
|
2011-07-09 04:19:30 +02:00
|
|
|
|
|
|
|
/* We might not even have permissions on this relation; don't lock it. */
|
Improve table locking behavior in the face of current DDL.
In the previous coding, callers were faced with an awkward choice:
look up the name, do permissions checks, and then lock the table; or
look up the name, lock the table, and then do permissions checks.
The first choice was wrong because the results of the name lookup
and permissions checks might be out-of-date by the time the table
lock was acquired, while the second allowed a user with no privileges
to interfere with access to a table by users who do have privileges
(e.g. if a malicious backend queues up for an AccessExclusiveLock on
a table on which AccessShareLock is already held, further attempts
to access the table will be blocked until the AccessExclusiveLock
is obtained and the malicious backend's transaction rolls back).
To fix, allow callers of RangeVarGetRelid() to pass a callback which
gets executed after performing the name lookup but before acquiring
the relation lock. If the name lookup is retried (because
invalidation messages are received), the callback will be re-executed
as well, so we get the best of both worlds. RangeVarGetRelid() is
renamed to RangeVarGetRelidExtended(); callers not wishing to supply
a callback can continue to invoke it as RangeVarGetRelid(), which is
now a macro. Since the only one caller that uses nowait = true now
passes a callback anyway, the RangeVarGetRelid() macro defaults nowait
as well. The callback can also be used for supplemental locking - for
example, REINDEX INDEX needs to acquire the table lock before the index
lock to reduce deadlock possibilities.
There's a lot more work to be done here to fix all the cases where this
can be a problem, but this commit provides the general infrastructure
and fixes the following specific cases: REINDEX INDEX, REINDEX TABLE,
LOCK TABLE, and and DROP TABLE/INDEX/SEQUENCE/VIEW/FOREIGN TABLE.
Per discussion with Noah Misch and Alvaro Herrera.
2011-11-30 16:12:27 +01:00
|
|
|
result = RangeVarGetRelid(rv, NoLock, false);
|
2005-10-03 01:50:16 +02:00
|
|
|
|
|
|
|
PG_RETURN_OID(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
|
|
|
* Given a C string, parse it into a qualified-name list.
|
1997-04-27 21:20:16 +02:00
|
|
|
*/
|
2002-06-20 19:19:08 +02:00
|
|
|
List *
|
2007-06-26 18:48:09 +02:00
|
|
|
stringToQualifiedNameList(const char *string)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-04-25 04:56:56 +02:00
|
|
|
char *rawname;
|
|
|
|
List *result = NIL;
|
|
|
|
List *namelist;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/* We need a modifiable copy of the input string. */
|
|
|
|
rawname = pstrdup(string);
|
|
|
|
|
|
|
|
if (!SplitIdentifierString(rawname, '.', &namelist))
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_NAME),
|
|
|
|
errmsg("invalid name syntax")));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
if (namelist == NIL)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_NAME),
|
|
|
|
errmsg("invalid name syntax")));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
foreach(l, namelist)
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
char *curname = (char *) lfirst(l);
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
result = lappend(result, makeString(pstrdup(curname)));
|
|
|
|
}
|
|
|
|
|
|
|
|
pfree(rawname);
|
2004-05-31 01:40:41 +02:00
|
|
|
list_free(namelist);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
return result;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2002-06-20 19:19:08 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* SUPPORT ROUTINES *
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
/*
|
|
|
|
* Given a C string, parse it into a qualified function or operator name
|
2014-05-06 18:12:18 +02:00
|
|
|
* followed by a parenthesized list of type names. Reduce the
|
2002-04-25 04:56:56 +02:00
|
|
|
* type names to an array of OIDs (returned into *nargs and *argtypes;
|
|
|
|
* the argtypes array should be of size FUNC_MAX_ARGS). The function or
|
|
|
|
* operator name is returned to *names as a List of Strings.
|
|
|
|
*
|
2017-08-16 06:22:32 +02:00
|
|
|
* If allowNone is true, accept "NONE" and return it as InvalidOid (this is
|
2002-08-22 02:01:51 +02:00
|
|
|
* for unary operators).
|
2002-04-25 04:56:56 +02:00
|
|
|
*/
|
|
|
|
static void
|
2007-06-26 18:48:09 +02:00
|
|
|
parseNameAndArgTypes(const char *string, bool allowNone, List **names,
|
|
|
|
int *nargs, Oid *argtypes)
|
2002-04-25 04:56:56 +02:00
|
|
|
{
|
|
|
|
char *rawname;
|
|
|
|
char *ptr;
|
|
|
|
char *ptr2;
|
|
|
|
char *typename;
|
|
|
|
bool in_quote;
|
|
|
|
bool had_comma;
|
|
|
|
int paren_count;
|
|
|
|
Oid typeid;
|
|
|
|
int32 typmod;
|
|
|
|
|
|
|
|
/* We need a modifiable copy of the input string. */
|
|
|
|
rawname = pstrdup(string);
|
|
|
|
|
|
|
|
/* Scan to find the expected left paren; mustn't be quoted */
|
|
|
|
in_quote = false;
|
|
|
|
for (ptr = rawname; *ptr; ptr++)
|
|
|
|
{
|
|
|
|
if (*ptr == '"')
|
|
|
|
in_quote = !in_quote;
|
|
|
|
else if (*ptr == '(' && !in_quote)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*ptr == '\0')
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
|
|
errmsg("expected a left parenthesis")));
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/* Separate the name and parse it into a list */
|
|
|
|
*ptr++ = '\0';
|
2007-06-26 18:48:09 +02:00
|
|
|
*names = stringToQualifiedNameList(rawname);
|
2002-04-25 04:56:56 +02:00
|
|
|
|
|
|
|
/* Check for the trailing right parenthesis and remove it */
|
|
|
|
ptr2 = ptr + strlen(ptr);
|
|
|
|
while (--ptr2 > ptr)
|
|
|
|
{
|
2017-05-24 21:28:34 +02:00
|
|
|
if (!scanner_isspace(*ptr2))
|
2002-04-25 04:56:56 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*ptr2 != ')')
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
|
|
errmsg("expected a right parenthesis")));
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
*ptr2 = '\0';
|
|
|
|
|
|
|
|
/* Separate the remaining string into comma-separated type names */
|
|
|
|
*nargs = 0;
|
|
|
|
had_comma = false;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* allow leading whitespace */
|
2017-05-24 21:28:34 +02:00
|
|
|
while (scanner_isspace(*ptr))
|
2002-04-25 04:56:56 +02:00
|
|
|
ptr++;
|
|
|
|
if (*ptr == '\0')
|
|
|
|
{
|
|
|
|
/* End of string. Okay unless we had a comma before. */
|
|
|
|
if (had_comma)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
|
|
errmsg("expected a type name")));
|
2002-04-25 04:56:56 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
typename = ptr;
|
|
|
|
/* Find end of type name --- end of string or comma */
|
|
|
|
/* ... but not a quoted or parenthesized comma */
|
|
|
|
in_quote = false;
|
|
|
|
paren_count = 0;
|
|
|
|
for (; *ptr; ptr++)
|
|
|
|
{
|
|
|
|
if (*ptr == '"')
|
|
|
|
in_quote = !in_quote;
|
|
|
|
else if (*ptr == ',' && !in_quote && paren_count == 0)
|
|
|
|
break;
|
|
|
|
else if (!in_quote)
|
|
|
|
{
|
|
|
|
switch (*ptr)
|
|
|
|
{
|
|
|
|
case '(':
|
|
|
|
case '[':
|
|
|
|
paren_count++;
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
case ']':
|
|
|
|
paren_count--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (in_quote || paren_count != 0)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
|
|
errmsg("improper type name")));
|
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
ptr2 = ptr;
|
|
|
|
if (*ptr == ',')
|
|
|
|
{
|
|
|
|
had_comma = true;
|
|
|
|
*ptr++ = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
had_comma = false;
|
|
|
|
Assert(*ptr == '\0');
|
|
|
|
}
|
|
|
|
/* Lop off trailing whitespace */
|
|
|
|
while (--ptr2 >= typename)
|
|
|
|
{
|
2017-05-24 21:28:34 +02:00
|
|
|
if (!scanner_isspace(*ptr2))
|
2002-04-25 04:56:56 +02:00
|
|
|
break;
|
|
|
|
*ptr2 = '\0';
|
|
|
|
}
|
|
|
|
|
2004-05-07 02:24:59 +02:00
|
|
|
if (allowNone && pg_strcasecmp(typename, "none") == 0)
|
2002-04-25 04:56:56 +02:00
|
|
|
{
|
2002-08-22 02:01:51 +02:00
|
|
|
/* Special case for NONE */
|
2002-04-25 04:56:56 +02:00
|
|
|
typeid = InvalidOid;
|
|
|
|
typmod = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Use full parser to resolve the type name */
|
2014-04-08 16:27:56 +02:00
|
|
|
parseTypeString(typename, &typeid, &typmod, false);
|
2002-04-25 04:56:56 +02:00
|
|
|
}
|
|
|
|
if (*nargs >= FUNC_MAX_ARGS)
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
|
2003-07-28 02:09:16 +02:00
|
|
|
errmsg("too many arguments")));
|
2003-07-27 06:53:12 +02:00
|
|
|
|
2002-04-25 04:56:56 +02:00
|
|
|
argtypes[*nargs] = typeid;
|
|
|
|
(*nargs)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
pfree(rawname);
|
|
|
|
}
|