2006-03-09 22:29:38 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1998-08-22 14:38:39 +02:00
|
|
|
* pl_comp.c - Compiler part of the PL/pgSQL
|
|
|
|
* procedural language
|
|
|
|
*
|
2019-01-02 18:44:25 +01:00
|
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
2006-03-09 22:29:38 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1998-08-22 14:38:39 +02:00
|
|
|
*
|
|
|
|
*
|
2006-03-09 22:29:38 +01:00
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/pl/plpgsql/src/pl_comp.c
|
1998-08-22 14:38:39 +02:00
|
|
|
*
|
2006-03-09 22:29:38 +01:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2017-03-08 23:21:08 +01:00
|
|
|
#include "postgres.h"
|
2001-10-09 06:15:38 +02:00
|
|
|
|
1998-08-22 14:38:39 +02:00
|
|
|
#include <ctype.h>
|
|
|
|
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
2002-03-26 20:17:02 +01:00
|
|
|
#include "catalog/namespace.h"
|
2002-03-29 20:06:29 +01:00
|
|
|
#include "catalog/pg_proc.h"
|
|
|
|
#include "catalog/pg_type.h"
|
2005-04-05 08:22:17 +02:00
|
|
|
#include "funcapi.h"
|
2002-03-29 20:06:29 +01:00
|
|
|
#include "nodes/makefuncs.h"
|
2001-10-09 06:15:38 +02:00
|
|
|
#include "parser/parse_type.h"
|
2019-10-23 06:08:53 +02:00
|
|
|
#include "plpgsql.h"
|
2001-02-09 04:26:28 +01:00
|
|
|
#include "utils/builtins.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "utils/guc.h"
|
2004-06-04 00:56:43 +02:00
|
|
|
#include "utils/lsyscache.h"
|
2005-05-06 19:24:55 +02:00
|
|
|
#include "utils/memutils.h"
|
2017-01-21 02:29:53 +01:00
|
|
|
#include "utils/regproc.h"
|
2011-02-23 18:18:09 +01:00
|
|
|
#include "utils/rel.h"
|
2001-02-09 04:26:28 +01:00
|
|
|
#include "utils/syscache.h"
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
#include "utils/typcache.h"
|
1998-08-22 14:38:39 +02:00
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Our own local and global variables
|
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-12 01:13:00 +01:00
|
|
|
PLpgSQL_stmt_block *plpgsql_parse_result;
|
|
|
|
|
1998-08-22 14:38:39 +02:00
|
|
|
static int datums_alloc;
|
1998-09-01 06:40:42 +02:00
|
|
|
int plpgsql_nDatums;
|
|
|
|
PLpgSQL_datum **plpgsql_Datums;
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
static int datums_last;
|
1998-08-22 14:38:39 +02:00
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
char *plpgsql_error_funcname;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
bool plpgsql_DumpExecTree = false;
|
|
|
|
bool plpgsql_check_syntax = false;
|
1998-08-22 14:38:39 +02:00
|
|
|
|
|
|
|
PLpgSQL_function *plpgsql_curr_compile;
|
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* A context appropriate for short-term allocs during compilation */
|
2016-03-03 10:45:59 +01:00
|
|
|
MemoryContext plpgsql_compile_tmp_cxt;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
|
2003-07-01 23:47:09 +02:00
|
|
|
/* ----------
|
|
|
|
* Hash table for compiled functions
|
|
|
|
* ----------
|
|
|
|
*/
|
2004-01-07 19:56:30 +01:00
|
|
|
static HTAB *plpgsql_HashTable = NULL;
|
2003-07-01 23:47:09 +02:00
|
|
|
|
|
|
|
typedef struct plpgsql_hashent
|
|
|
|
{
|
|
|
|
PLpgSQL_func_hashkey key;
|
2003-08-04 02:43:34 +02:00
|
|
|
PLpgSQL_function *function;
|
2005-11-22 19:17:34 +01:00
|
|
|
} plpgsql_HashEnt;
|
2003-07-01 23:47:09 +02:00
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
#define FUNCS_PER_USER 128 /* initial table size */
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2004-08-21 00:00:14 +02:00
|
|
|
/* ----------
|
|
|
|
* Lookup table for EXCEPTION condition names
|
|
|
|
* ----------
|
|
|
|
*/
|
2004-08-29 07:07:03 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
2004-08-21 00:00:14 +02:00
|
|
|
const char *label;
|
|
|
|
int sqlerrstate;
|
2005-11-22 19:17:34 +01:00
|
|
|
} ExceptionLabelMap;
|
2004-08-21 00:00:14 +02:00
|
|
|
|
|
|
|
static const ExceptionLabelMap exception_label_map[] = {
|
2012-06-10 21:20:04 +02:00
|
|
|
#include "plerrcodes.h" /* pgrminclude ignore */
|
2004-08-29 07:07:03 +02:00
|
|
|
{NULL, 0}
|
2004-08-21 00:00:14 +02:00
|
|
|
};
|
|
|
|
|
2003-07-01 23:47:09 +02:00
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* static prototypes
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
|
2019-05-22 19:04:48 +02:00
|
|
|
HeapTuple procTup,
|
|
|
|
PLpgSQL_function *function,
|
|
|
|
PLpgSQL_func_hashkey *hashkey,
|
|
|
|
bool forValidator);
|
Modernize plpgsql's handling of parse locations, making it look a lot more
like the core parser's code. In particular, track locations at the character
rather than line level during parsing, allowing many more parse-time error
conditions to be reported with precise error pointers rather than just
"near line N".
Also, exploit the fact that we no longer need to substitute $N for variable
references by making extracted SQL queries and expressions be exact copies
of subranges of the function text, rather than having random whitespace
changes within them. This makes it possible to directly map parse error
positions from the core parser onto positions in the function text, which
lets us report them without the previous kluge of showing the intermediate
internal-query form. (Later it might be good to do that for core
parse-analysis errors too, but this patch is just touching plpgsql's
lexer/parser, not what happens at runtime.)
In passing, make plpgsql's lexer use palloc not malloc.
These changes make plpgsql's parse-time error reports noticeably nicer
(as illustrated by the regression test changes), and will also simplify
the planned removal of plpgsql's separate lexer by reducing the impedance
mismatch between what it does and what the core lexer does.
2009-11-09 01:26:55 +01:00
|
|
|
static void plpgsql_compile_error_callback(void *arg);
|
2016-08-18 18:00:00 +02:00
|
|
|
static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name);
|
2009-09-23 01:43:43 +02:00
|
|
|
static void add_dummy_return(PLpgSQL_function *function);
|
2009-11-06 19:37:55 +01:00
|
|
|
static Node *plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref);
|
|
|
|
static Node *plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var);
|
|
|
|
static Node *plpgsql_param_ref(ParseState *pstate, ParamRef *pref);
|
2010-11-18 23:06:57 +01:00
|
|
|
static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
|
2019-05-22 19:04:48 +02:00
|
|
|
ColumnRef *cref, bool error_if_no_field);
|
2009-11-06 19:37:55 +01:00
|
|
|
static Node *make_datum_param(PLpgSQL_expr *expr, int dno, int location);
|
2005-11-22 19:17:34 +01:00
|
|
|
static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod,
|
|
|
|
Oid collation, TypeName *origtypname);
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
static void plpgsql_start_datums(void);
|
|
|
|
static void plpgsql_finish_datums(PLpgSQL_function *function);
|
2003-08-18 21:16:02 +02:00
|
|
|
static void compute_function_hashkey(FunctionCallInfo fcinfo,
|
2019-05-22 19:04:48 +02:00
|
|
|
Form_pg_proc procStruct,
|
|
|
|
PLpgSQL_func_hashkey *hashkey,
|
|
|
|
bool forValidator);
|
2005-04-05 08:22:17 +02:00
|
|
|
static void plpgsql_resolve_polymorphic_argtypes(int numargs,
|
2019-05-22 19:04:48 +02:00
|
|
|
Oid *argtypes, char *argmodes,
|
|
|
|
Node *call_expr, bool forValidator,
|
|
|
|
const char *proname);
|
2005-11-22 19:17:34 +01:00
|
|
|
static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
|
|
|
|
static void plpgsql_HashTableInsert(PLpgSQL_function *function,
|
2019-05-22 19:04:48 +02:00
|
|
|
PLpgSQL_func_hashkey *func_key);
|
2005-11-22 19:17:34 +01:00
|
|
|
static void plpgsql_HashTableDelete(PLpgSQL_function *function);
|
|
|
|
static void delete_function(PLpgSQL_function *func);
|
2001-04-06 04:06:48 +02:00
|
|
|
|
1998-08-22 14:38:39 +02:00
|
|
|
/* ----------
|
2003-07-01 23:47:09 +02:00
|
|
|
* plpgsql_compile Make an execution tree for a PL/pgSQL function.
|
|
|
|
*
|
2004-03-19 19:58:07 +01:00
|
|
|
* If forValidator is true, we're only compiling for validation purposes,
|
|
|
|
* and so some checks are skipped.
|
|
|
|
*
|
2003-07-01 23:47:09 +02:00
|
|
|
* Note: it's important for this to fall through quickly if the function
|
|
|
|
* has already been compiled.
|
1998-08-22 14:38:39 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
1998-09-01 06:40:42 +02:00
|
|
|
PLpgSQL_function *
|
2004-03-19 19:58:07 +01:00
|
|
|
plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
2003-07-01 23:47:09 +02:00
|
|
|
Oid funcOid = fcinfo->flinfo->fn_oid;
|
1998-09-01 06:40:42 +02:00
|
|
|
HeapTuple procTup;
|
|
|
|
Form_pg_proc procStruct;
|
2003-07-01 23:47:09 +02:00
|
|
|
PLpgSQL_function *function;
|
|
|
|
PLpgSQL_func_hashkey hashkey;
|
2007-01-30 23:05:13 +01:00
|
|
|
bool function_valid = false;
|
2003-07-01 23:47:09 +02:00
|
|
|
bool hashkey_valid = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lookup the pg_proc tuple by Oid; we'll need it in any case
|
|
|
|
*/
|
2010-02-14 19:42:19 +01:00
|
|
|
procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
|
2003-07-01 23:47:09 +02:00
|
|
|
if (!HeapTupleIsValid(procTup))
|
2003-07-26 01:37:31 +02:00
|
|
|
elog(ERROR, "cache lookup failed for function %u", funcOid);
|
2003-07-01 23:47:09 +02:00
|
|
|
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* See if there's already a cache entry for the current FmgrInfo. If not,
|
|
|
|
* try to find one in the hash table.
|
2003-07-01 23:47:09 +02:00
|
|
|
*/
|
|
|
|
function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
|
|
|
|
|
2007-01-30 23:05:13 +01:00
|
|
|
recheck:
|
2003-07-01 23:47:09 +02:00
|
|
|
if (!function)
|
|
|
|
{
|
|
|
|
/* Compute hashkey using function signature and actual arg types */
|
2004-03-19 19:58:07 +01:00
|
|
|
compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
|
2003-07-01 23:47:09 +02:00
|
|
|
hashkey_valid = true;
|
|
|
|
|
|
|
|
/* And do the lookup */
|
|
|
|
function = plpgsql_HashTableLookup(&hashkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (function)
|
|
|
|
{
|
|
|
|
/* We have a compiled function, but is it still valid? */
|
2013-12-22 21:49:09 +01:00
|
|
|
if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
|
2007-02-09 04:35:35 +01:00
|
|
|
ItemPointerEquals(&function->fn_tid, &procTup->t_self))
|
2007-01-30 23:05:13 +01:00
|
|
|
function_valid = true;
|
|
|
|
else
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
2007-01-30 23:05:13 +01:00
|
|
|
/*
|
|
|
|
* Nope, so remove it from hashtable and try to drop associated
|
|
|
|
* storage (if not done already).
|
|
|
|
*/
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
delete_function(function);
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2007-01-30 23:05:13 +01:00
|
|
|
/*
|
|
|
|
* If the function isn't in active use then we can overwrite the
|
|
|
|
* func struct with new data, allowing any other existing fn_extra
|
|
|
|
* pointers to make use of the new definition on their next use.
|
|
|
|
* If it is in use then just leave it alone and make a new one.
|
|
|
|
* (The active invocations will run to completion using the
|
|
|
|
* previous definition, and then the cache entry will just be
|
|
|
|
* leaked; doesn't seem worth adding code to clean it up, given
|
|
|
|
* what a corner case this is.)
|
|
|
|
*
|
|
|
|
* If we found the function struct via fn_extra then it's possible
|
2007-11-15 22:14:46 +01:00
|
|
|
* a replacement has already been made, so go back and recheck the
|
|
|
|
* hashtable.
|
2007-01-30 23:05:13 +01:00
|
|
|
*/
|
|
|
|
if (function->use_count != 0)
|
|
|
|
{
|
|
|
|
function = NULL;
|
|
|
|
if (!hashkey_valid)
|
|
|
|
goto recheck;
|
|
|
|
}
|
2003-07-01 23:47:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If the function wasn't found or was out-of-date, we have to compile it
|
2003-07-01 23:47:09 +02:00
|
|
|
*/
|
2007-01-30 23:05:13 +01:00
|
|
|
if (!function_valid)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Calculate hashkey if we didn't already; we'll need it to store the
|
|
|
|
* completed function.
|
2003-07-01 23:47:09 +02:00
|
|
|
*/
|
|
|
|
if (!hashkey_valid)
|
2004-03-19 19:58:07 +01:00
|
|
|
compute_function_hashkey(fcinfo, procStruct, &hashkey,
|
|
|
|
forValidator);
|
2003-07-01 23:47:09 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the hard part.
|
|
|
|
*/
|
2007-01-30 23:05:13 +01:00
|
|
|
function = do_compile(fcinfo, procTup, function,
|
|
|
|
&hashkey, forValidator);
|
2003-07-01 23:47:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseSysCache(procTup);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Save pointer in FmgrInfo to avoid search on subsequent calls
|
|
|
|
*/
|
|
|
|
fcinfo->flinfo->fn_extra = (void *) function;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Finally return the compiled function
|
|
|
|
*/
|
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the slow part of plpgsql_compile().
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
*
|
2007-01-30 23:05:13 +01:00
|
|
|
* The passed-in "function" pointer is either NULL or an already-allocated
|
|
|
|
* function struct to overwrite.
|
|
|
|
*
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
* While compiling a function, the CurrentMemoryContext is the
|
|
|
|
* per-function memory context of the function we are compiling. That
|
|
|
|
* means a palloc() will allocate storage with the same lifetime as
|
|
|
|
* the function itself.
|
|
|
|
*
|
|
|
|
* Because palloc()'d storage will not be immediately freed, temporary
|
|
|
|
* allocations should either be performed in a short-lived memory
|
|
|
|
* context or explicitly pfree'd. Since not all backend functions are
|
|
|
|
* careful about pfree'ing their allocations, it is also wise to
|
|
|
|
* switch into a short-term context before calling into the
|
|
|
|
* backend. An appropriate context for performing short-term
|
2016-03-03 10:45:59 +01:00
|
|
|
* allocations is the plpgsql_compile_tmp_cxt.
|
2007-01-30 23:05:13 +01:00
|
|
|
*
|
|
|
|
* NB: this code is not re-entrant. We assume that nothing we do here could
|
|
|
|
* result in the invocation of another plpgsql function.
|
2003-07-01 23:47:09 +02:00
|
|
|
*/
|
|
|
|
static PLpgSQL_function *
|
|
|
|
do_compile(FunctionCallInfo fcinfo,
|
|
|
|
HeapTuple procTup,
|
2007-01-30 23:05:13 +01:00
|
|
|
PLpgSQL_function *function,
|
2005-11-22 19:17:34 +01:00
|
|
|
PLpgSQL_func_hashkey *hashkey,
|
2004-03-19 19:58:07 +01:00
|
|
|
bool forValidator)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
|
|
|
Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
|
2012-07-20 17:38:47 +02:00
|
|
|
bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
|
|
|
|
bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
|
2004-01-07 00:55:19 +01:00
|
|
|
Datum prosrcdatum;
|
|
|
|
bool isnull;
|
2003-07-01 23:47:09 +02:00
|
|
|
char *proc_source;
|
1998-09-01 06:40:42 +02:00
|
|
|
HeapTuple typeTup;
|
2018-03-02 14:57:38 +01:00
|
|
|
Form_pg_type typeStruct;
|
2004-06-04 00:56:43 +02:00
|
|
|
PLpgSQL_variable *var;
|
1998-09-01 06:40:42 +02:00
|
|
|
PLpgSQL_rec *rec;
|
|
|
|
int i;
|
2003-04-24 23:16:45 +02:00
|
|
|
ErrorContextCallback plerrcontext;
|
2003-07-01 23:47:09 +02:00
|
|
|
int parse_rc;
|
|
|
|
Oid rettypeid;
|
2005-04-05 08:22:17 +02:00
|
|
|
int numargs;
|
2005-04-07 16:53:04 +02:00
|
|
|
int num_in_args = 0;
|
|
|
|
int num_out_args = 0;
|
2005-04-05 08:22:17 +02:00
|
|
|
Oid *argtypes;
|
2004-01-07 07:20:02 +01:00
|
|
|
char **argnames;
|
2005-04-05 08:22:17 +02:00
|
|
|
char *argmodes;
|
|
|
|
int *in_arg_varnos = NULL;
|
|
|
|
PLpgSQL_variable **out_arg_variables;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
MemoryContext func_cxt;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Setup the scanner input and error info. We assume that this function
|
2005-10-15 04:49:52 +02:00
|
|
|
* cannot be invoked recursively, so there's no need to save and restore
|
|
|
|
* the static variables used here.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
2004-01-07 00:55:19 +01:00
|
|
|
prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
|
|
|
|
Anum_pg_proc_prosrc, &isnull);
|
|
|
|
if (isnull)
|
|
|
|
elog(ERROR, "null prosrc");
|
2008-03-25 23:42:46 +01:00
|
|
|
proc_source = TextDatumGetCString(prosrcdatum);
|
Revise plpgsql's scanner to process comments and string literals in a way
more nearly matching the core SQL scanner. The user-visible effects are:
* Block comments (slash-star comments) now nest, as per SQL spec.
* In standard_conforming_strings mode, backslash as the last character of a
non-E string literal is now correctly taken as an ordinary character;
formerly it was misinterpreted as escaping the ending quote. (Since the
string also had to pass through the core scanner, this invariably led
to syntax errors.)
* Formerly, backslashes in the format string of RAISE were always treated as
quoting the next character, regardless of mode. Now, they are ordinary
characters with standard_conforming_strings on, while with it off, they
introduce the same set of escapes as in the core SQL scanner. Also,
escape_string_warning is now effective for RAISE format strings. These
changes make RAISE format strings work just like any other string literal.
This is implemented by copying and pasting a lot of logic from the core
scanner. It would be a good idea to look into getting rid of plpgsql's
scanner entirely in favor of using the core scanner. However, that involves
more change than I can justify making during beta --- in particular, the core
scanner would have to become re-entrant.
In passing, remove the kluge that made the plpgsql scanner emit T_FUNCTION or
T_TRIGGER as a made-up first token. That presumably had some value once upon
a time, but now it's just useless complication for both the scanner and the
grammar.
2009-04-19 20:52:58 +02:00
|
|
|
plpgsql_scanner_init(proc_source);
|
2003-04-24 23:16:45 +02:00
|
|
|
|
2001-10-09 06:15:38 +02:00
|
|
|
plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2001-10-09 17:59:56 +02:00
|
|
|
/*
|
2003-04-24 23:16:45 +02:00
|
|
|
* Setup error traceback support for ereport()
|
2001-10-09 17:59:56 +02:00
|
|
|
*/
|
2003-04-24 23:16:45 +02:00
|
|
|
plerrcontext.callback = plpgsql_compile_error_callback;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
plerrcontext.arg = forValidator ? proc_source : NULL;
|
2003-04-24 23:16:45 +02:00
|
|
|
plerrcontext.previous = error_context_stack;
|
|
|
|
error_context_stack = &plerrcontext;
|
2001-10-09 17:59:56 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Do extra syntax checks when validating the function definition. We skip
|
|
|
|
* this when actually compiling functions for execution, for performance
|
|
|
|
* reasons.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
plpgsql_check_syntax = forValidator;
|
|
|
|
|
|
|
|
/*
|
2007-01-30 23:05:13 +01:00
|
|
|
* Create the new function struct, if not done already. The function
|
|
|
|
* structs are never thrown away, so keep them in TopMemoryContext.
|
|
|
|
*/
|
|
|
|
if (function == NULL)
|
|
|
|
{
|
|
|
|
function = (PLpgSQL_function *)
|
|
|
|
MemoryContextAllocZero(TopMemoryContext, sizeof(PLpgSQL_function));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* re-using a previously existing struct, so clear it out */
|
|
|
|
memset(function, 0, sizeof(PLpgSQL_function));
|
|
|
|
}
|
|
|
|
plpgsql_curr_compile = function;
|
|
|
|
|
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* All the permanent output of compilation (e.g. parse tree) is kept in a
|
|
|
|
* per-function memory context, so it can be reclaimed easily.
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
*/
|
|
|
|
func_cxt = AllocSetContextCreate(TopMemoryContext,
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
"PL/pgSQL function",
|
Add macros to make AllocSetContextCreate() calls simpler and safer.
I found that half a dozen (nearly 5%) of our AllocSetContextCreate calls
had typos in the context-sizing parameters. While none of these led to
especially significant problems, they did create minor inefficiencies,
and it's now clear that expecting people to copy-and-paste those calls
accurately is not a great idea. Let's reduce the risk of future errors
by introducing single macros that encapsulate the common use-cases.
Three such macros are enough to cover all but two special-purpose contexts;
those two calls can be left as-is, I think.
While this patch doesn't in itself improve matters for third-party
extensions, it doesn't break anything for them either, and they can
gradually adopt the simplified notation over time.
In passing, change TopMemoryContext to use the default allocation
parameters. Formerly it could only be extended 8K at a time. That was
probably reasonable when this code was written; but nowadays we create
many more contexts than we did then, so that it's not unusual to have a
couple hundred K in TopMemoryContext, even without considering various
dubious code that sticks other things there. There seems no good reason
not to let it use growing blocks like most other contexts.
Back-patch to 9.6, mostly because that's still close enough to HEAD that
it's easy to do so, and keeping the branches in sync can be expected to
avoid some future back-patching pain. The bugs fixed by these changes
don't seem to be significant enough to justify fixing them further back.
Discussion: <21072.1472321324@sss.pgh.pa.us>
2016-08-27 23:50:38 +02:00
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
2016-03-03 10:45:59 +01:00
|
|
|
plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2012-01-31 09:34:50 +01:00
|
|
|
function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
MemoryContextSetIdentifier(func_cxt, function->fn_signature);
|
2003-07-01 23:47:09 +02:00
|
|
|
function->fn_oid = fcinfo->flinfo->fn_oid;
|
2013-12-22 21:49:09 +01:00
|
|
|
function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
|
2007-02-09 04:35:35 +01:00
|
|
|
function->fn_tid = procTup->t_self;
|
2011-04-13 01:19:24 +02:00
|
|
|
function->fn_input_collation = fcinfo->fncollation;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
function->fn_cxt = func_cxt;
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
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:18:54 +02:00
|
|
|
function->out_param_varno = -1; /* set up for no OUT param */
|
2009-11-13 23:43:42 +01:00
|
|
|
function->resolve_option = plpgsql_variable_conflict;
|
2013-10-07 21:38:49 +02:00
|
|
|
function->print_strict_params = plpgsql_print_strict_params;
|
2014-04-06 18:21:51 +02:00
|
|
|
/* only promote extra warnings and errors at CREATE FUNCTION time */
|
|
|
|
function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
|
|
|
|
function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
|
2009-11-06 19:37:55 +01:00
|
|
|
|
2012-07-20 17:38:47 +02:00
|
|
|
if (is_dml_trigger)
|
2012-07-21 04:31:19 +02:00
|
|
|
function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
|
2012-07-20 17:38:47 +02:00
|
|
|
else if (is_event_trigger)
|
2012-07-21 04:31:19 +02:00
|
|
|
function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
|
2012-07-20 17:38:47 +02:00
|
|
|
else
|
2012-07-21 04:31:19 +02:00
|
|
|
function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
|
2012-07-20 17:38:47 +02:00
|
|
|
|
2018-03-02 14:57:38 +01:00
|
|
|
function->fn_prokind = procStruct->prokind;
|
|
|
|
|
2019-01-24 22:23:12 +01:00
|
|
|
function->nstatements = 0;
|
|
|
|
|
2009-11-06 19:37:55 +01:00
|
|
|
/*
|
|
|
|
* Initialize the compiler, particularly the namespace stack. The
|
|
|
|
* outermost namespace contains function parameters and other special
|
|
|
|
* variables (such as FOUND), and is named after the function itself.
|
|
|
|
*/
|
|
|
|
plpgsql_ns_init();
|
2015-08-22 02:17:19 +02:00
|
|
|
plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
|
2009-11-06 19:37:55 +01:00
|
|
|
plpgsql_DumpExecTree = false;
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
plpgsql_start_datums();
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2012-07-20 17:38:47 +02:00
|
|
|
switch (function->fn_is_trigger)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2012-07-20 17:38:47 +02:00
|
|
|
case PLPGSQL_NOT_TRIGGER:
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-04-05 08:22:17 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Fetch info about the procedure's parameters. Allocations aren't
|
|
|
|
* needed permanently, so make them in tmp cxt.
|
2005-04-05 08:22:17 +02:00
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* We also need to resolve any polymorphic input or output
|
2014-05-06 18:12:18 +02:00
|
|
|
* argument types. In validation mode we won't be able to, so we
|
2005-10-15 04:49:52 +02:00
|
|
|
* arbitrarily assume we are dealing with integers.
|
2005-04-05 08:22:17 +02:00
|
|
|
*/
|
2016-03-03 10:45:59 +01:00
|
|
|
MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
|
2005-04-05 08:22:17 +02:00
|
|
|
|
2005-12-28 19:11:25 +01:00
|
|
|
numargs = get_func_arg_info(procTup,
|
|
|
|
&argtypes, &argnames, &argmodes);
|
2005-04-05 08:22:17 +02:00
|
|
|
|
|
|
|
plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
|
|
|
|
fcinfo->flinfo->fn_expr,
|
|
|
|
forValidator,
|
|
|
|
plpgsql_error_funcname);
|
|
|
|
|
|
|
|
in_arg_varnos = (int *) palloc(numargs * sizeof(int));
|
|
|
|
out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
|
|
|
|
|
|
|
|
MemoryContextSwitchTo(func_cxt);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the variables for the procedure's parameters.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < numargs; i++)
|
|
|
|
{
|
|
|
|
char buf[32];
|
|
|
|
Oid argtypeid = argtypes[i];
|
|
|
|
char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
|
|
|
|
PLpgSQL_type *argdtype;
|
|
|
|
PLpgSQL_variable *argvariable;
|
2016-08-18 18:00:00 +02:00
|
|
|
PLpgSQL_nsitem_type argitemtype;
|
2005-04-05 08:22:17 +02:00
|
|
|
|
|
|
|
/* Create $n name for variable */
|
|
|
|
snprintf(buf, sizeof(buf), "$%d", i + 1);
|
|
|
|
|
|
|
|
/* Create datatype info */
|
2011-03-25 20:06:36 +01:00
|
|
|
argdtype = plpgsql_build_datatype(argtypeid,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL);
|
2005-04-05 08:22:17 +02:00
|
|
|
|
|
|
|
/* Disallow pseudotype argument */
|
2007-04-02 05:49:42 +02:00
|
|
|
/* (note we already replaced polymorphic types) */
|
2005-04-05 08:22:17 +02:00
|
|
|
/* (build_variable would do this, but wrong message) */
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
|
2005-04-05 08:22:17 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
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
|
|
|
errmsg("PL/pgSQL functions cannot accept type %s",
|
|
|
|
format_type_be(argtypeid))));
|
2005-04-05 08:22:17 +02:00
|
|
|
|
2017-09-11 22:24:34 +02:00
|
|
|
/*
|
|
|
|
* Build variable and add to datum list. If there's a name
|
|
|
|
* for the argument, use that as refname, else use $n name.
|
|
|
|
*/
|
|
|
|
argvariable = plpgsql_build_variable((argnames &&
|
|
|
|
argnames[i][0] != '\0') ?
|
|
|
|
argnames[i] : buf,
|
|
|
|
0, argdtype, false);
|
2005-04-05 08:22:17 +02:00
|
|
|
|
|
|
|
if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
|
|
|
|
{
|
|
|
|
argitemtype = PLPGSQL_NSTYPE_VAR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
|
|
|
|
argitemtype = PLPGSQL_NSTYPE_REC;
|
2005-04-05 08:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Remember arguments in appropriate arrays */
|
2008-07-16 03:30:23 +02:00
|
|
|
if (argmode == PROARGMODE_IN ||
|
|
|
|
argmode == PROARGMODE_INOUT ||
|
|
|
|
argmode == PROARGMODE_VARIADIC)
|
2005-04-05 08:22:17 +02:00
|
|
|
in_arg_varnos[num_in_args++] = argvariable->dno;
|
2008-07-18 05:32:53 +02:00
|
|
|
if (argmode == PROARGMODE_OUT ||
|
|
|
|
argmode == PROARGMODE_INOUT ||
|
|
|
|
argmode == PROARGMODE_TABLE)
|
2005-04-05 08:22:17 +02:00
|
|
|
out_arg_variables[num_out_args++] = argvariable;
|
|
|
|
|
|
|
|
/* Add to namespace under the $n name */
|
2011-05-23 22:34:27 +02:00
|
|
|
add_parameter_name(argitemtype, argvariable->dno, buf);
|
2005-04-05 08:22:17 +02:00
|
|
|
|
|
|
|
/* If there's a name for the argument, make an alias */
|
|
|
|
if (argnames && argnames[i][0] != '\0')
|
2011-05-23 22:34:27 +02:00
|
|
|
add_parameter_name(argitemtype, argvariable->dno,
|
2005-04-05 08:22:17 +02:00
|
|
|
argnames[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there's just one OUT parameter, out_param_varno points
|
2014-05-06 18:12:18 +02:00
|
|
|
* directly to it. If there's more than one, build a row that
|
2018-03-14 16:47:21 +01:00
|
|
|
* holds all of them. Procedures return a row even for one OUT
|
|
|
|
* parameter.
|
2005-04-05 08:22:17 +02:00
|
|
|
*/
|
2018-03-14 16:47:21 +01:00
|
|
|
if (num_out_args > 1 ||
|
|
|
|
(num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
|
2005-04-05 08:22:17 +02:00
|
|
|
{
|
|
|
|
PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
|
|
|
|
num_out_args);
|
|
|
|
|
|
|
|
plpgsql_adddatum((PLpgSQL_datum *) row);
|
2008-11-05 01:07:54 +01:00
|
|
|
function->out_param_varno = row->dno;
|
2005-04-05 08:22:17 +02:00
|
|
|
}
|
2018-03-14 16:47:21 +01:00
|
|
|
else if (num_out_args == 1)
|
|
|
|
function->out_param_varno = out_arg_variables[0]->dno;
|
2005-04-05 08:22:17 +02:00
|
|
|
|
2003-07-01 23:47:09 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Check for a polymorphic returntype. If found, use the actual
|
|
|
|
* returntype type from the caller's FuncExpr node, if we have
|
|
|
|
* one. (In validation mode we arbitrarily assume we are dealing
|
|
|
|
* with integers.)
|
2003-07-26 01:37:31 +02:00
|
|
|
*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Note: errcode is FEATURE_NOT_SUPPORTED because it should always
|
|
|
|
* work; if it doesn't we're in some context that fails to make
|
|
|
|
* the info available.
|
2003-07-01 23:47:09 +02:00
|
|
|
*/
|
|
|
|
rettypeid = procStruct->prorettype;
|
2007-04-02 05:49:42 +02:00
|
|
|
if (IsPolymorphicType(rettypeid))
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
2004-03-19 19:58:07 +01:00
|
|
|
if (forValidator)
|
|
|
|
{
|
|
|
|
if (rettypeid == ANYARRAYOID)
|
|
|
|
rettypeid = INT4ARRAYOID;
|
2011-11-03 12:16:28 +01:00
|
|
|
else if (rettypeid == ANYRANGEOID)
|
|
|
|
rettypeid = INT4RANGEOID;
|
2017-06-21 20:39:04 +02:00
|
|
|
else /* ANYELEMENT or ANYNONARRAY */
|
2004-03-19 19:58:07 +01:00
|
|
|
rettypeid = INT4OID;
|
2007-04-02 05:49:42 +02:00
|
|
|
/* XXX what could we use for ANYENUM? */
|
2004-03-19 19:58:07 +01:00
|
|
|
}
|
|
|
|
else
|
2005-04-05 08:22:17 +02:00
|
|
|
{
|
2004-03-19 19:58:07 +01:00
|
|
|
rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
|
2005-04-05 08:22:17 +02:00
|
|
|
if (!OidIsValid(rettypeid))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
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
|
|
|
errmsg("could not determine actual return type "
|
|
|
|
"for polymorphic function \"%s\"",
|
|
|
|
plpgsql_error_funcname)));
|
2005-04-05 08:22:17 +02:00
|
|
|
}
|
2003-07-01 23:47:09 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
1998-09-01 06:40:42 +02:00
|
|
|
* Normal function has a defined returntype
|
|
|
|
*/
|
2003-07-01 23:47:09 +02:00
|
|
|
function->fn_rettype = rettypeid;
|
1998-09-01 06:40:42 +02:00
|
|
|
function->fn_retset = procStruct->proretset;
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2004-11-30 04:50:29 +01:00
|
|
|
* Lookup the function's return type
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
2018-03-02 14:57:38 +01:00
|
|
|
typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
|
|
|
|
if (!HeapTupleIsValid(typeTup))
|
|
|
|
elog(ERROR, "cache lookup failed for type %u", rettypeid);
|
|
|
|
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
|
|
|
|
|
|
|
/* Disallow pseudotype result, except VOID or RECORD */
|
|
|
|
/* (note we already replaced polymorphic types) */
|
|
|
|
if (typeStruct->typtype == TYPTYPE_PSEUDO)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2018-03-02 14:57:38 +01:00
|
|
|
if (rettypeid == VOIDOID ||
|
|
|
|
rettypeid == RECORDOID)
|
2018-04-26 20:47:16 +02:00
|
|
|
/* okay */ ;
|
2018-03-02 14:57:38 +01:00
|
|
|
else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("trigger functions can only be called as triggers")));
|
|
|
|
else
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("PL/pgSQL functions cannot return type %s",
|
|
|
|
format_type_be(rettypeid))));
|
|
|
|
}
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
|
2018-03-02 14:57:38 +01:00
|
|
|
function->fn_retistuple = type_is_rowtype(rettypeid);
|
|
|
|
function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
|
|
|
|
function->fn_retbyval = typeStruct->typbyval;
|
|
|
|
function->fn_rettyplen = typeStruct->typlen;
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
|
2018-03-02 14:57:38 +01:00
|
|
|
/*
|
2018-04-26 20:47:16 +02:00
|
|
|
* install $0 reference, but only for polymorphic return types,
|
|
|
|
* and not when the return is specified through an output
|
|
|
|
* parameter.
|
2018-03-02 14:57:38 +01:00
|
|
|
*/
|
|
|
|
if (IsPolymorphicType(procStruct->prorettype) &&
|
|
|
|
num_out_args == 0)
|
|
|
|
{
|
|
|
|
(void) plpgsql_build_variable("$0", 0,
|
|
|
|
build_datatype(typeTup,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2018-03-02 14:57:38 +01:00
|
|
|
true);
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
2018-03-02 14:57:38 +01:00
|
|
|
|
|
|
|
ReleaseSysCache(typeTup);
|
1998-09-01 06:40:42 +02:00
|
|
|
break;
|
|
|
|
|
2012-07-20 17:38:47 +02:00
|
|
|
case PLPGSQL_DML_TRIGGER:
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Trigger procedure's return type is unknown yet */
|
1998-09-01 06:40:42 +02:00
|
|
|
function->fn_rettype = InvalidOid;
|
|
|
|
function->fn_retbyval = false;
|
|
|
|
function->fn_retistuple = true;
|
2018-02-15 22:25:19 +01:00
|
|
|
function->fn_retisdomain = false;
|
1998-09-01 06:40:42 +02:00
|
|
|
function->fn_retset = false;
|
|
|
|
|
2005-07-06 18:42:10 +02:00
|
|
|
/* shouldn't be any declared arguments */
|
|
|
|
if (procStruct->pronargs != 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
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
|
|
|
errmsg("trigger functions cannot have declared arguments"),
|
2009-02-18 12:33:04 +01:00
|
|
|
errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
|
2005-07-06 18:42:10 +02:00
|
|
|
|
2017-04-01 06:30:08 +02:00
|
|
|
/* Add the record for referencing NEW ROW */
|
2018-02-14 04:15:08 +01:00
|
|
|
rec = plpgsql_build_record("new", 0, NULL, RECORDOID, true);
|
2008-11-05 01:07:54 +01:00
|
|
|
function->new_varno = rec->dno;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2017-04-01 06:30:08 +02:00
|
|
|
/* Add the record for referencing OLD ROW */
|
2018-02-14 04:15:08 +01:00
|
|
|
rec = plpgsql_build_record("old", 0, NULL, RECORDOID, true);
|
2008-11-05 01:07:54 +01:00
|
|
|
function->old_varno = rec->dno;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Add the variable tg_name */
|
|
|
|
var = plpgsql_build_variable("tg_name", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(NAMEOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Add the variable tg_when */
|
|
|
|
var = plpgsql_build_variable("tg_when", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(TEXTOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Add the variable tg_level */
|
|
|
|
var = plpgsql_build_variable("tg_level", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(TEXTOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Add the variable tg_op */
|
|
|
|
var = plpgsql_build_variable("tg_op", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(TEXTOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Add the variable tg_relid */
|
|
|
|
var = plpgsql_build_variable("tg_relid", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(OIDOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
InvalidOid,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Add the variable tg_relname */
|
|
|
|
var = plpgsql_build_variable("tg_relname", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(NAMEOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2006-05-28 05:03:17 +02:00
|
|
|
/* tg_table_name is now preferred to tg_relname */
|
|
|
|
var = plpgsql_build_variable("tg_table_name", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(NAMEOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2006-05-28 05:03:17 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
|
2006-05-28 05:03:17 +02:00
|
|
|
|
2009-11-04 23:26:08 +01:00
|
|
|
/* add the variable tg_table_schema */
|
2006-05-28 05:03:17 +02:00
|
|
|
var = plpgsql_build_variable("tg_table_schema", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(NAMEOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2006-05-28 05:03:17 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
|
2006-05-28 05:03:17 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Add the variable tg_nargs */
|
|
|
|
var = plpgsql_build_variable("tg_nargs", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(INT4OID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
InvalidOid,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-04 23:26:08 +01:00
|
|
|
/* Add the variable tg_argv */
|
|
|
|
var = plpgsql_build_variable("tg_argv", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(TEXTARRAYOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2009-11-04 23:26:08 +01:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
|
2009-11-04 23:26:08 +01:00
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
break;
|
|
|
|
|
2012-07-20 17:38:47 +02:00
|
|
|
case PLPGSQL_EVENT_TRIGGER:
|
|
|
|
function->fn_rettype = VOIDOID;
|
|
|
|
function->fn_retbyval = false;
|
|
|
|
function->fn_retistuple = true;
|
2018-02-15 22:25:19 +01:00
|
|
|
function->fn_retisdomain = false;
|
2012-07-20 17:38:47 +02:00
|
|
|
function->fn_retset = false;
|
|
|
|
|
|
|
|
/* shouldn't be any declared arguments */
|
|
|
|
if (procStruct->pronargs != 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
|
|
|
errmsg("event trigger functions cannot have declared arguments")));
|
|
|
|
|
|
|
|
/* Add the variable tg_event */
|
|
|
|
var = plpgsql_build_variable("tg_event", 0,
|
|
|
|
plpgsql_build_datatype(TEXTOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2012-07-20 17:38:47 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
|
2012-07-20 17:38:47 +02:00
|
|
|
|
|
|
|
/* Add the variable tg_tag */
|
|
|
|
var = plpgsql_build_variable("tg_tag", 0,
|
|
|
|
plpgsql_build_datatype(TEXTOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
function->fn_input_collation,
|
|
|
|
NULL),
|
2012-07-20 17:38:47 +02:00
|
|
|
true);
|
2018-02-14 01:20:37 +01:00
|
|
|
Assert(var->dtype == PLPGSQL_DTYPE_VAR);
|
|
|
|
var->dtype = PLPGSQL_DTYPE_PROMISE;
|
|
|
|
((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
|
2012-07-20 17:38:47 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
default:
|
2012-07-20 17:38:47 +02:00
|
|
|
elog(ERROR, "unrecognized function typecode: %d",
|
|
|
|
(int) function->fn_is_trigger);
|
1998-09-01 06:40:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-09-13 22:10:13 +02:00
|
|
|
/* Remember if function is STABLE/IMMUTABLE */
|
|
|
|
function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2002-09-01 18:28:06 +02:00
|
|
|
* Create the magic FOUND variable.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
var = plpgsql_build_variable("found", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(BOOLOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
InvalidOid,
|
|
|
|
NULL),
|
2004-06-04 00:56:43 +02:00
|
|
|
true);
|
|
|
|
function->found_varno = var->dno;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2004-11-30 04:50:29 +01:00
|
|
|
* Now parse the function's text
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
|
|
|
parse_rc = plpgsql_yyparse();
|
|
|
|
if (parse_rc != 0)
|
2003-07-26 01:37:31 +02:00
|
|
|
elog(ERROR, "plpgsql parser returned %d", parse_rc);
|
2009-11-12 01:13:00 +01:00
|
|
|
function->action = plpgsql_parse_result;
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2003-05-05 18:46:28 +02:00
|
|
|
plpgsql_scanner_finish();
|
2004-03-21 23:29:11 +01:00
|
|
|
pfree(proc_source);
|
2003-05-05 18:46:28 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2005-04-07 16:53:04 +02:00
|
|
|
* If it has OUT parameters or returns VOID or returns a set, we allow
|
2005-10-15 04:49:52 +02:00
|
|
|
* control to fall off the end without an explicit RETURN statement. The
|
|
|
|
* easiest way to implement this is to add a RETURN statement to the end
|
2009-09-23 01:43:43 +02:00
|
|
|
* of the statement list during parsing.
|
2005-04-07 16:53:04 +02:00
|
|
|
*/
|
|
|
|
if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
|
|
|
|
function->fn_retset)
|
2009-09-23 01:43:43 +02:00
|
|
|
add_dummy_return(function);
|
2005-04-07 16:53:04 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Complete the function's info
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
|
|
|
function->fn_nargs = procStruct->pronargs;
|
|
|
|
for (i = 0; i < function->fn_nargs; i++)
|
2005-04-05 08:22:17 +02:00
|
|
|
function->fn_argvarnos[i] = in_arg_varnos[i];
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
|
|
|
|
plpgsql_finish_datums(function);
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2003-07-01 23:47:09 +02:00
|
|
|
/* Debug dump for completed functions */
|
|
|
|
if (plpgsql_DumpExecTree)
|
|
|
|
plpgsql_dumptree(function);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add it to the hash table
|
|
|
|
*/
|
|
|
|
plpgsql_HashTableInsert(function, hashkey);
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2001-10-09 17:59:56 +02:00
|
|
|
/*
|
2003-04-24 23:16:45 +02:00
|
|
|
* Pop the error context stack
|
2001-10-09 17:59:56 +02:00
|
|
|
*/
|
2003-04-24 23:16:45 +02:00
|
|
|
error_context_stack = plerrcontext.previous;
|
2001-10-09 17:59:56 +02:00
|
|
|
plpgsql_error_funcname = NULL;
|
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
plpgsql_check_syntax = false;
|
|
|
|
|
2016-03-03 10:45:59 +01:00
|
|
|
MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
|
|
|
|
plpgsql_compile_tmp_cxt = NULL;
|
1998-09-01 06:40:42 +02:00
|
|
|
return function;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
2009-09-23 01:43:43 +02:00
|
|
|
/* ----------
|
|
|
|
* plpgsql_compile_inline Make an execution tree for an anonymous code block.
|
|
|
|
*
|
|
|
|
* Note: this is generally parallel to do_compile(); is it worth trying to
|
|
|
|
* merge the two?
|
|
|
|
*
|
|
|
|
* Note: we assume the block will be thrown away so there is no need to build
|
|
|
|
* persistent data structures.
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
PLpgSQL_function *
|
|
|
|
plpgsql_compile_inline(char *proc_source)
|
|
|
|
{
|
|
|
|
char *func_name = "inline_code_block";
|
|
|
|
PLpgSQL_function *function;
|
|
|
|
ErrorContextCallback plerrcontext;
|
|
|
|
PLpgSQL_variable *var;
|
|
|
|
int parse_rc;
|
|
|
|
MemoryContext func_cxt;
|
|
|
|
|
|
|
|
/*
|
2014-05-06 18:12:18 +02:00
|
|
|
* Setup the scanner input and error info. We assume that this function
|
2009-09-23 01:43:43 +02:00
|
|
|
* cannot be invoked recursively, so there's no need to save and restore
|
|
|
|
* the static variables used here.
|
|
|
|
*/
|
|
|
|
plpgsql_scanner_init(proc_source);
|
|
|
|
|
|
|
|
plpgsql_error_funcname = func_name;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup error traceback support for ereport()
|
|
|
|
*/
|
|
|
|
plerrcontext.callback = plpgsql_compile_error_callback;
|
|
|
|
plerrcontext.arg = proc_source;
|
|
|
|
plerrcontext.previous = error_context_stack;
|
|
|
|
error_context_stack = &plerrcontext;
|
|
|
|
|
|
|
|
/* Do extra syntax checking if check_function_bodies is on */
|
|
|
|
plpgsql_check_syntax = check_function_bodies;
|
|
|
|
|
|
|
|
/* Function struct does not live past current statement */
|
|
|
|
function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
|
|
|
|
|
|
|
|
plpgsql_curr_compile = function;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* All the rest of the compile-time storage (e.g. parse tree) is kept in
|
|
|
|
* its own memory context, so it can be reclaimed easily.
|
|
|
|
*/
|
|
|
|
func_cxt = AllocSetContextCreate(CurrentMemoryContext,
|
Add macros to make AllocSetContextCreate() calls simpler and safer.
I found that half a dozen (nearly 5%) of our AllocSetContextCreate calls
had typos in the context-sizing parameters. While none of these led to
especially significant problems, they did create minor inefficiencies,
and it's now clear that expecting people to copy-and-paste those calls
accurately is not a great idea. Let's reduce the risk of future errors
by introducing single macros that encapsulate the common use-cases.
Three such macros are enough to cover all but two special-purpose contexts;
those two calls can be left as-is, I think.
While this patch doesn't in itself improve matters for third-party
extensions, it doesn't break anything for them either, and they can
gradually adopt the simplified notation over time.
In passing, change TopMemoryContext to use the default allocation
parameters. Formerly it could only be extended 8K at a time. That was
probably reasonable when this code was written; but nowadays we create
many more contexts than we did then, so that it's not unusual to have a
couple hundred K in TopMemoryContext, even without considering various
dubious code that sticks other things there. There seems no good reason
not to let it use growing blocks like most other contexts.
Back-patch to 9.6, mostly because that's still close enough to HEAD that
it's easy to do so, and keeping the branches in sync can be expected to
avoid some future back-patching pain. The bugs fixed by these changes
don't seem to be significant enough to justify fixing them further back.
Discussion: <21072.1472321324@sss.pgh.pa.us>
2016-08-27 23:50:38 +02:00
|
|
|
"PL/pgSQL inline code context",
|
|
|
|
ALLOCSET_DEFAULT_SIZES);
|
2016-03-03 10:45:59 +01:00
|
|
|
plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
|
2009-09-23 01:43:43 +02:00
|
|
|
|
2012-01-31 09:34:50 +01:00
|
|
|
function->fn_signature = pstrdup(func_name);
|
2012-07-20 17:38:47 +02:00
|
|
|
function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
|
2011-03-25 20:06:36 +01:00
|
|
|
function->fn_input_collation = InvalidOid;
|
2009-09-23 01:43:43 +02:00
|
|
|
function->fn_cxt = func_cxt;
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
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:18:54 +02:00
|
|
|
function->out_param_varno = -1; /* set up for no OUT param */
|
2009-11-13 23:43:42 +01:00
|
|
|
function->resolve_option = plpgsql_variable_conflict;
|
2013-10-07 21:38:49 +02:00
|
|
|
function->print_strict_params = plpgsql_print_strict_params;
|
2014-05-06 18:12:18 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* don't do extra validation for inline code as we don't want to add spam
|
|
|
|
* at runtime
|
|
|
|
*/
|
2014-04-06 18:21:51 +02:00
|
|
|
function->extra_warnings = 0;
|
|
|
|
function->extra_errors = 0;
|
2009-11-06 19:37:55 +01:00
|
|
|
|
2019-01-24 22:23:12 +01:00
|
|
|
function->nstatements = 0;
|
|
|
|
|
2009-11-06 19:37:55 +01:00
|
|
|
plpgsql_ns_init();
|
2015-08-22 02:17:19 +02:00
|
|
|
plpgsql_ns_push(func_name, PLPGSQL_LABEL_BLOCK);
|
2009-11-06 19:37:55 +01:00
|
|
|
plpgsql_DumpExecTree = false;
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
plpgsql_start_datums();
|
2009-09-23 01:43:43 +02:00
|
|
|
|
|
|
|
/* Set up as though in a function returning VOID */
|
|
|
|
function->fn_rettype = VOIDOID;
|
|
|
|
function->fn_retset = false;
|
|
|
|
function->fn_retistuple = false;
|
2018-02-15 22:25:19 +01:00
|
|
|
function->fn_retisdomain = false;
|
2018-03-02 14:57:38 +01:00
|
|
|
function->fn_prokind = PROKIND_FUNCTION;
|
2009-09-23 01:43:43 +02:00
|
|
|
/* a bit of hardwired knowledge about type VOID here */
|
|
|
|
function->fn_retbyval = true;
|
|
|
|
function->fn_rettyplen = sizeof(int32);
|
|
|
|
|
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* Remember if function is STABLE/IMMUTABLE. XXX would it be better to
|
2017-08-16 06:22:32 +02:00
|
|
|
* set this true inside a read-only transaction? Not clear.
|
2009-09-23 01:43:43 +02:00
|
|
|
*/
|
|
|
|
function->fn_readonly = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the magic FOUND variable.
|
|
|
|
*/
|
|
|
|
var = plpgsql_build_variable("found", 0,
|
2011-03-25 20:06:36 +01:00
|
|
|
plpgsql_build_datatype(BOOLOID,
|
|
|
|
-1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
InvalidOid,
|
|
|
|
NULL),
|
2009-09-23 01:43:43 +02:00
|
|
|
true);
|
|
|
|
function->found_varno = var->dno;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now parse the function's text
|
|
|
|
*/
|
|
|
|
parse_rc = plpgsql_yyparse();
|
|
|
|
if (parse_rc != 0)
|
|
|
|
elog(ERROR, "plpgsql parser returned %d", parse_rc);
|
2009-11-12 01:13:00 +01:00
|
|
|
function->action = plpgsql_parse_result;
|
2009-09-23 01:43:43 +02:00
|
|
|
|
|
|
|
plpgsql_scanner_finish();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If it returns VOID (always true at the moment), we allow control to
|
|
|
|
* fall off the end without an explicit RETURN statement.
|
|
|
|
*/
|
|
|
|
if (function->fn_rettype == VOIDOID)
|
|
|
|
add_dummy_return(function);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Complete the function's info
|
|
|
|
*/
|
|
|
|
function->fn_nargs = 0;
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
|
|
|
|
plpgsql_finish_datums(function);
|
2009-09-23 01:43:43 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Pop the error context stack
|
|
|
|
*/
|
|
|
|
error_context_stack = plerrcontext.previous;
|
|
|
|
plpgsql_error_funcname = NULL;
|
|
|
|
|
|
|
|
plpgsql_check_syntax = false;
|
|
|
|
|
2016-03-03 10:45:59 +01:00
|
|
|
MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
|
|
|
|
plpgsql_compile_tmp_cxt = NULL;
|
2009-09-23 01:43:43 +02:00
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2003-04-24 23:16:45 +02:00
|
|
|
/*
|
2009-09-23 01:43:43 +02:00
|
|
|
* error context callback to let us supply a call-stack traceback.
|
|
|
|
* If we are validating or executing an anonymous code block, the function
|
|
|
|
* source text is passed as an argument.
|
2003-04-24 23:16:45 +02:00
|
|
|
*/
|
Modernize plpgsql's handling of parse locations, making it look a lot more
like the core parser's code. In particular, track locations at the character
rather than line level during parsing, allowing many more parse-time error
conditions to be reported with precise error pointers rather than just
"near line N".
Also, exploit the fact that we no longer need to substitute $N for variable
references by making extracted SQL queries and expressions be exact copies
of subranges of the function text, rather than having random whitespace
changes within them. This makes it possible to directly map parse error
positions from the core parser onto positions in the function text, which
lets us report them without the previous kluge of showing the intermediate
internal-query form. (Later it might be good to do that for core
parse-analysis errors too, but this patch is just touching plpgsql's
lexer/parser, not what happens at runtime.)
In passing, make plpgsql's lexer use palloc not malloc.
These changes make plpgsql's parse-time error reports noticeably nicer
(as illustrated by the regression test changes), and will also simplify
the planned removal of plpgsql's separate lexer by reducing the impedance
mismatch between what it does and what the core lexer does.
2009-11-09 01:26:55 +01:00
|
|
|
static void
|
2003-04-24 23:16:45 +02:00
|
|
|
plpgsql_compile_error_callback(void *arg)
|
|
|
|
{
|
2004-03-21 23:29:11 +01:00
|
|
|
if (arg)
|
|
|
|
{
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Try to convert syntax error position to reference text of original
|
2009-09-23 01:43:43 +02:00
|
|
|
* CREATE FUNCTION or DO command.
|
2004-03-21 23:29:11 +01:00
|
|
|
*/
|
|
|
|
if (function_parse_error_transpose((const char *) arg))
|
|
|
|
return;
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2004-03-21 23:29:11 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Done if a syntax error position was reported; otherwise we have to
|
|
|
|
* fall back to a "near line N" report.
|
2004-03-21 23:29:11 +01:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2003-04-24 23:16:45 +02:00
|
|
|
if (plpgsql_error_funcname)
|
2009-02-18 12:33:04 +01:00
|
|
|
errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
|
Modernize plpgsql's handling of parse locations, making it look a lot more
like the core parser's code. In particular, track locations at the character
rather than line level during parsing, allowing many more parse-time error
conditions to be reported with precise error pointers rather than just
"near line N".
Also, exploit the fact that we no longer need to substitute $N for variable
references by making extracted SQL queries and expressions be exact copies
of subranges of the function text, rather than having random whitespace
changes within them. This makes it possible to directly map parse error
positions from the core parser onto positions in the function text, which
lets us report them without the previous kluge of showing the intermediate
internal-query form. (Later it might be good to do that for core
parse-analysis errors too, but this patch is just touching plpgsql's
lexer/parser, not what happens at runtime.)
In passing, make plpgsql's lexer use palloc not malloc.
These changes make plpgsql's parse-time error reports noticeably nicer
(as illustrated by the regression test changes), and will also simplify
the planned removal of plpgsql's separate lexer by reducing the impedance
mismatch between what it does and what the core lexer does.
2009-11-09 01:26:55 +01:00
|
|
|
plpgsql_error_funcname, plpgsql_latest_lineno());
|
2003-04-24 23:16:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-23 22:34:27 +02:00
|
|
|
/*
|
|
|
|
* Add a name for a function parameter to the function's namespace
|
|
|
|
*/
|
|
|
|
static void
|
2016-08-18 18:00:00 +02:00
|
|
|
add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
|
2011-05-23 22:34:27 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Before adding the name, check for duplicates. We need this even though
|
|
|
|
* functioncmds.c has a similar check, because that code explicitly
|
|
|
|
* doesn't complain about conflicting IN and OUT parameter names. In
|
|
|
|
* plpgsql, such names are in the same namespace, so there is no way to
|
|
|
|
* disambiguate.
|
|
|
|
*/
|
|
|
|
if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
|
|
|
|
name, NULL, NULL,
|
|
|
|
NULL) != NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
|
|
|
errmsg("parameter name \"%s\" used more than once",
|
|
|
|
name)));
|
|
|
|
|
|
|
|
/* OK, add the name */
|
|
|
|
plpgsql_ns_additem(itemtype, itemno, name);
|
|
|
|
}
|
|
|
|
|
2009-09-23 01:43:43 +02:00
|
|
|
/*
|
|
|
|
* Add a dummy RETURN statement to the given function's body
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
add_dummy_return(PLpgSQL_function *function)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If the outer block has an EXCEPTION clause, we need to make a new outer
|
|
|
|
* block, since the added RETURN shouldn't act like it is inside the
|
|
|
|
* EXCEPTION clause.
|
|
|
|
*/
|
|
|
|
if (function->action->exceptions != NULL)
|
|
|
|
{
|
|
|
|
PLpgSQL_stmt_block *new;
|
|
|
|
|
|
|
|
new = palloc0(sizeof(PLpgSQL_stmt_block));
|
|
|
|
new->cmd_type = PLPGSQL_STMT_BLOCK;
|
2019-01-24 22:23:12 +01:00
|
|
|
new->stmtid = ++function->nstatements;
|
2009-09-23 01:43:43 +02:00
|
|
|
new->body = list_make1(function->action);
|
|
|
|
|
|
|
|
function->action = new;
|
|
|
|
}
|
|
|
|
if (function->action->body == NIL ||
|
|
|
|
((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
|
|
|
|
{
|
|
|
|
PLpgSQL_stmt_return *new;
|
|
|
|
|
|
|
|
new = palloc0(sizeof(PLpgSQL_stmt_return));
|
|
|
|
new->cmd_type = PLPGSQL_STMT_RETURN;
|
2019-01-24 22:23:12 +01:00
|
|
|
new->stmtid = ++function->nstatements;
|
2009-09-23 01:43:43 +02:00
|
|
|
new->expr = NULL;
|
|
|
|
new->retvarno = function->out_param_varno;
|
|
|
|
|
|
|
|
function->action->body = lappend(function->action->body, new);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-06 19:37:55 +01:00
|
|
|
/*
|
|
|
|
* plpgsql_parser_setup set up parser hooks for dynamic parameters
|
|
|
|
*
|
|
|
|
* Note: this routine, and the hook functions it prepares for, are logically
|
|
|
|
* part of plpgsql parsing. But they actually run during function execution,
|
|
|
|
* when we are ready to evaluate a SQL query or expression that has not
|
|
|
|
* previously been parsed and planned.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
|
|
|
|
{
|
|
|
|
pstate->p_pre_columnref_hook = plpgsql_pre_column_ref;
|
|
|
|
pstate->p_post_columnref_hook = plpgsql_post_column_ref;
|
|
|
|
pstate->p_paramref_hook = plpgsql_param_ref;
|
|
|
|
/* no need to use p_coerce_param_hook */
|
|
|
|
pstate->p_ref_hook_state = (void *) expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* plpgsql_pre_column_ref parser callback before parsing a ColumnRef
|
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
|
|
|
|
{
|
|
|
|
PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
|
|
|
|
|
2009-11-13 23:43:42 +01:00
|
|
|
if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
|
2010-11-18 23:06:57 +01:00
|
|
|
return resolve_column_ref(pstate, expr, cref, false);
|
2009-11-06 19:37:55 +01:00
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* plpgsql_post_column_ref parser callback after parsing a ColumnRef
|
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
|
|
|
|
{
|
|
|
|
PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
|
|
|
|
Node *myvar;
|
|
|
|
|
2009-11-13 23:43:42 +01:00
|
|
|
if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
|
2009-11-06 19:37:55 +01:00
|
|
|
return NULL; /* we already found there's no match */
|
|
|
|
|
2009-11-13 23:43:42 +01:00
|
|
|
if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
|
2009-11-06 19:37:55 +01:00
|
|
|
return NULL; /* there's a table column, prefer that */
|
|
|
|
|
2010-11-18 23:06:57 +01:00
|
|
|
/*
|
|
|
|
* If we find a record/row variable but can't match a field name, throw
|
2014-05-06 18:12:18 +02:00
|
|
|
* error if there was no core resolution for the ColumnRef either. In
|
2010-11-18 23:06:57 +01:00
|
|
|
* that situation, the reference is inevitably going to fail, and
|
2011-04-10 17:42:00 +02:00
|
|
|
* complaining about the record/row variable is likely to be more on-point
|
|
|
|
* than the core parser's error message. (It's too bad we don't have
|
|
|
|
* access to transformColumnRef's internal crerr state here, as in case of
|
|
|
|
* a conflict with a table name this could still be less than the most
|
|
|
|
* helpful error message possible.)
|
2010-11-18 23:06:57 +01:00
|
|
|
*/
|
|
|
|
myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
|
2009-11-06 19:37:55 +01:00
|
|
|
|
|
|
|
if (myvar != NULL && var != NULL)
|
|
|
|
{
|
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* We could leave it to the core parser to throw this error, but we
|
|
|
|
* can add a more useful detail message than the core could.
|
2009-11-06 19:37:55 +01:00
|
|
|
*/
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_AMBIGUOUS_COLUMN),
|
|
|
|
errmsg("column reference \"%s\" is ambiguous",
|
|
|
|
NameListToString(cref->fields)),
|
|
|
|
errdetail("It could refer to either a PL/pgSQL variable or a table column."),
|
|
|
|
parser_errposition(pstate, cref->location)));
|
|
|
|
}
|
|
|
|
|
|
|
|
return myvar;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* plpgsql_param_ref parser callback for ParamRefs ($n symbols)
|
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
|
|
|
|
{
|
|
|
|
PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
|
|
|
|
char pname[32];
|
|
|
|
PLpgSQL_nsitem *nse;
|
|
|
|
|
|
|
|
snprintf(pname, sizeof(pname), "$%d", pref->number);
|
|
|
|
|
2009-11-07 01:52:26 +01:00
|
|
|
nse = plpgsql_ns_lookup(expr->ns, false,
|
2009-11-06 19:37:55 +01:00
|
|
|
pname, NULL, NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (nse == NULL)
|
|
|
|
return NULL; /* name not known to plpgsql */
|
|
|
|
|
|
|
|
return make_datum_param(expr, nse->itemno, pref->location);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* resolve_column_ref attempt to resolve a ColumnRef as a plpgsql var
|
|
|
|
*
|
|
|
|
* Returns the translated node structure, or NULL if name not found
|
2010-11-18 23:06:57 +01:00
|
|
|
*
|
|
|
|
* error_if_no_field tells whether to throw error or quietly return NULL if
|
|
|
|
* we are able to match a record/row name but don't find a field name match.
|
2009-11-06 19:37:55 +01:00
|
|
|
*/
|
|
|
|
static Node *
|
2010-11-18 23:06:57 +01:00
|
|
|
resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
|
|
|
|
ColumnRef *cref, bool error_if_no_field)
|
2009-11-06 19:37:55 +01:00
|
|
|
{
|
|
|
|
PLpgSQL_execstate *estate;
|
|
|
|
PLpgSQL_nsitem *nse;
|
|
|
|
const char *name1;
|
|
|
|
const char *name2 = NULL;
|
|
|
|
const char *name3 = NULL;
|
|
|
|
const char *colname = NULL;
|
|
|
|
int nnames;
|
|
|
|
int nnames_scalar = 0;
|
|
|
|
int nnames_wholerow = 0;
|
|
|
|
int nnames_field = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We use the function's current estate to resolve parameter data types.
|
|
|
|
* This is really pretty bogus because there is no provision for updating
|
|
|
|
* plans when those types change ...
|
|
|
|
*/
|
|
|
|
estate = expr->func->cur_estate;
|
|
|
|
|
|
|
|
/*----------
|
|
|
|
* The allowed syntaxes are:
|
|
|
|
*
|
|
|
|
* A Scalar variable reference, or whole-row record reference.
|
|
|
|
* A.B Qualified scalar or whole-row reference, or field reference.
|
|
|
|
* A.B.C Qualified record field reference.
|
|
|
|
* A.* Whole-row record reference.
|
|
|
|
* A.B.* Qualified whole-row record reference.
|
|
|
|
*----------
|
|
|
|
*/
|
|
|
|
switch (list_length(cref->fields))
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
Node *field1 = (Node *) linitial(cref->fields);
|
|
|
|
|
|
|
|
Assert(IsA(field1, String));
|
|
|
|
name1 = strVal(field1);
|
|
|
|
nnames_scalar = 1;
|
|
|
|
nnames_wholerow = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
Node *field1 = (Node *) linitial(cref->fields);
|
|
|
|
Node *field2 = (Node *) lsecond(cref->fields);
|
|
|
|
|
|
|
|
Assert(IsA(field1, String));
|
|
|
|
name1 = strVal(field1);
|
|
|
|
|
|
|
|
/* Whole-row reference? */
|
|
|
|
if (IsA(field2, A_Star))
|
|
|
|
{
|
|
|
|
/* Set name2 to prevent matches to scalar variables */
|
|
|
|
name2 = "*";
|
|
|
|
nnames_wholerow = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Assert(IsA(field2, String));
|
|
|
|
name2 = strVal(field2);
|
|
|
|
colname = name2;
|
|
|
|
nnames_scalar = 2;
|
|
|
|
nnames_wholerow = 2;
|
|
|
|
nnames_field = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
Node *field1 = (Node *) linitial(cref->fields);
|
|
|
|
Node *field2 = (Node *) lsecond(cref->fields);
|
|
|
|
Node *field3 = (Node *) lthird(cref->fields);
|
|
|
|
|
|
|
|
Assert(IsA(field1, String));
|
|
|
|
name1 = strVal(field1);
|
|
|
|
Assert(IsA(field2, String));
|
|
|
|
name2 = strVal(field2);
|
|
|
|
|
|
|
|
/* Whole-row reference? */
|
|
|
|
if (IsA(field3, A_Star))
|
|
|
|
{
|
|
|
|
/* Set name3 to prevent matches to scalar variables */
|
|
|
|
name3 = "*";
|
|
|
|
nnames_wholerow = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Assert(IsA(field3, String));
|
|
|
|
name3 = strVal(field3);
|
|
|
|
colname = name3;
|
|
|
|
nnames_field = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
/* too many names, ignore */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-11-07 01:52:26 +01:00
|
|
|
nse = plpgsql_ns_lookup(expr->ns, false,
|
2009-11-06 19:37:55 +01:00
|
|
|
name1, name2, name3,
|
|
|
|
&nnames);
|
|
|
|
|
|
|
|
if (nse == NULL)
|
|
|
|
return NULL; /* name not known to plpgsql */
|
|
|
|
|
|
|
|
switch (nse->itemtype)
|
|
|
|
{
|
|
|
|
case PLPGSQL_NSTYPE_VAR:
|
|
|
|
if (nnames == nnames_scalar)
|
|
|
|
return make_datum_param(expr, nse->itemno, cref->location);
|
|
|
|
break;
|
|
|
|
case PLPGSQL_NSTYPE_REC:
|
|
|
|
if (nnames == nnames_wholerow)
|
|
|
|
return make_datum_param(expr, nse->itemno, cref->location);
|
|
|
|
if (nnames == nnames_field)
|
|
|
|
{
|
2010-01-10 18:15:18 +01:00
|
|
|
/* colname could be a field in this record */
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
PLpgSQL_rec *rec = (PLpgSQL_rec *) estate->datums[nse->itemno];
|
2009-11-06 19:37:55 +01:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* search for a datum referencing this field */
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
i = rec->firstfield;
|
|
|
|
while (i >= 0)
|
2009-11-06 19:37:55 +01:00
|
|
|
{
|
|
|
|
PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
|
|
|
|
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
|
|
|
|
fld->recparentno == nse->itemno);
|
|
|
|
if (strcmp(fld->fieldname, colname) == 0)
|
2009-11-06 19:37:55 +01:00
|
|
|
{
|
|
|
|
return make_datum_param(expr, i, cref->location);
|
|
|
|
}
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
i = fld->nextfield;
|
2009-11-06 19:37:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-01-10 18:15:18 +01:00
|
|
|
* We should not get here, because a RECFIELD datum should
|
|
|
|
* have been built at parse time for every possible qualified
|
2014-05-06 18:12:18 +02:00
|
|
|
* reference to fields of this record. But if we do, handle
|
2010-11-18 23:06:57 +01:00
|
|
|
* it like field-not-found: throw error or return NULL.
|
2009-11-06 19:37:55 +01:00
|
|
|
*/
|
2010-11-18 23:06:57 +01:00
|
|
|
if (error_if_no_field)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
|
|
|
errmsg("record \"%s\" has no field \"%s\"",
|
|
|
|
(nnames_field == 1) ? name1 : name2,
|
|
|
|
colname),
|
|
|
|
parser_errposition(pstate, cref->location)));
|
2009-11-06 19:37:55 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2009-11-07 01:52:26 +01:00
|
|
|
elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
|
2009-11-06 19:37:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Name format doesn't match the plpgsql variable type */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper for columnref parsing: build a Param referencing a plpgsql datum,
|
|
|
|
* and make sure that that datum is listed in the expression's paramnos.
|
|
|
|
*/
|
|
|
|
static Node *
|
|
|
|
make_datum_param(PLpgSQL_expr *expr, int dno, int location)
|
|
|
|
{
|
|
|
|
PLpgSQL_execstate *estate;
|
2011-03-25 20:06:36 +01:00
|
|
|
PLpgSQL_datum *datum;
|
2009-11-06 19:37:55 +01:00
|
|
|
Param *param;
|
|
|
|
MemoryContext oldcontext;
|
|
|
|
|
|
|
|
/* see comment in resolve_column_ref */
|
|
|
|
estate = expr->func->cur_estate;
|
|
|
|
Assert(dno >= 0 && dno < estate->ndatums);
|
2011-03-25 20:06:36 +01:00
|
|
|
datum = estate->datums[dno];
|
2009-11-06 19:37:55 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Bitmapset must be allocated in function's permanent memory context
|
|
|
|
*/
|
|
|
|
oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
|
|
|
|
expr->paramnos = bms_add_member(expr->paramnos, dno);
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
|
|
|
param = makeNode(Param);
|
|
|
|
param->paramkind = PARAM_EXTERN;
|
|
|
|
param->paramid = dno + 1;
|
2016-03-03 10:45:59 +01:00
|
|
|
plpgsql_exec_get_datum_type_info(estate,
|
2016-06-10 00:02:36 +02:00
|
|
|
datum,
|
|
|
|
¶m->paramtype,
|
|
|
|
¶m->paramtypmod,
|
|
|
|
¶m->paramcollid);
|
2009-11-06 19:37:55 +01:00
|
|
|
param->location = location;
|
|
|
|
|
|
|
|
return (Node *) param;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-08-22 14:38:39 +02:00
|
|
|
/* ----------
|
|
|
|
* plpgsql_parse_word The scanner calls this to postparse
|
2009-11-12 01:13:00 +01:00
|
|
|
* any single word that is not a reserved keyword.
|
|
|
|
*
|
|
|
|
* word1 is the downcased/dequoted identifier; it must be palloc'd in the
|
|
|
|
* function's long-term memory context.
|
|
|
|
*
|
|
|
|
* yytxt is the original token text; we need this to check for quoting,
|
|
|
|
* so that later checks for unreserved keywords work properly.
|
|
|
|
*
|
2019-01-04 18:16:19 +01:00
|
|
|
* We attempt to recognize the token as a variable only if lookup is true
|
|
|
|
* and the plpgsql_IdentifierLookup context permits it.
|
|
|
|
*
|
2017-08-16 06:22:32 +02:00
|
|
|
* If recognized as a variable, fill in *wdatum and return true;
|
|
|
|
* if not recognized, fill in *word and return false.
|
2009-11-12 01:13:00 +01:00
|
|
|
* (Note: those two pointers actually point to members of the same union,
|
|
|
|
* but for notational reasons we pass them separately.)
|
1998-08-22 14:38:39 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-12 01:13:00 +01:00
|
|
|
bool
|
2019-01-04 18:16:19 +01:00
|
|
|
plpgsql_parse_word(char *word1, const char *yytxt, bool lookup,
|
2009-11-12 01:13:00 +01:00
|
|
|
PLwdatum *wdatum, PLword *word)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
2009-11-12 01:13:00 +01:00
|
|
|
PLpgSQL_nsitem *ns;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2010-01-10 18:15:18 +01:00
|
|
|
/*
|
2019-01-04 18:16:19 +01:00
|
|
|
* We should not lookup variables in DECLARE sections. In SQL
|
|
|
|
* expressions, there's no need to do so either --- lookup will happen
|
|
|
|
* when the expression is compiled.
|
2010-01-10 18:15:18 +01:00
|
|
|
*/
|
2019-01-04 18:16:19 +01:00
|
|
|
if (lookup && plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2009-11-10 03:13:13 +01:00
|
|
|
/*
|
|
|
|
* Do a lookup in the current namespace stack
|
|
|
|
*/
|
2009-11-12 01:13:00 +01:00
|
|
|
ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
|
|
|
|
word1, NULL, NULL,
|
|
|
|
NULL);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-12 01:13:00 +01:00
|
|
|
if (ns != NULL)
|
2009-11-10 03:13:13 +01:00
|
|
|
{
|
2009-11-12 01:13:00 +01:00
|
|
|
switch (ns->itemtype)
|
2009-11-10 03:13:13 +01:00
|
|
|
{
|
|
|
|
case PLPGSQL_NSTYPE_VAR:
|
|
|
|
case PLPGSQL_NSTYPE_REC:
|
2009-11-12 01:13:00 +01:00
|
|
|
wdatum->datum = plpgsql_Datums[ns->itemno];
|
|
|
|
wdatum->ident = word1;
|
|
|
|
wdatum->quoted = (yytxt[0] == '"');
|
|
|
|
wdatum->idents = NIL;
|
|
|
|
return true;
|
2009-11-10 03:13:13 +01:00
|
|
|
|
|
|
|
default:
|
2010-01-10 18:15:18 +01:00
|
|
|
/* plpgsql_ns_lookup should never return anything else */
|
2009-11-10 03:13:13 +01:00
|
|
|
elog(ERROR, "unrecognized plpgsql itemtype: %d",
|
2009-11-12 01:13:00 +01:00
|
|
|
ns->itemtype);
|
2009-11-10 03:13:13 +01:00
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Nothing found - up to now it's a word without any special meaning for
|
|
|
|
* us.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
2009-11-12 01:13:00 +01:00
|
|
|
word->ident = word1;
|
|
|
|
word->quoted = (yytxt[0] == '"');
|
|
|
|
return false;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* plpgsql_parse_dblword Same lookup for two words
|
|
|
|
* separated by a dot.
|
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-12 01:13:00 +01:00
|
|
|
bool
|
|
|
|
plpgsql_parse_dblword(char *word1, char *word2,
|
|
|
|
PLwdatum *wdatum, PLcword *cword)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
PLpgSQL_nsitem *ns;
|
2009-11-10 03:13:13 +01:00
|
|
|
List *idents;
|
2007-11-27 20:58:44 +01:00
|
|
|
int nnames;
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2009-11-12 01:13:00 +01:00
|
|
|
idents = list_make2(makeString(word1),
|
|
|
|
makeString(word2));
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2010-01-10 18:15:18 +01:00
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* We should do nothing in DECLARE sections. In SQL expressions, we
|
|
|
|
* really only need to make sure that RECFIELD datums are created when
|
|
|
|
* needed.
|
2010-01-10 18:15:18 +01:00
|
|
|
*/
|
|
|
|
if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2009-11-10 03:13:13 +01:00
|
|
|
/*
|
|
|
|
* Do a lookup in the current namespace stack
|
|
|
|
*/
|
|
|
|
ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
|
2009-11-12 01:13:00 +01:00
|
|
|
word1, word2, NULL,
|
2009-11-10 03:13:13 +01:00
|
|
|
&nnames);
|
|
|
|
if (ns != NULL)
|
|
|
|
{
|
|
|
|
switch (ns->itemtype)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2009-11-10 03:13:13 +01:00
|
|
|
case PLPGSQL_NSTYPE_VAR:
|
|
|
|
/* Block-qualified reference to scalar variable. */
|
2009-11-12 01:13:00 +01:00
|
|
|
wdatum->datum = plpgsql_Datums[ns->itemno];
|
|
|
|
wdatum->ident = NULL;
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
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:18:54 +02:00
|
|
|
wdatum->quoted = false; /* not used */
|
2009-11-12 01:13:00 +01:00
|
|
|
wdatum->idents = idents;
|
|
|
|
return true;
|
2009-11-10 03:13:13 +01:00
|
|
|
|
|
|
|
case PLPGSQL_NSTYPE_REC:
|
|
|
|
if (nnames == 1)
|
|
|
|
{
|
|
|
|
/*
|
2010-01-10 18:15:18 +01:00
|
|
|
* First word is a record name, so second word could
|
|
|
|
* be a field in this record. We build a RECFIELD
|
|
|
|
* datum whether it is or not --- any error will be
|
|
|
|
* detected later.
|
2009-11-10 03:13:13 +01:00
|
|
|
*/
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
PLpgSQL_rec *rec;
|
2009-11-10 03:13:13 +01:00
|
|
|
PLpgSQL_recfield *new;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
|
|
|
|
new = plpgsql_build_recfield(rec, word2);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-12 01:13:00 +01:00
|
|
|
wdatum->datum = (PLpgSQL_datum *) new;
|
2009-11-10 03:13:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Block-qualified reference to record variable. */
|
2009-11-12 01:13:00 +01:00
|
|
|
wdatum->datum = plpgsql_Datums[ns->itemno];
|
2009-11-10 03:13:13 +01:00
|
|
|
}
|
2009-11-12 01:13:00 +01:00
|
|
|
wdatum->ident = NULL;
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
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:18:54 +02:00
|
|
|
wdatum->quoted = false; /* not used */
|
2009-11-12 01:13:00 +01:00
|
|
|
wdatum->idents = idents;
|
|
|
|
return true;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-10 03:13:13 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2009-11-10 03:13:13 +01:00
|
|
|
/* Nothing found */
|
2009-11-12 01:13:00 +01:00
|
|
|
cword->idents = idents;
|
|
|
|
return false;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* plpgsql_parse_tripword Same lookup for three words
|
|
|
|
* separated by dots.
|
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-12 01:13:00 +01:00
|
|
|
bool
|
|
|
|
plpgsql_parse_tripword(char *word1, char *word2, char *word3,
|
|
|
|
PLwdatum *wdatum, PLcword *cword)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
PLpgSQL_nsitem *ns;
|
2009-11-10 03:13:13 +01:00
|
|
|
List *idents;
|
2007-11-27 20:58:44 +01:00
|
|
|
int nnames;
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2009-11-12 01:13:00 +01:00
|
|
|
idents = list_make3(makeString(word1),
|
|
|
|
makeString(word2),
|
|
|
|
makeString(word3));
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2010-01-10 18:15:18 +01:00
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* We should do nothing in DECLARE sections. In SQL expressions, we
|
|
|
|
* really only need to make sure that RECFIELD datums are created when
|
|
|
|
* needed.
|
2010-01-10 18:15:18 +01:00
|
|
|
*/
|
|
|
|
if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2009-11-10 03:13:13 +01:00
|
|
|
/*
|
|
|
|
* Do a lookup in the current namespace stack. Must find a qualified
|
|
|
|
* reference, else ignore.
|
|
|
|
*/
|
|
|
|
ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
|
2009-11-12 01:13:00 +01:00
|
|
|
word1, word2, word3,
|
2009-11-10 03:13:13 +01:00
|
|
|
&nnames);
|
|
|
|
if (ns != NULL && nnames == 2)
|
|
|
|
{
|
|
|
|
switch (ns->itemtype)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2009-11-10 03:13:13 +01:00
|
|
|
case PLPGSQL_NSTYPE_REC:
|
2010-02-26 03:01:40 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* words 1/2 are a record name, so third word could be
|
|
|
|
* a field in this record.
|
|
|
|
*/
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
PLpgSQL_rec *rec;
|
2010-02-26 03:01:40 +01:00
|
|
|
PLpgSQL_recfield *new;
|
2009-11-10 03:13:13 +01:00
|
|
|
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
|
|
|
|
new = plpgsql_build_recfield(rec, word3);
|
2009-11-10 03:13:13 +01:00
|
|
|
|
2010-02-26 03:01:40 +01:00
|
|
|
wdatum->datum = (PLpgSQL_datum *) new;
|
|
|
|
wdatum->ident = NULL;
|
|
|
|
wdatum->quoted = false; /* not used */
|
|
|
|
wdatum->idents = idents;
|
|
|
|
return true;
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-10 03:13:13 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2009-11-10 03:13:13 +01:00
|
|
|
/* Nothing found */
|
2009-11-12 01:13:00 +01:00
|
|
|
cword->idents = idents;
|
|
|
|
return false;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* plpgsql_parse_wordtype The scanner found word%TYPE. word can be
|
|
|
|
* a variable name or a basetype.
|
2009-11-07 01:52:26 +01:00
|
|
|
*
|
|
|
|
* Returns datatype struct, or NULL if no match found for word.
|
1998-08-22 14:38:39 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-07 01:52:26 +01:00
|
|
|
PLpgSQL_type *
|
2009-11-10 03:13:13 +01:00
|
|
|
plpgsql_parse_wordtype(char *ident)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
2009-11-07 01:52:26 +01:00
|
|
|
PLpgSQL_type *dtype;
|
1998-09-01 06:40:42 +02:00
|
|
|
PLpgSQL_nsitem *nse;
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
TypeName *typeName;
|
2007-11-11 20:22:49 +01:00
|
|
|
HeapTuple typeTup;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2009-11-07 01:52:26 +01:00
|
|
|
* Do a lookup in the current namespace stack
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
2009-11-07 01:52:26 +01:00
|
|
|
nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
|
2009-11-10 03:13:13 +01:00
|
|
|
ident, NULL, NULL,
|
2009-11-06 19:37:55 +01:00
|
|
|
NULL);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
|
|
|
if (nse != NULL)
|
|
|
|
{
|
|
|
|
switch (nse->itemtype)
|
|
|
|
{
|
|
|
|
case PLPGSQL_NSTYPE_VAR:
|
2009-11-07 01:52:26 +01:00
|
|
|
return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-07 01:52:26 +01:00
|
|
|
/* XXX perhaps allow REC/ROW here? */
|
2004-06-04 00:56:43 +02:00
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
default:
|
2009-11-07 01:52:26 +01:00
|
|
|
return NULL;
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* Word wasn't found in the namespace stack. Try to find a data type with
|
|
|
|
* that name, but ignore shell types and complex types.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
typeName = makeTypeName(ident);
|
|
|
|
typeTup = LookupTypeName(NULL, typeName, NULL, false);
|
2007-11-11 20:22:49 +01:00
|
|
|
if (typeTup)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2007-11-11 20:22:49 +01:00
|
|
|
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2007-11-11 20:22:49 +01:00
|
|
|
if (!typeStruct->typisdefined ||
|
|
|
|
typeStruct->typrelid != InvalidOid)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2002-03-29 20:06:29 +01:00
|
|
|
ReleaseSysCache(typeTup);
|
2009-11-07 01:52:26 +01:00
|
|
|
return NULL;
|
2002-03-29 20:06:29 +01:00
|
|
|
}
|
2007-11-11 20:22:49 +01:00
|
|
|
|
2011-03-25 20:06:36 +01:00
|
|
|
dtype = build_datatype(typeTup, -1,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
plpgsql_curr_compile->fn_input_collation,
|
|
|
|
typeName);
|
2007-11-11 20:22:49 +01:00
|
|
|
|
|
|
|
ReleaseSysCache(typeTup);
|
2009-11-07 01:52:26 +01:00
|
|
|
return dtype;
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Nothing found - up to now it's a word without any special meaning for
|
|
|
|
* us.
|
1998-09-01 06:40:42 +02:00
|
|
|
*/
|
2009-11-07 01:52:26 +01:00
|
|
|
return NULL;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
2009-11-10 03:13:13 +01:00
|
|
|
* plpgsql_parse_cwordtype Same lookup for compositeword%TYPE
|
1998-08-22 14:38:39 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-07 01:52:26 +01:00
|
|
|
PLpgSQL_type *
|
2009-11-10 03:13:13 +01:00
|
|
|
plpgsql_parse_cwordtype(List *idents)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
2009-11-07 01:52:26 +01:00
|
|
|
PLpgSQL_type *dtype = NULL;
|
1998-09-01 06:40:42 +02:00
|
|
|
PLpgSQL_nsitem *nse;
|
2009-11-10 03:13:13 +01:00
|
|
|
const char *fldname;
|
2002-03-26 20:17:02 +01:00
|
|
|
Oid classOid;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
HeapTuple classtup = NULL;
|
|
|
|
HeapTuple attrtup = NULL;
|
|
|
|
HeapTuple typetup = NULL;
|
1998-09-01 06:40:42 +02:00
|
|
|
Form_pg_class classStruct;
|
|
|
|
Form_pg_attribute attrStruct;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
MemoryContext oldCxt;
|
|
|
|
|
|
|
|
/* Avoid memory leaks in the long-term function context */
|
2016-03-03 10:45:59 +01:00
|
|
|
oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-10 03:13:13 +01:00
|
|
|
if (list_length(idents) == 2)
|
|
|
|
{
|
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* Do a lookup in the current namespace stack. We don't need to check
|
|
|
|
* number of names matched, because we will only consider scalar
|
|
|
|
* variables.
|
2009-11-10 03:13:13 +01:00
|
|
|
*/
|
|
|
|
nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
|
|
|
|
strVal(linitial(idents)),
|
|
|
|
strVal(lsecond(idents)),
|
|
|
|
NULL,
|
|
|
|
NULL);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-10 03:13:13 +01:00
|
|
|
if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
|
|
|
|
{
|
|
|
|
dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
|
|
|
|
goto done;
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2009-11-10 03:13:13 +01:00
|
|
|
/*
|
|
|
|
* First word could also be a table name
|
|
|
|
*/
|
|
|
|
classOid = RelnameGetRelid(strVal(linitial(idents)));
|
|
|
|
if (!OidIsValid(classOid))
|
|
|
|
goto done;
|
|
|
|
fldname = strVal(lsecond(idents));
|
|
|
|
}
|
|
|
|
else if (list_length(idents) == 3)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2009-11-10 03:13:13 +01:00
|
|
|
RangeVar *relvar;
|
|
|
|
|
|
|
|
relvar = makeRangeVar(strVal(linitial(idents)),
|
|
|
|
strVal(lsecond(idents)),
|
|
|
|
-1);
|
2011-07-09 04:19:30 +02:00
|
|
|
/* Can't lock relation - we might not have privileges. */
|
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
|
|
|
classOid = RangeVarGetRelid(relvar, NoLock, true);
|
2009-11-10 03:13:13 +01:00
|
|
|
if (!OidIsValid(classOid))
|
|
|
|
goto done;
|
|
|
|
fldname = strVal(lthird(idents));
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
2009-11-10 03:13:13 +01:00
|
|
|
else
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
goto done;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
|
2002-09-12 02:24:10 +02:00
|
|
|
if (!HeapTupleIsValid(classtup))
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
goto done;
|
2005-12-09 18:08:49 +01:00
|
|
|
classStruct = (Form_pg_class) GETSTRUCT(classtup);
|
2002-09-12 02:24:10 +02:00
|
|
|
|
|
|
|
/*
|
2013-03-04 01:23:31 +01:00
|
|
|
* It must be a relation, sequence, view, materialized view, composite
|
|
|
|
* type, or foreign table
|
2002-09-12 02:24:10 +02:00
|
|
|
*/
|
|
|
|
if (classStruct->relkind != RELKIND_RELATION &&
|
|
|
|
classStruct->relkind != RELKIND_SEQUENCE &&
|
|
|
|
classStruct->relkind != RELKIND_VIEW &&
|
2013-03-04 01:23:31 +01:00
|
|
|
classStruct->relkind != RELKIND_MATVIEW &&
|
2011-11-13 00:49:09 +01:00
|
|
|
classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
|
2017-06-14 10:00:01 +02:00
|
|
|
classStruct->relkind != RELKIND_FOREIGN_TABLE &&
|
|
|
|
classStruct->relkind != RELKIND_PARTITIONED_TABLE)
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
goto done;
|
2002-09-12 02:24:10 +02:00
|
|
|
|
|
|
|
/*
|
2005-12-09 18:08:49 +01:00
|
|
|
* Fetch the named table field and its type
|
2002-09-12 02:24:10 +02:00
|
|
|
*/
|
2009-11-10 03:13:13 +01:00
|
|
|
attrtup = SearchSysCacheAttName(classOid, fldname);
|
2002-09-12 02:24:10 +02:00
|
|
|
if (!HeapTupleIsValid(attrtup))
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
goto done;
|
|
|
|
attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
|
2005-12-09 18:08:49 +01:00
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
typetup = SearchSysCache1(TYPEOID,
|
|
|
|
ObjectIdGetDatum(attrStruct->atttypid));
|
2002-09-12 02:24:10 +02:00
|
|
|
if (!HeapTupleIsValid(typetup))
|
2003-07-26 01:37:31 +02:00
|
|
|
elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
|
2002-09-12 02:24:10 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Found that - build a compiler type struct in the caller's cxt and
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
* return it. Note that we treat the type as being found-by-OID; no
|
|
|
|
* attempt to re-look-up the type name will happen during invalidations.
|
2002-09-12 02:24:10 +02:00
|
|
|
*/
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
MemoryContextSwitchTo(oldCxt);
|
2011-03-25 20:06:36 +01:00
|
|
|
dtype = build_datatype(typetup,
|
|
|
|
attrStruct->atttypmod,
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
attrStruct->attcollation,
|
|
|
|
NULL);
|
2016-03-03 10:45:59 +01:00
|
|
|
MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
|
2002-09-12 02:24:10 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
done:
|
|
|
|
if (HeapTupleIsValid(classtup))
|
|
|
|
ReleaseSysCache(classtup);
|
2005-12-09 18:08:49 +01:00
|
|
|
if (HeapTupleIsValid(attrtup))
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
ReleaseSysCache(attrtup);
|
|
|
|
if (HeapTupleIsValid(typetup))
|
|
|
|
ReleaseSysCache(typetup);
|
2004-06-04 00:56:43 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
MemoryContextSwitchTo(oldCxt);
|
2009-11-07 01:52:26 +01:00
|
|
|
return dtype;
|
2002-09-12 02:24:10 +02:00
|
|
|
}
|
1998-08-22 14:38:39 +02:00
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
|
|
|
|
* So word must be a table name.
|
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-07 01:52:26 +01:00
|
|
|
PLpgSQL_type *
|
2009-11-10 03:13:13 +01:00
|
|
|
plpgsql_parse_wordrowtype(char *ident)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
2002-03-26 20:17:02 +01:00
|
|
|
Oid classOid;
|
2002-08-12 16:25:07 +02:00
|
|
|
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
/*
|
|
|
|
* Look up the relation. Note that because relation rowtypes have the
|
|
|
|
* same names as their relations, this could be handled as a type lookup
|
|
|
|
* equally well; we use the relation lookup code path only because the
|
|
|
|
* errors thrown here have traditionally referred to relations not types.
|
|
|
|
* But we'll make a TypeName in case we have to do re-look-up of the type.
|
|
|
|
*/
|
2009-11-10 03:13:13 +01:00
|
|
|
classOid = RelnameGetRelid(ident);
|
2002-08-12 16:25:07 +02:00
|
|
|
if (!OidIsValid(classOid))
|
2003-07-26 01:37:31 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_TABLE),
|
2009-11-10 03:13:13 +01:00
|
|
|
errmsg("relation \"%s\" does not exist", ident)));
|
2002-08-12 16:25:07 +02:00
|
|
|
|
2009-11-07 01:52:26 +01:00
|
|
|
/* Build and return the row type struct */
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
|
|
|
|
makeTypeName(ident));
|
2002-08-12 16:25:07 +02:00
|
|
|
}
|
|
|
|
|
2002-09-12 02:24:10 +02:00
|
|
|
/* ----------
|
2009-11-10 03:13:13 +01:00
|
|
|
* plpgsql_parse_cwordrowtype Scanner found compositeword%ROWTYPE.
|
2004-06-04 00:56:43 +02:00
|
|
|
* So word must be a namespace qualified table name.
|
2002-09-12 02:24:10 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2009-11-07 01:52:26 +01:00
|
|
|
PLpgSQL_type *
|
2009-11-10 03:13:13 +01:00
|
|
|
plpgsql_parse_cwordrowtype(List *idents)
|
2002-09-12 02:24:10 +02:00
|
|
|
{
|
|
|
|
Oid classOid;
|
|
|
|
RangeVar *relvar;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
MemoryContext oldCxt;
|
|
|
|
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
/*
|
|
|
|
* As above, this is a relation lookup but could be a type lookup if we
|
|
|
|
* weren't being backwards-compatible about error wording.
|
|
|
|
*/
|
2009-11-10 03:13:13 +01:00
|
|
|
if (list_length(idents) != 2)
|
|
|
|
return NULL;
|
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Avoid memory leaks in long-term function context */
|
2016-03-03 10:45:59 +01:00
|
|
|
oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
|
2002-09-12 02:24:10 +02:00
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
/* Look up relation name. Can't lock it - we might not have privileges. */
|
2009-11-10 03:13:13 +01:00
|
|
|
relvar = makeRangeVar(strVal(linitial(idents)),
|
|
|
|
strVal(lsecond(idents)),
|
|
|
|
-1);
|
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
|
|
|
classOid = RangeVarGetRelid(relvar, NoLock, false);
|
2002-09-12 02:24:10 +02:00
|
|
|
|
2009-11-07 01:52:26 +01:00
|
|
|
MemoryContextSwitchTo(oldCxt);
|
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* Build and return the row type struct */
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
|
|
|
|
makeTypeNameFromNameList(idents));
|
2002-09-12 02:24:10 +02:00
|
|
|
}
|
|
|
|
|
2002-08-12 16:25:07 +02:00
|
|
|
/*
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
* plpgsql_build_variable - build a datum-array entry of a given
|
|
|
|
* datatype
|
2004-06-04 00:56:43 +02:00
|
|
|
*
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
* The returned struct may be a PLpgSQL_var or PLpgSQL_rec
|
|
|
|
* depending on the given datatype, and is allocated via
|
2014-05-06 18:12:18 +02:00
|
|
|
* palloc. The struct is automatically added to the current datum
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
* array, and optionally to the current namespace.
|
2002-08-12 16:25:07 +02:00
|
|
|
*/
|
2004-06-04 00:56:43 +02:00
|
|
|
PLpgSQL_variable *
|
2005-11-22 19:17:34 +01:00
|
|
|
plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
|
2004-08-29 07:07:03 +02:00
|
|
|
bool add2namespace)
|
2004-06-04 00:56:43 +02:00
|
|
|
{
|
|
|
|
PLpgSQL_variable *result;
|
|
|
|
|
|
|
|
switch (dtype->ttype)
|
|
|
|
{
|
|
|
|
case PLPGSQL_TTYPE_SCALAR:
|
2004-08-29 07:07:03 +02:00
|
|
|
{
|
|
|
|
/* Ordinary scalar datatype */
|
|
|
|
PLpgSQL_var *var;
|
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
var = palloc0(sizeof(PLpgSQL_var));
|
2004-08-29 07:07:03 +02:00
|
|
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
var->refname = pstrdup(refname);
|
2004-08-29 07:07:03 +02:00
|
|
|
var->lineno = lineno;
|
|
|
|
var->datatype = dtype;
|
2018-02-14 04:15:08 +01:00
|
|
|
/* other fields are left as 0, might be changed by caller */
|
2004-08-29 07:07:03 +02:00
|
|
|
|
|
|
|
/* preset to NULL */
|
|
|
|
var->value = 0;
|
|
|
|
var->isnull = true;
|
|
|
|
var->freeval = false;
|
|
|
|
|
|
|
|
plpgsql_adddatum((PLpgSQL_datum *) var);
|
|
|
|
if (add2namespace)
|
|
|
|
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
|
2008-11-05 01:07:54 +01:00
|
|
|
var->dno,
|
2004-08-29 07:07:03 +02:00
|
|
|
refname);
|
|
|
|
result = (PLpgSQL_variable *) var;
|
|
|
|
break;
|
|
|
|
}
|
2004-06-04 00:56:43 +02:00
|
|
|
case PLPGSQL_TTYPE_REC:
|
2004-08-29 07:07:03 +02:00
|
|
|
{
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
/* Composite type -- build a record variable */
|
2004-08-29 07:07:03 +02:00
|
|
|
PLpgSQL_rec *rec;
|
2004-06-04 00:56:43 +02:00
|
|
|
|
2018-02-14 04:15:08 +01:00
|
|
|
rec = plpgsql_build_record(refname, lineno,
|
|
|
|
dtype, dtype->typoid,
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
add2namespace);
|
2004-08-29 07:07:03 +02:00
|
|
|
result = (PLpgSQL_variable *) rec;
|
|
|
|
break;
|
|
|
|
}
|
2004-06-04 00:56:43 +02:00
|
|
|
case PLPGSQL_TTYPE_PSEUDO:
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("variable \"%s\" has pseudo-type %s",
|
|
|
|
refname, format_type_be(dtype->typoid))));
|
2005-10-15 04:49:52 +02:00
|
|
|
result = NULL; /* keep compiler quiet */
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
break;
|
2004-06-04 00:56:43 +02:00
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
|
|
|
|
result = NULL; /* keep compiler quiet */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-04-07 01:43:29 +02:00
|
|
|
/*
|
|
|
|
* Build empty named record variable, and optionally add it to namespace
|
|
|
|
*/
|
|
|
|
PLpgSQL_rec *
|
2018-02-14 04:15:08 +01:00
|
|
|
plpgsql_build_record(const char *refname, int lineno,
|
|
|
|
PLpgSQL_type *dtype, Oid rectypeid,
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
bool add2namespace)
|
2008-04-07 01:43:29 +02:00
|
|
|
{
|
|
|
|
PLpgSQL_rec *rec;
|
|
|
|
|
|
|
|
rec = palloc0(sizeof(PLpgSQL_rec));
|
|
|
|
rec->dtype = PLPGSQL_DTYPE_REC;
|
|
|
|
rec->refname = pstrdup(refname);
|
|
|
|
rec->lineno = lineno;
|
2018-02-14 04:15:08 +01:00
|
|
|
/* other fields are left as 0, might be changed by caller */
|
|
|
|
rec->datatype = dtype;
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
rec->rectypeid = rectypeid;
|
|
|
|
rec->firstfield = -1;
|
|
|
|
rec->erh = NULL;
|
2008-04-07 01:43:29 +02:00
|
|
|
plpgsql_adddatum((PLpgSQL_datum *) rec);
|
|
|
|
if (add2namespace)
|
2008-11-05 01:07:54 +01:00
|
|
|
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->dno, rec->refname);
|
2008-04-07 01:43:29 +02:00
|
|
|
|
|
|
|
return rec;
|
|
|
|
}
|
|
|
|
|
2005-04-05 08:22:17 +02:00
|
|
|
/*
|
|
|
|
* Build a row-variable data structure given the component variables.
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
* Include a rowtupdesc, since we will need to materialize the row result.
|
2005-04-05 08:22:17 +02:00
|
|
|
*/
|
|
|
|
static PLpgSQL_row *
|
2005-11-22 19:17:34 +01:00
|
|
|
build_row_from_vars(PLpgSQL_variable **vars, int numvars)
|
2005-04-05 08:22:17 +02:00
|
|
|
{
|
|
|
|
PLpgSQL_row *row;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
row = palloc0(sizeof(PLpgSQL_row));
|
|
|
|
row->dtype = PLPGSQL_DTYPE_ROW;
|
2018-10-05 18:45:37 +02:00
|
|
|
row->refname = "(unnamed row)";
|
|
|
|
row->lineno = -1;
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
row->rowtupdesc = CreateTemplateTupleDesc(numvars);
|
2005-04-05 08:22:17 +02:00
|
|
|
row->nfields = numvars;
|
|
|
|
row->fieldnames = palloc(numvars * sizeof(char *));
|
|
|
|
row->varnos = palloc(numvars * sizeof(int));
|
|
|
|
|
|
|
|
for (i = 0; i < numvars; i++)
|
|
|
|
{
|
|
|
|
PLpgSQL_variable *var = vars[i];
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
Oid typoid;
|
|
|
|
int32 typmod;
|
|
|
|
Oid typcoll;
|
2005-04-05 08:22:17 +02:00
|
|
|
|
2018-02-14 04:15:08 +01:00
|
|
|
/* Member vars of a row should never be const */
|
|
|
|
Assert(!var->isconst);
|
|
|
|
|
2005-04-05 08:22:17 +02:00
|
|
|
switch (var->dtype)
|
|
|
|
{
|
|
|
|
case PLPGSQL_DTYPE_VAR:
|
2018-02-14 01:20:37 +01:00
|
|
|
case PLPGSQL_DTYPE_PROMISE:
|
2005-04-05 08:22:17 +02:00
|
|
|
typoid = ((PLpgSQL_var *) var)->datatype->typoid;
|
|
|
|
typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
|
2011-03-26 23:28:40 +01:00
|
|
|
typcoll = ((PLpgSQL_var *) var)->datatype->collation;
|
2005-04-05 08:22:17 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PLPGSQL_DTYPE_REC:
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
/* shouldn't need to revalidate rectypeid already... */
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
typoid = ((PLpgSQL_rec *) var)->rectypeid;
|
|
|
|
typmod = -1; /* don't know typmod, if it's used at all */
|
|
|
|
typcoll = InvalidOid; /* composite types have no collation */
|
2005-04-05 08:22:17 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized dtype: %d", var->dtype);
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
typoid = InvalidOid; /* keep compiler quiet */
|
|
|
|
typmod = 0;
|
|
|
|
typcoll = InvalidOid;
|
|
|
|
break;
|
2005-04-05 08:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
row->fieldnames[i] = var->refname;
|
|
|
|
row->varnos[i] = var->dno;
|
|
|
|
|
2005-10-15 04:49:52 +02:00
|
|
|
TupleDescInitEntry(row->rowtupdesc, i + 1,
|
2005-04-05 08:22:17 +02:00
|
|
|
var->refname,
|
|
|
|
typoid, typmod,
|
|
|
|
0);
|
2011-03-26 23:28:40 +01:00
|
|
|
TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
|
2005-04-05 08:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return row;
|
|
|
|
}
|
|
|
|
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
/*
|
|
|
|
* Build a RECFIELD datum for the named field of the specified record variable
|
|
|
|
*
|
|
|
|
* If there's already such a datum, just return it; we don't need duplicates.
|
|
|
|
*/
|
|
|
|
PLpgSQL_recfield *
|
|
|
|
plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
|
|
|
|
{
|
|
|
|
PLpgSQL_recfield *recfield;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* search for an existing datum referencing this field */
|
|
|
|
i = rec->firstfield;
|
|
|
|
while (i >= 0)
|
|
|
|
{
|
|
|
|
PLpgSQL_recfield *fld = (PLpgSQL_recfield *) plpgsql_Datums[i];
|
|
|
|
|
|
|
|
Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
|
|
|
|
fld->recparentno == rec->dno);
|
|
|
|
if (strcmp(fld->fieldname, fldname) == 0)
|
|
|
|
return fld;
|
|
|
|
i = fld->nextfield;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* nope, so make a new one */
|
|
|
|
recfield = palloc0(sizeof(PLpgSQL_recfield));
|
|
|
|
recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
|
|
|
|
recfield->fieldname = pstrdup(fldname);
|
|
|
|
recfield->recparentno = rec->dno;
|
|
|
|
recfield->rectupledescid = INVALID_TUPLEDESC_IDENTIFIER;
|
|
|
|
|
|
|
|
plpgsql_adddatum((PLpgSQL_datum *) recfield);
|
|
|
|
|
|
|
|
/* now we can link it into the parent's chain */
|
|
|
|
recfield->nextfield = rec->firstfield;
|
|
|
|
rec->firstfield = recfield->dno;
|
|
|
|
|
|
|
|
return recfield;
|
|
|
|
}
|
|
|
|
|
2004-06-04 00:56:43 +02:00
|
|
|
/*
|
|
|
|
* plpgsql_build_datatype
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
* Build PLpgSQL_type struct given type OID, typmod, collation,
|
|
|
|
* and type's parsed name.
|
2011-03-25 20:06:36 +01:00
|
|
|
*
|
|
|
|
* If collation is not InvalidOid then it overrides the type's default
|
|
|
|
* collation. But collation is ignored if the datatype is non-collatable.
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
*
|
|
|
|
* origtypname is the parsed form of what the user wrote as the type name.
|
|
|
|
* It can be NULL if the type could not be a composite type, or if it was
|
|
|
|
* identified by OID to begin with (e.g., it's a function argument type).
|
2004-06-04 00:56:43 +02:00
|
|
|
*/
|
|
|
|
PLpgSQL_type *
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
plpgsql_build_datatype(Oid typeOid, int32 typmod,
|
|
|
|
Oid collation, TypeName *origtypname)
|
2004-06-04 00:56:43 +02:00
|
|
|
{
|
|
|
|
HeapTuple typeTup;
|
|
|
|
PLpgSQL_type *typ;
|
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
|
2001-10-09 06:15:38 +02:00
|
|
|
if (!HeapTupleIsValid(typeTup))
|
2004-06-04 00:56:43 +02:00
|
|
|
elog(ERROR, "cache lookup failed for type %u", typeOid);
|
2003-04-28 00:21:22 +02:00
|
|
|
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
typ = build_datatype(typeTup, typmod, collation, origtypname);
|
2003-04-28 00:21:22 +02:00
|
|
|
|
|
|
|
ReleaseSysCache(typeTup);
|
|
|
|
|
|
|
|
return typ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
* and additional details (see comments for plpgsql_build_datatype).
|
2003-04-28 00:21:22 +02:00
|
|
|
*/
|
|
|
|
static PLpgSQL_type *
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
build_datatype(HeapTuple typeTup, int32 typmod,
|
|
|
|
Oid collation, TypeName *origtypname)
|
2003-04-28 00:21:22 +02:00
|
|
|
{
|
|
|
|
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
|
|
|
PLpgSQL_type *typ;
|
2001-10-09 06:15:38 +02:00
|
|
|
|
2004-06-04 00:56:43 +02:00
|
|
|
if (!typeStruct->typisdefined)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("type \"%s\" is only a shell",
|
|
|
|
NameStr(typeStruct->typname))));
|
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
|
2001-10-09 06:15:38 +02:00
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
typ->typname = pstrdup(NameStr(typeStruct->typname));
|
Remove WITH OIDS support, change oid catalog column visibility.
Previously tables declared WITH OIDS, including a significant fraction
of the catalog tables, stored the oid column not as a normal column,
but as part of the tuple header.
This special column was not shown by default, which was somewhat odd,
as it's often (consider e.g. pg_class.oid) one of the more important
parts of a row. Neither pg_dump nor COPY included the contents of the
oid column by default.
The fact that the oid column was not an ordinary column necessitated a
significant amount of special case code to support oid columns. That
already was painful for the existing, but upcoming work aiming to make
table storage pluggable, would have required expanding and duplicating
that "specialness" significantly.
WITH OIDS has been deprecated since 2005 (commit ff02d0a05280e0).
Remove it.
Removing includes:
- CREATE TABLE and ALTER TABLE syntax for declaring the table to be
WITH OIDS has been removed (WITH (oids[ = true]) will error out)
- pg_dump does not support dumping tables declared WITH OIDS and will
issue a warning when dumping one (and ignore the oid column).
- restoring an pg_dump archive with pg_restore will warn when
restoring a table with oid contents (and ignore the oid column)
- COPY will refuse to load binary dump that includes oids.
- pg_upgrade will error out when encountering tables declared WITH
OIDS, they have to be altered to remove the oid column first.
- Functionality to access the oid of the last inserted row (like
plpgsql's RESULT_OID, spi's SPI_lastoid, ...) has been removed.
The syntax for declaring a table WITHOUT OIDS (or WITH (oids = false)
for CREATE TABLE) is still supported. While that requires a bit of
support code, it seems unnecessary to break applications / dumps that
do not use oids, and are explicit about not using them.
The biggest user of WITH OID columns was postgres' catalog. This
commit changes all 'magic' oid columns to be columns that are normally
declared and stored. To reduce unnecessary query breakage all the
newly added columns are still named 'oid', even if a table's column
naming scheme would indicate 'reloid' or such. This obviously
requires adapting a lot code, mostly replacing oid access via
HeapTupleGetOid() with access to the underlying Form_pg_*->oid column.
The bootstrap process now assigns oids for all oid columns in
genbki.pl that do not have an explicit value (starting at the largest
oid previously used), only oids assigned later by oids will be above
FirstBootstrapObjectId. As the oid column now is a normal column the
special bootstrap syntax for oids has been removed.
Oids are not automatically assigned during insertion anymore, all
backend code explicitly assigns oids with GetNewOidWithIndex(). For
the rare case that insertions into the catalog via SQL are called for
the new pg_nextoid() function can be used (which only works on catalog
tables).
The fact that oid columns on system tables are now normal columns
means that they will be included in the set of columns expanded
by * (i.e. SELECT * FROM pg_class will now include the table's oid,
previously it did not). It'd not technically be hard to hide oid
column by default, but that'd mean confusing behavior would either
have to be carried forward forever, or it'd cause breakage down the
line.
While it's not unlikely that further adjustments are needed, the
scope/invasiveness of the patch makes it worthwhile to get merge this
now. It's painful to maintain externally, too complicated to commit
after the code code freeze, and a dependency of a number of other
patches.
Catversion bump, for obvious reasons.
Author: Andres Freund, with contributions by John Naylor
Discussion: https://postgr.es/m/20180930034810.ywp2c7awz7opzcfr@alap3.anarazel.de
2018-11-21 00:36:57 +01:00
|
|
|
typ->typoid = typeStruct->oid;
|
2004-06-04 00:56:43 +02:00
|
|
|
switch (typeStruct->typtype)
|
|
|
|
{
|
2007-04-02 05:49:42 +02:00
|
|
|
case TYPTYPE_BASE:
|
|
|
|
case TYPTYPE_ENUM:
|
2011-11-03 12:16:28 +01:00
|
|
|
case TYPTYPE_RANGE:
|
2004-06-04 00:56:43 +02:00
|
|
|
typ->ttype = PLPGSQL_TTYPE_SCALAR;
|
|
|
|
break;
|
2007-04-02 05:49:42 +02:00
|
|
|
case TYPTYPE_COMPOSITE:
|
Make plpgsql use its DTYPE_REC code paths for composite-type variables.
Formerly, DTYPE_REC was used only for variables declared as "record";
variables of named composite types used DTYPE_ROW, which is faster for
some purposes but much less flexible. In particular, the ROW code paths
are entirely incapable of dealing with DDL-caused changes to the number
or data types of the columns of a row variable, once a particular plpgsql
function has been parsed for the first time in a session. And, since the
stored representation of a ROW isn't a tuple, there wasn't any easy way
to deal with variables of domain-over-composite types, since the domain
constraint checking code would expect the value to be checked to be a
tuple. A lesser, but still real, annoyance is that ROW format cannot
represent a true NULL composite value, only a row of per-field NULL
values, which is not exactly the same thing.
Hence, switch to using DTYPE_REC for all composite-typed variables,
whether "record", named composite type, or domain over named composite
type. DTYPE_ROW remains but is used only for its native purpose, to
represent a fixed-at-compile-time list of variables, for instance the
targets of an INTO clause.
To accomplish this without taking significant performance losses, introduce
infrastructure that allows storing composite-type variables as "expanded
objects", similar to the "expanded array" infrastructure introduced in
commit 1dc5ebc90. A composite variable's value is thereby kept (most of
the time) in the form of separate Datums, so that field accesses and
updates are not much more expensive than they were in the ROW format.
This holds the line, more or less, on performance of variables of named
composite types in field-access-intensive microbenchmarks, and makes
variables declared "record" perform much better than before in similar
tests. In addition, the logic involved with enforcing composite-domain
constraints against updates of individual fields is in the expanded
record infrastructure not plpgsql proper, so that it might be reusable
for other purposes.
In further support of this, introduce a typcache feature for assigning a
unique-within-process identifier to each distinct tuple descriptor of
interest; in particular, DDL alterations on composite types result in a new
identifier for that type. This allows very cheap detection of the need to
refresh tupdesc-dependent data. This improves on the "tupDescSeqNo" idea
I had in commit 687f096ea: that assigned identifying sequence numbers to
successive versions of individual composite types, but the numbers were not
unique across different types, nor was there support for assigning numbers
to registered record types.
In passing, allow plpgsql functions to accept as well as return type
"record". There was no good reason for the old restriction, and it
was out of step with most of the other PLs.
Tom Lane, reviewed by Pavel Stehule
Discussion: https://postgr.es/m/8962.1514399547@sss.pgh.pa.us
2018-02-14 00:52:21 +01:00
|
|
|
typ->ttype = PLPGSQL_TTYPE_REC;
|
|
|
|
break;
|
|
|
|
case TYPTYPE_DOMAIN:
|
|
|
|
if (type_is_rowtype(typeStruct->typbasetype))
|
|
|
|
typ->ttype = PLPGSQL_TTYPE_REC;
|
|
|
|
else
|
|
|
|
typ->ttype = PLPGSQL_TTYPE_SCALAR;
|
2004-06-04 00:56:43 +02:00
|
|
|
break;
|
2007-04-02 05:49:42 +02:00
|
|
|
case TYPTYPE_PSEUDO:
|
2004-06-04 00:56:43 +02:00
|
|
|
if (typ->typoid == RECORDOID)
|
|
|
|
typ->ttype = PLPGSQL_TTYPE_REC;
|
|
|
|
else
|
|
|
|
typ->ttype = PLPGSQL_TTYPE_PSEUDO;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized typtype: %d",
|
|
|
|
(int) typeStruct->typtype);
|
|
|
|
break;
|
|
|
|
}
|
2001-10-09 06:15:38 +02:00
|
|
|
typ->typlen = typeStruct->typlen;
|
2003-04-28 00:21:22 +02:00
|
|
|
typ->typbyval = typeStruct->typbyval;
|
Use standard casting mechanism to convert types in plpgsql, when possible.
plpgsql's historical method for converting datatypes during assignments was
to apply the source type's output function and then the destination type's
input function. Aside from being miserably inefficient in most cases, this
method failed outright in many cases where a user might expect it to work;
an example is that "declare x int; ... x := 3.9;" would fail, not round the
value to 4.
Instead, let's convert by applying the appropriate assignment cast whenever
there is one. To avoid breaking compatibility unnecessarily, fall back to
the I/O conversion method if there is no assignment cast.
So far as I can tell, there is just one case where this method produces a
different result than the old code in a case where the old code would not
have thrown an error. That is assignment of a boolean value to a string
variable (type text, varchar, or bpchar); the old way gave boolean's output
representation, ie 't'/'f', while the new way follows the behavior of the
bool-to-text cast and so gives 'true' or 'false'. This will need to be
called out as an incompatibility in the 9.5 release notes.
Aside from handling many conversion cases more sanely, this method is
often significantly faster than the old way. In part that's because
of more effective caching of the conversion info.
2015-03-04 17:04:30 +01:00
|
|
|
typ->typtype = typeStruct->typtype;
|
2011-03-25 20:06:36 +01:00
|
|
|
typ->collation = typeStruct->typcollation;
|
|
|
|
if (OidIsValid(collation) && OidIsValid(typ->collation))
|
|
|
|
typ->collation = collation;
|
Support "expanded" objects, particularly arrays, for better performance.
This patch introduces the ability for complex datatypes to have an
in-memory representation that is different from their on-disk format.
On-disk formats are typically optimized for minimal size, and in any case
they can't contain pointers, so they are often not well-suited for
computation. Now a datatype can invent an "expanded" in-memory format
that is better suited for its operations, and then pass that around among
the C functions that operate on the datatype. There are also provisions
(rudimentary as yet) to allow an expanded object to be modified in-place
under suitable conditions, so that operations like assignment to an element
of an array need not involve copying the entire array.
The initial application for this feature is arrays, but it is not hard
to foresee using it for other container types like JSON, XML and hstore.
I have hopes that it will be useful to PostGIS as well.
In this initial implementation, a few heuristics have been hard-wired
into plpgsql to improve performance for arrays that are stored in
plpgsql variables. We would like to generalize those hacks so that
other datatypes can obtain similar improvements, but figuring out some
appropriate APIs is left as a task for future work. (The heuristics
themselves are probably not optimal yet, either, as they sometimes
force expansion of arrays that would be better left alone.)
Preliminary performance testing shows impressive speed gains for plpgsql
functions that do element-by-element access or update of large arrays.
There are other cases that get a little slower, as a result of added array
format conversions; but we can hope to improve anything that's annoyingly
bad. In any case most applications should see a net win.
Tom Lane, reviewed by Andres Freund
2015-05-14 18:08:40 +02:00
|
|
|
/* Detect if type is true array, or domain thereof */
|
|
|
|
/* NB: this is only used to decide whether to apply expand_array */
|
|
|
|
if (typeStruct->typtype == TYPTYPE_BASE)
|
|
|
|
{
|
2016-08-18 20:48:51 +02:00
|
|
|
/*
|
|
|
|
* This test should include what get_element_type() checks. We also
|
|
|
|
* disallow non-toastable array types (i.e. oidvector and int2vector).
|
|
|
|
*/
|
Support "expanded" objects, particularly arrays, for better performance.
This patch introduces the ability for complex datatypes to have an
in-memory representation that is different from their on-disk format.
On-disk formats are typically optimized for minimal size, and in any case
they can't contain pointers, so they are often not well-suited for
computation. Now a datatype can invent an "expanded" in-memory format
that is better suited for its operations, and then pass that around among
the C functions that operate on the datatype. There are also provisions
(rudimentary as yet) to allow an expanded object to be modified in-place
under suitable conditions, so that operations like assignment to an element
of an array need not involve copying the entire array.
The initial application for this feature is arrays, but it is not hard
to foresee using it for other container types like JSON, XML and hstore.
I have hopes that it will be useful to PostGIS as well.
In this initial implementation, a few heuristics have been hard-wired
into plpgsql to improve performance for arrays that are stored in
plpgsql variables. We would like to generalize those hacks so that
other datatypes can obtain similar improvements, but figuring out some
appropriate APIs is left as a task for future work. (The heuristics
themselves are probably not optimal yet, either, as they sometimes
force expansion of arrays that would be better left alone.)
Preliminary performance testing shows impressive speed gains for plpgsql
functions that do element-by-element access or update of large arrays.
There are other cases that get a little slower, as a result of added array
format conversions; but we can hope to improve anything that's annoyingly
bad. In any case most applications should see a net win.
Tom Lane, reviewed by Andres Freund
2015-05-14 18:08:40 +02:00
|
|
|
typ->typisarray = (typeStruct->typlen == -1 &&
|
2016-08-18 20:48:51 +02:00
|
|
|
OidIsValid(typeStruct->typelem) &&
|
|
|
|
typeStruct->typstorage != 'p');
|
Support "expanded" objects, particularly arrays, for better performance.
This patch introduces the ability for complex datatypes to have an
in-memory representation that is different from their on-disk format.
On-disk formats are typically optimized for minimal size, and in any case
they can't contain pointers, so they are often not well-suited for
computation. Now a datatype can invent an "expanded" in-memory format
that is better suited for its operations, and then pass that around among
the C functions that operate on the datatype. There are also provisions
(rudimentary as yet) to allow an expanded object to be modified in-place
under suitable conditions, so that operations like assignment to an element
of an array need not involve copying the entire array.
The initial application for this feature is arrays, but it is not hard
to foresee using it for other container types like JSON, XML and hstore.
I have hopes that it will be useful to PostGIS as well.
In this initial implementation, a few heuristics have been hard-wired
into plpgsql to improve performance for arrays that are stored in
plpgsql variables. We would like to generalize those hacks so that
other datatypes can obtain similar improvements, but figuring out some
appropriate APIs is left as a task for future work. (The heuristics
themselves are probably not optimal yet, either, as they sometimes
force expansion of arrays that would be better left alone.)
Preliminary performance testing shows impressive speed gains for plpgsql
functions that do element-by-element access or update of large arrays.
There are other cases that get a little slower, as a result of added array
format conversions; but we can hope to improve anything that's annoyingly
bad. In any case most applications should see a net win.
Tom Lane, reviewed by Andres Freund
2015-05-14 18:08:40 +02:00
|
|
|
}
|
|
|
|
else if (typeStruct->typtype == TYPTYPE_DOMAIN)
|
|
|
|
{
|
|
|
|
/* we can short-circuit looking up base types if it's not varlena */
|
|
|
|
typ->typisarray = (typeStruct->typlen == -1 &&
|
2016-08-18 20:48:51 +02:00
|
|
|
typeStruct->typstorage != 'p' &&
|
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
|
|
|
OidIsValid(get_base_element_type(typeStruct->typbasetype)));
|
Support "expanded" objects, particularly arrays, for better performance.
This patch introduces the ability for complex datatypes to have an
in-memory representation that is different from their on-disk format.
On-disk formats are typically optimized for minimal size, and in any case
they can't contain pointers, so they are often not well-suited for
computation. Now a datatype can invent an "expanded" in-memory format
that is better suited for its operations, and then pass that around among
the C functions that operate on the datatype. There are also provisions
(rudimentary as yet) to allow an expanded object to be modified in-place
under suitable conditions, so that operations like assignment to an element
of an array need not involve copying the entire array.
The initial application for this feature is arrays, but it is not hard
to foresee using it for other container types like JSON, XML and hstore.
I have hopes that it will be useful to PostGIS as well.
In this initial implementation, a few heuristics have been hard-wired
into plpgsql to improve performance for arrays that are stored in
plpgsql variables. We would like to generalize those hacks so that
other datatypes can obtain similar improvements, but figuring out some
appropriate APIs is left as a task for future work. (The heuristics
themselves are probably not optimal yet, either, as they sometimes
force expansion of arrays that would be better left alone.)
Preliminary performance testing shows impressive speed gains for plpgsql
functions that do element-by-element access or update of large arrays.
There are other cases that get a little slower, as a result of added array
format conversions; but we can hope to improve anything that's annoyingly
bad. In any case most applications should see a net win.
Tom Lane, reviewed by Andres Freund
2015-05-14 18:08:40 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
typ->typisarray = false;
|
2001-10-09 06:15:38 +02:00
|
|
|
typ->atttypmod = typmod;
|
|
|
|
|
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f5799 rearranged things in plpgsql to make it cope better with
composite types changing underneath it intra-session. However, I failed to
consider the case of a composite type being dropped and recreated entirely.
In my defense, the previous coding didn't consider that possibility at all
either --- but it would accidentally work so long as you didn't change the
type's field list, because the built-at-compile-time list of component
variables would then still match the type's new definition. The new
coding, however, occasionally tries to re-look-up the type by OID, and
then fails to find the dropped type.
To fix this, we need to save the TypeName struct, and then redo the type
OID lookup from that. Of course that's expensive, so we don't want to do
it every time we need the type OID. This can be fixed in the same way that
4b93f5799 dealt with changes to composite types' definitions: keep an eye
on the type's typcache entry to see if its tupledesc has been invalidated.
(Perhaps, at some point, this mechanism should be generalized so it can
work for non-composite types too; but for now, plpgsql only tries to
cope with intra-session redefinitions of composites.)
I'm slightly hesitant to back-patch this into v11, because it changes
the contents of struct PLpgSQL_type as well as the signature of
plpgsql_build_datatype(), so in principle it could break code that is
poking into the innards of plpgsql. However, the only popular extension
of that ilk is pldebugger, and it doesn't seem to be affected. Since
this is a regression for people who were relying on the old behavior,
it seems worth taking the small risk of causing compatibility issues.
Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f5799
came in.
Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
2019-08-15 21:21:47 +02:00
|
|
|
/*
|
|
|
|
* If it's a named composite type (or domain over one), find the typcache
|
|
|
|
* entry and record the current tupdesc ID, so we can detect changes
|
|
|
|
* (including drops). We don't currently support on-the-fly replacement
|
|
|
|
* of non-composite types, else we might want to do this for them too.
|
|
|
|
*/
|
|
|
|
if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
|
|
|
|
{
|
|
|
|
TypeCacheEntry *typentry;
|
|
|
|
|
|
|
|
typentry = lookup_type_cache(typ->typoid,
|
|
|
|
TYPECACHE_TUPDESC |
|
|
|
|
TYPECACHE_DOMAIN_BASE_INFO);
|
|
|
|
if (typentry->typtype == TYPTYPE_DOMAIN)
|
|
|
|
typentry = lookup_type_cache(typentry->domainBaseType,
|
|
|
|
TYPECACHE_TUPDESC);
|
|
|
|
if (typentry->tupDesc == NULL)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
|
|
|
errmsg("type %s is not composite",
|
|
|
|
format_type_be(typ->typoid))));
|
|
|
|
|
|
|
|
typ->origtypname = origtypname;
|
|
|
|
typ->tcache = typentry;
|
|
|
|
typ->tupdesc_id = typentry->tupDesc_identifier;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
typ->origtypname = NULL;
|
|
|
|
typ->tcache = NULL;
|
|
|
|
typ->tupdesc_id = 0;
|
|
|
|
}
|
|
|
|
|
2001-10-09 06:15:38 +02:00
|
|
|
return typ;
|
|
|
|
}
|
|
|
|
|
2008-05-14 00:10:30 +02:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* plpgsql_recognize_err_condition
|
|
|
|
* Check condition name and translate it to SQLSTATE.
|
2008-05-14 00:10:30 +02:00
|
|
|
*
|
|
|
|
* Note: there are some cases where the same condition name has multiple
|
|
|
|
* entries in the table. We arbitrarily return the first match.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (allow_sqlstate)
|
|
|
|
{
|
|
|
|
if (strlen(condname) == 5 &&
|
|
|
|
strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
|
|
|
|
return MAKE_SQLSTATE(condname[0],
|
|
|
|
condname[1],
|
|
|
|
condname[2],
|
|
|
|
condname[3],
|
|
|
|
condname[4]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; exception_label_map[i].label != NULL; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(condname, exception_label_map[i].label) == 0)
|
|
|
|
return exception_label_map[i].sqlerrstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("unrecognized exception condition \"%s\"",
|
|
|
|
condname)));
|
|
|
|
return 0; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
2004-08-21 00:00:14 +02:00
|
|
|
/*
|
|
|
|
* plpgsql_parse_err_condition
|
|
|
|
* Generate PLpgSQL_condition entry(s) for an exception condition name
|
|
|
|
*
|
|
|
|
* This has to be able to return a list because there are some duplicate
|
|
|
|
* names in the table of error code names.
|
|
|
|
*/
|
|
|
|
PLpgSQL_condition *
|
|
|
|
plpgsql_parse_err_condition(char *condname)
|
|
|
|
{
|
|
|
|
int i;
|
2004-08-29 07:07:03 +02:00
|
|
|
PLpgSQL_condition *new;
|
|
|
|
PLpgSQL_condition *prev;
|
2004-08-21 00:00:14 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* XXX Eventually we will want to look for user-defined exception names
|
|
|
|
* here.
|
2004-08-21 00:00:14 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2004-08-29 07:07:03 +02:00
|
|
|
* OTHERS is represented as code 0 (which would map to '00000', but we
|
|
|
|
* have no need to represent that as an exception condition).
|
2004-08-21 00:00:14 +02:00
|
|
|
*/
|
|
|
|
if (strcmp(condname, "others") == 0)
|
|
|
|
{
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
new = palloc(sizeof(PLpgSQL_condition));
|
2004-08-21 00:00:14 +02:00
|
|
|
new->sqlerrstate = 0;
|
|
|
|
new->condname = condname;
|
|
|
|
new->next = NULL;
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = NULL;
|
|
|
|
for (i = 0; exception_label_map[i].label != NULL; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(condname, exception_label_map[i].label) == 0)
|
|
|
|
{
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
new = palloc(sizeof(PLpgSQL_condition));
|
2004-08-21 00:00:14 +02:00
|
|
|
new->sqlerrstate = exception_label_map[i].sqlerrstate;
|
|
|
|
new->condname = condname;
|
|
|
|
new->next = prev;
|
|
|
|
prev = new;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!prev)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
|
|
|
errmsg("unrecognized exception condition \"%s\"",
|
|
|
|
condname)));
|
|
|
|
|
|
|
|
return prev;
|
|
|
|
}
|
2001-10-09 06:15:38 +02:00
|
|
|
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
/* ----------
|
|
|
|
* plpgsql_start_datums Initialize datum list at compile startup.
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
plpgsql_start_datums(void)
|
|
|
|
{
|
|
|
|
datums_alloc = 128;
|
|
|
|
plpgsql_nDatums = 0;
|
|
|
|
/* This is short-lived, so needn't allocate in function's cxt */
|
2016-03-03 10:45:59 +01:00
|
|
|
plpgsql_Datums = MemoryContextAlloc(plpgsql_compile_tmp_cxt,
|
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
|
|
|
sizeof(PLpgSQL_datum *) * datums_alloc);
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
/* datums_last tracks what's been seen by plpgsql_add_initdatums() */
|
|
|
|
datums_last = 0;
|
|
|
|
}
|
|
|
|
|
1998-08-22 14:38:39 +02:00
|
|
|
/* ----------
|
|
|
|
* plpgsql_adddatum Add a variable, record or row
|
2005-06-10 18:23:11 +02:00
|
|
|
* to the compiler's datum list.
|
1998-08-22 14:38:39 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
1998-09-01 06:40:42 +02:00
|
|
|
void
|
2019-05-31 18:34:54 +02:00
|
|
|
plpgsql_adddatum(PLpgSQL_datum *newdatum)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
if (plpgsql_nDatums == datums_alloc)
|
|
|
|
{
|
|
|
|
datums_alloc *= 2;
|
|
|
|
plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
|
|
|
|
}
|
1998-08-22 14:38:39 +02:00
|
|
|
|
2019-05-31 18:34:54 +02:00
|
|
|
newdatum->dno = plpgsql_nDatums;
|
|
|
|
plpgsql_Datums[plpgsql_nDatums++] = newdatum;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
/* ----------
|
|
|
|
* plpgsql_finish_datums Copy completed datum info into function struct.
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
plpgsql_finish_datums(PLpgSQL_function *function)
|
|
|
|
{
|
2018-02-14 01:10:43 +01:00
|
|
|
Size copiable_size = 0;
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
function->ndatums = plpgsql_nDatums;
|
|
|
|
function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
|
|
|
|
for (i = 0; i < plpgsql_nDatums; i++)
|
2018-02-14 01:10:43 +01:00
|
|
|
{
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
function->datums[i] = plpgsql_Datums[i];
|
2018-02-14 01:10:43 +01:00
|
|
|
|
|
|
|
/* This must agree with copy_plpgsql_datums on what is copiable */
|
|
|
|
switch (function->datums[i]->dtype)
|
|
|
|
{
|
|
|
|
case PLPGSQL_DTYPE_VAR:
|
2018-02-14 01:20:37 +01:00
|
|
|
case PLPGSQL_DTYPE_PROMISE:
|
2018-02-14 01:10:43 +01:00
|
|
|
copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
|
|
|
|
break;
|
|
|
|
case PLPGSQL_DTYPE_REC:
|
|
|
|
copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function->copiable_size = copiable_size;
|
Further reduce overhead for passing plpgsql variables to the executor.
This builds on commit 21dcda2713656a7483e3280ac9d2ada20a87a9a9 by keeping
a plpgsql function's shared ParamListInfo's entries for simple variables
(PLPGSQL_DTYPE_VARs) valid at all times. That adds a few cycles to each
assignment to such variables, but saves significantly more cycles each time
they are used; so except in the pathological case of many dead stores, this
should always be a win. Initial testing says it's good for about a 10%
speedup of simple calculations; more in large functions with many datums.
We can't use this method for row/record references unfortunately, so what
we do for those is reset those ParamListInfo slots after use; which we
can skip doing unless some of them were actually evaluated during the
previous evaluation call. So this should frequently be a win as well,
while worst case is that it's similar cost to the previous approach.
Also, closer study suggests that the previous method of instantiating a
new ParamListInfo array per evaluation is actually probably optimal for
cursor-opening executor calls. The reason is that whatever is visible in
the array is going to get copied into the cursor portal via copyParamList.
So if we used the function's main ParamListInfo for those calls, we'd end
up with all of its DTYPE_VAR vars getting copied, which might well include
large pass-by-reference values that the cursor actually has no need for.
To avoid a possible net degradation in cursor cases, go back to creating
and filling a private ParamListInfo in those cases (which therefore will be
exactly the same speed as before 21dcda271365). We still get some benefit
out of this though, because this approach means that we only have to defend
against copyParamList's try-to-fetch-every-slot behavior in the case of an
unshared ParamListInfo; so plpgsql_param_fetch() can skip testing
expr->paramnos in the common case.
To ensure that the main ParamListInfo's image of a DTYPE_VAR datum is
always valid, all assignments to such variables are now funneled through
assign_simple_var(). But this makes for cleaner and shorter code anyway.
2015-07-05 18:57:17 +02:00
|
|
|
}
|
|
|
|
|
1998-08-22 14:38:39 +02:00
|
|
|
|
|
|
|
/* ----------
|
2007-02-08 19:37:14 +01:00
|
|
|
* plpgsql_add_initdatums Make an array of the datum numbers of
|
2017-12-09 18:03:00 +01:00
|
|
|
* all the initializable datums created since the last call
|
2007-02-08 19:37:14 +01:00
|
|
|
* to this function.
|
|
|
|
*
|
|
|
|
* If varnos is NULL, we just forget any datum entries created since the
|
|
|
|
* last call.
|
|
|
|
*
|
2017-12-09 18:03:00 +01:00
|
|
|
* This is used around a DECLARE section to create a list of the datums
|
|
|
|
* that have to be initialized at block entry. Note that datums can also
|
2007-02-08 19:37:14 +01:00
|
|
|
* be created elsewhere than DECLARE, eg by a FOR-loop, but it is then
|
|
|
|
* the responsibility of special-purpose code to initialize them.
|
1998-08-22 14:38:39 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
1998-09-01 06:40:42 +02:00
|
|
|
int
|
|
|
|
plpgsql_add_initdatums(int **varnos)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
int i;
|
|
|
|
int n = 0;
|
|
|
|
|
2017-12-09 18:03:00 +01:00
|
|
|
/*
|
|
|
|
* The set of dtypes recognized here must match what exec_stmt_block()
|
|
|
|
* cares about (re)initializing at block entry.
|
|
|
|
*/
|
1998-09-01 06:40:42 +02:00
|
|
|
for (i = datums_last; i < plpgsql_nDatums; i++)
|
|
|
|
{
|
|
|
|
switch (plpgsql_Datums[i]->dtype)
|
|
|
|
{
|
|
|
|
case PLPGSQL_DTYPE_VAR:
|
2017-12-09 18:03:00 +01:00
|
|
|
case PLPGSQL_DTYPE_REC:
|
1998-09-01 06:40:42 +02:00
|
|
|
n++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
if (varnos != NULL)
|
|
|
|
{
|
2003-08-08 21:19:32 +02:00
|
|
|
if (n > 0)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
*varnos = (int *) palloc(sizeof(int) * n);
|
2003-08-08 21:19:32 +02:00
|
|
|
|
|
|
|
n = 0;
|
|
|
|
for (i = datums_last; i < plpgsql_nDatums; i++)
|
1998-09-01 06:40:42 +02:00
|
|
|
{
|
2003-08-08 21:19:32 +02:00
|
|
|
switch (plpgsql_Datums[i]->dtype)
|
|
|
|
{
|
|
|
|
case PLPGSQL_DTYPE_VAR:
|
2017-12-09 18:03:00 +01:00
|
|
|
case PLPGSQL_DTYPE_REC:
|
2003-08-08 21:19:32 +02:00
|
|
|
(*varnos)[n++] = plpgsql_Datums[i]->dno;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2003-08-08 21:19:32 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
|
|
|
}
|
2003-08-08 21:19:32 +02:00
|
|
|
else
|
|
|
|
*varnos = NULL;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
datums_last = plpgsql_nDatums;
|
|
|
|
return n;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-01 23:47:09 +02:00
|
|
|
/*
|
|
|
|
* Compute the hashkey for a given function invocation
|
|
|
|
*
|
|
|
|
* The hashkey is returned into the caller-provided storage at *hashkey.
|
|
|
|
*/
|
|
|
|
static void
|
2003-08-18 21:16:02 +02:00
|
|
|
compute_function_hashkey(FunctionCallInfo fcinfo,
|
2003-07-01 23:47:09 +02:00
|
|
|
Form_pg_proc procStruct,
|
2005-11-22 19:17:34 +01:00
|
|
|
PLpgSQL_func_hashkey *hashkey,
|
2004-03-19 19:58:07 +01:00
|
|
|
bool forValidator)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
|
|
|
/* Make sure any unused bytes of the struct are zero */
|
|
|
|
MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
|
|
|
|
|
2003-08-18 21:16:02 +02:00
|
|
|
/* get function OID */
|
|
|
|
hashkey->funcOid = fcinfo->flinfo->fn_oid;
|
|
|
|
|
2008-10-09 18:35:07 +02:00
|
|
|
/* get call context */
|
|
|
|
hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
|
|
|
|
|
2004-03-19 19:58:07 +01:00
|
|
|
/*
|
2017-04-01 06:30:08 +02:00
|
|
|
* if trigger, get its OID. In validation mode we do not know what
|
|
|
|
* relation or transition table names are intended to be used, so we leave
|
|
|
|
* trigOid zero; the hash entry built in this case will never really be
|
|
|
|
* used.
|
2004-03-19 19:58:07 +01:00
|
|
|
*/
|
2008-10-09 18:35:07 +02:00
|
|
|
if (hashkey->isTrigger && !forValidator)
|
2003-08-18 21:16:02 +02:00
|
|
|
{
|
|
|
|
TriggerData *trigdata = (TriggerData *) fcinfo->context;
|
|
|
|
|
2017-04-01 06:30:08 +02:00
|
|
|
hashkey->trigOid = trigdata->tg_trigger->tgoid;
|
2003-08-18 21:16:02 +02:00
|
|
|
}
|
2003-07-01 23:47:09 +02:00
|
|
|
|
2011-03-25 20:06:36 +01:00
|
|
|
/* get input collation, if known */
|
2011-04-13 01:19:24 +02:00
|
|
|
hashkey->inputCollation = fcinfo->fncollation;
|
2011-03-25 20:06:36 +01:00
|
|
|
|
2005-04-05 08:22:17 +02:00
|
|
|
if (procStruct->pronargs > 0)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
2005-04-05 08:22:17 +02:00
|
|
|
/* get the argument types */
|
|
|
|
memcpy(hashkey->argtypes, procStruct->proargtypes.values,
|
|
|
|
procStruct->pronargs * sizeof(Oid));
|
|
|
|
|
|
|
|
/* resolve any polymorphic argument types */
|
|
|
|
plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
|
|
|
|
hashkey->argtypes,
|
|
|
|
NULL,
|
|
|
|
fcinfo->flinfo->fn_expr,
|
|
|
|
forValidator,
|
|
|
|
NameStr(procStruct->proname));
|
|
|
|
}
|
|
|
|
}
|
2003-07-01 23:47:09 +02:00
|
|
|
|
2005-04-05 08:22:17 +02:00
|
|
|
/*
|
|
|
|
* This is the same as the standard resolve_polymorphic_argtypes() function,
|
|
|
|
* but with a special case for validation: assume that polymorphic arguments
|
2011-11-21 05:50:27 +01:00
|
|
|
* are integer, integer-array or integer-range. Also, we go ahead and report
|
2011-11-03 12:16:28 +01:00
|
|
|
* the error if we can't resolve the types.
|
2005-04-05 08:22:17 +02:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
plpgsql_resolve_polymorphic_argtypes(int numargs,
|
|
|
|
Oid *argtypes, char *argmodes,
|
|
|
|
Node *call_expr, bool forValidator,
|
|
|
|
const char *proname)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!forValidator)
|
|
|
|
{
|
|
|
|
/* normal case, pass to standard routine */
|
|
|
|
if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
|
|
|
|
call_expr))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
|
|
errmsg("could not determine actual argument "
|
|
|
|
"type for polymorphic function \"%s\"",
|
|
|
|
proname)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* special validation case */
|
|
|
|
for (i = 0; i < numargs; i++)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
2005-04-05 08:22:17 +02:00
|
|
|
switch (argtypes[i])
|
2004-03-19 19:58:07 +01:00
|
|
|
{
|
2005-04-05 08:22:17 +02:00
|
|
|
case ANYELEMENTOID:
|
2007-06-07 01:00:50 +02:00
|
|
|
case ANYNONARRAYOID:
|
2017-06-21 20:39:04 +02:00
|
|
|
case ANYENUMOID: /* XXX dubious */
|
2005-04-05 08:22:17 +02:00
|
|
|
argtypes[i] = INT4OID;
|
|
|
|
break;
|
|
|
|
case ANYARRAYOID:
|
|
|
|
argtypes[i] = INT4ARRAYOID;
|
|
|
|
break;
|
2011-11-21 05:50:27 +01:00
|
|
|
case ANYRANGEOID:
|
|
|
|
argtypes[i] = INT4RANGEOID;
|
|
|
|
break;
|
2005-04-05 08:22:17 +02:00
|
|
|
default:
|
|
|
|
break;
|
2004-03-19 19:58:07 +01:00
|
|
|
}
|
2003-07-01 23:47:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-30 23:05:13 +01:00
|
|
|
/*
|
|
|
|
* delete_function - clean up as much as possible of a stale function cache
|
|
|
|
*
|
|
|
|
* We can't release the PLpgSQL_function struct itself, because of the
|
2014-05-06 18:12:18 +02:00
|
|
|
* possibility that there are fn_extra pointers to it. We can release
|
2007-01-30 23:05:13 +01:00
|
|
|
* the subsidiary storage, but only if there are no active evaluations
|
|
|
|
* in progress. Otherwise we'll just leak that storage. Since the
|
|
|
|
* case would only occur if a pg_proc update is detected during a nested
|
|
|
|
* recursive call on the function, a leak seems acceptable.
|
|
|
|
*
|
|
|
|
* Note that this can be called more than once if there are multiple fn_extra
|
|
|
|
* pointers to the same function cache. Hence be careful not to do things
|
|
|
|
* twice.
|
|
|
|
*/
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
static void
|
2005-11-22 19:17:34 +01:00
|
|
|
delete_function(PLpgSQL_function *func)
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
{
|
2007-01-30 23:05:13 +01:00
|
|
|
/* remove function from hash table (might be done already) */
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
plpgsql_HashTableDelete(func);
|
|
|
|
|
2007-01-30 23:05:13 +01:00
|
|
|
/* release the function's storage if safe and not done already */
|
2011-03-27 18:51:04 +02:00
|
|
|
if (func->use_count == 0)
|
|
|
|
plpgsql_free_function_memory(func);
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
}
|
|
|
|
|
2019-08-05 05:14:58 +02:00
|
|
|
/* exported so we can call it from _PG_init() */
|
2003-07-31 20:36:46 +02:00
|
|
|
void
|
2003-07-01 23:47:09 +02:00
|
|
|
plpgsql_HashTableInit(void)
|
|
|
|
{
|
|
|
|
HASHCTL ctl;
|
|
|
|
|
This patch changes makes some significant changes to how compilation
and parsing work in PL/PgSQL:
- memory management is now done via palloc(). The compiled representation
of each function now has its own memory context. Therefore, the storage
consumed by a function can be reclaimed via MemoryContextDelete().
During compilation, the CurrentMemoryContext is the function's memory
context. This means that a palloc() is sufficient to allocate memory
that will have the same lifetime as the function itself. As a result,
code invoked during compilation should be careful to pfree() temporary
allocations to avoid leaking memory. Since a lot of the code in the
backend is not careful about releasing palloc'ed memory, that means
we should switch into a temporary memory context before invoking
backend functions. A temporary context appropriate for such allocations
is `compile_tmp_cxt'.
- The ability to use palloc() allows us to simply a lot of the code in
the parser. Rather than representing lists of elements via ad hoc
linked lists or arrays, we can use the List type. Rather than doing
malloc followed by memset(0), we can just use palloc0().
- We now check that the user has supplied the right number of parameters
to a RAISE statement. Supplying either too few or too many results in
an error (at runtime).
- PL/PgSQL's parser needs to accept arbitrary SQL statements. Since we
do not want to duplicate the SQL grammar in the PL/PgSQL grammar, this
means we need to be quite lax in what the PL/PgSQL grammar considers
a "SQL statement". This can lead to misleading behavior if there is a
syntax error in the function definition, since we assume a malformed
PL/PgSQL construct is a SQL statement. Furthermore, these errors were
only detected at runtime (when we tried to execute the alleged "SQL
statement" via SPI).
To rectify this, the patch changes the parser to invoke the main SQL
parser when it sees a string it believes to be a SQL expression. This
means that synctically-invalid SQL will be rejected during the
compilation of the PL/PgSQL function. This is only done when compiling
for "validation" purposes (i.e. at CREATE FUNCTION time), so it should
not impose a runtime overhead.
- Fixes for the various buffer overruns I've patched in stable branches
in the past few weeks. I've rewritten code where I thought it was
warranted (unlike the patches applied to older branches, which were
minimally invasive).
- Various other minor changes and cleanups.
- Updates to the regression tests.
2005-02-22 08:18:27 +01:00
|
|
|
/* don't allow double-initialization */
|
|
|
|
Assert(plpgsql_HashTable == NULL);
|
|
|
|
|
2003-07-01 23:47:09 +02:00
|
|
|
memset(&ctl, 0, sizeof(ctl));
|
|
|
|
ctl.keysize = sizeof(PLpgSQL_func_hashkey);
|
|
|
|
ctl.entrysize = sizeof(plpgsql_HashEnt);
|
Allow memory contexts to have both fixed and variable ident strings.
Originally, we treated memory context names as potentially variable in
all cases, and therefore always copied them into the context header.
Commit 9fa6f00b1 rethought this a little bit and invented a distinction
between fixed and variable names, skipping the copy step for the former.
But we can make things both simpler and more useful by instead allowing
there to be two parts to a context's identification, a fixed "name" and
an optional, variable "ident". The name supplied in the context create
call is now required to be a compile-time-constant string in all cases,
as it is never copied but just pointed to. The "ident" string, if
wanted, is supplied later. This is needed because typically we want
the ident to be stored inside the context so that it's cleaned up
automatically on context deletion; that means it has to be copied into
the context before we can set the pointer.
The cost of this approach is basically just an additional pointer field
in struct MemoryContextData, which isn't much overhead, and is bought
back entirely in the AllocSet case by not needing a headerSize field
anymore, since we no longer have to cope with variable header length.
In addition, we can simplify the internal interfaces for memory context
creation still further, saving a few cycles there. And it's no longer
true that a custom identifier disqualifies a context from participating
in aset.c's freelist scheme, so possibly there's some win on that end.
All the places that were using non-compile-time-constant context names
are adjusted to put the variable info into the "ident" instead. This
allows more effective identification of those contexts in many cases;
for example, subsidary contexts of relcache entries are now identified
by both type (e.g. "index info") and relname, where before you got only
one or the other. Contexts associated with PL function cache entries
are now identified more fully and uniformly, too.
I also arranged for plancache contexts to use the query source string
as their identifier. This is basically free for CachedPlanSources, as
they contained a copy of that string already. We pay an extra pstrdup
to do it for CachedPlans. That could perhaps be avoided, but it would
make things more fragile (since the CachedPlanSource is sometimes
destroyed first). I suspect future improvements in error reporting will
require CachedPlans to have a copy of that string anyway, so it's not
clear that it's worth moving mountains to avoid it now.
This also changes the APIs for context statistics routines so that the
context-specific routines no longer assume that output goes straight
to stderr, nor do they know all details of the output format. This
is useful immediately to reduce code duplication, and it also allows
for external code to do something with stats output that's different
from printing to stderr.
The reason for pushing this now rather than waiting for v12 is that
it rethinks some of the API changes made by commit 9fa6f00b1. Seems
better for extension authors to endure just one round of API changes
not two.
Discussion: https://postgr.es/m/CAB=Je-FdtmFZ9y9REHD7VsSrnCkiBhsA4mdsLKSPauwXtQBeNA@mail.gmail.com
2018-03-27 22:46:47 +02:00
|
|
|
plpgsql_HashTable = hash_create("PLpgSQL function hash",
|
2003-07-01 23:47:09 +02:00
|
|
|
FUNCS_PER_USER,
|
|
|
|
&ctl,
|
Improve hash_create's API for selecting simple-binary-key hash functions.
Previously, if you wanted anything besides C-string hash keys, you had to
specify a custom hashing function to hash_create(). Nearly all such
callers were specifying tag_hash or oid_hash; which is tedious, and rather
error-prone, since a caller could easily miss the opportunity to optimize
by using hash_uint32 when appropriate. Replace this with a design whereby
callers using simple binary-data keys just specify HASH_BLOBS and don't
need to mess with specific support functions. hash_create() itself will
take care of optimizing when the key size is four bytes.
This nets out saving a few hundred bytes of code space, and offers
a measurable performance improvement in tidbitmap.c (which was not
exploiting the opportunity to use hash_uint32 for its 4-byte keys).
There might be some wins elsewhere too, I didn't analyze closely.
In future we could look into offering a similar optimized hashing function
for 8-byte keys. Under this design that could be done in a centralized
and machine-independent fashion, whereas getting it right for keys of
platform-dependent sizes would've been notationally painful before.
For the moment, the old way still works fine, so as not to break source
code compatibility for loadable modules. Eventually we might want to
remove tag_hash and friends from the exported API altogether, since there's
no real need for them to be explicitly referenced from outside dynahash.c.
Teodor Sigaev and Tom Lane
2014-12-18 19:36:29 +01:00
|
|
|
HASH_ELEM | HASH_BLOBS);
|
2003-07-01 23:47:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static PLpgSQL_function *
|
2005-11-22 19:17:34 +01:00
|
|
|
plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
plpgsql_HashEnt *hentry;
|
2003-07-01 23:47:09 +02:00
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
|
|
|
|
(void *) func_key,
|
|
|
|
HASH_FIND,
|
|
|
|
NULL);
|
2003-07-01 23:47:09 +02:00
|
|
|
if (hentry)
|
|
|
|
return hentry->function;
|
|
|
|
else
|
2004-01-07 19:56:30 +01:00
|
|
|
return NULL;
|
2003-07-01 23:47:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-11-22 19:17:34 +01:00
|
|
|
plpgsql_HashTableInsert(PLpgSQL_function *function,
|
|
|
|
PLpgSQL_func_hashkey *func_key)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
plpgsql_HashEnt *hentry;
|
|
|
|
bool found;
|
2003-07-01 23:47:09 +02:00
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
|
|
|
|
(void *) func_key,
|
|
|
|
HASH_ENTER,
|
|
|
|
&found);
|
2003-07-01 23:47:09 +02:00
|
|
|
if (found)
|
2003-07-26 01:37:31 +02:00
|
|
|
elog(WARNING, "trying to insert a function that already exists");
|
2003-07-01 23:47:09 +02:00
|
|
|
|
|
|
|
hentry->function = function;
|
|
|
|
/* prepare back link from function to hashtable key */
|
|
|
|
function->fn_hashkey = &hentry->key;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-11-22 19:17:34 +01:00
|
|
|
plpgsql_HashTableDelete(PLpgSQL_function *function)
|
2003-07-01 23:47:09 +02:00
|
|
|
{
|
2003-08-04 02:43:34 +02:00
|
|
|
plpgsql_HashEnt *hentry;
|
2003-07-01 23:47:09 +02:00
|
|
|
|
2007-01-30 23:05:13 +01:00
|
|
|
/* do nothing if not in table */
|
|
|
|
if (function->fn_hashkey == NULL)
|
|
|
|
return;
|
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
|
2005-10-15 04:49:52 +02:00
|
|
|
(void *) function->fn_hashkey,
|
2003-08-04 02:43:34 +02:00
|
|
|
HASH_REMOVE,
|
|
|
|
NULL);
|
2003-07-01 23:47:09 +02:00
|
|
|
if (hentry == NULL)
|
|
|
|
elog(WARNING, "trying to delete function that does not exist");
|
2007-01-30 23:05:13 +01:00
|
|
|
|
|
|
|
/* remove back link, which no longer points to allocated storage */
|
|
|
|
function->fn_hashkey = NULL;
|
2003-07-01 23:47:09 +02:00
|
|
|
}
|