Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdeac948

Browse files
committed
Insert conditional SPI_push/SPI_pop calls into InputFunctionCall,
OutputFunctionCall, and friends. This allows SPI-using functions to invokedatatype I/O without concern for the possibility that a SPI-using functionwill be called (which could be either the I/O function itself, or a functionused in a domain check constraint). It's a tad ugly, but not nearly as uglyas what'd be needed to make this work via retail insertion of push/popoperations in all the PLs.This reverts my patch of 2007-01-30 that inserted some retail SPI_push/popcalls into plpgsql; that approach only fixed plpgsql, and not any other PLs.But the other PLs have the issue too, as illustrated by a recent gripe fromChristian Schröder.Back-patch to 8.2, which is as far back as this solution will work. It'salso as far back as we need to worry about the domain-constraint case, sinceearlier versions did not attempt to check domain constraints within datatypeinput. I'm not aware of any old I/O functions that use SPI themselves, sothis should be sufficient for a back-patch.
1 parent6b88393 commitdeac948

File tree

4 files changed

+77
-40
lines changed

4 files changed

+77
-40
lines changed

‎src/backend/executor/spi.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.205 2009/01/0713:44:36 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.206 2009/01/0720:38:56 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -304,6 +304,31 @@ SPI_pop(void)
304304
_SPI_curid--;
305305
}
306306

307+
/* Conditional push: push only if we're inside a SPI procedure */
308+
bool
309+
SPI_push_conditional(void)
310+
{
311+
boolpushed= (_SPI_curid!=_SPI_connected);
312+
313+
if (pushed)
314+
{
315+
_SPI_curid++;
316+
/* We should now be in a state where SPI_connect would succeed */
317+
Assert(_SPI_curid==_SPI_connected);
318+
}
319+
returnpushed;
320+
}
321+
322+
/* Conditional pop: pop only if SPI_push_conditional pushed */
323+
void
324+
SPI_pop_conditional(boolpushed)
325+
{
326+
/* We should be in a state where SPI_connect would succeed */
327+
Assert(_SPI_curid==_SPI_connected);
328+
if (pushed)
329+
_SPI_curid--;
330+
}
331+
307332
/* Restore state of SPI stack after aborting a subtransaction */
308333
void
309334
SPI_restore_connection(void)

‎src/backend/utils/fmgr/fmgr.c

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.124 2009/01/01 17:23:51 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.125 2009/01/07 20:38:56 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -19,6 +19,7 @@
1919
#include"catalog/pg_language.h"
2020
#include"catalog/pg_proc.h"
2121
#include"executor/functions.h"
22+
#include"executor/spi.h"
2223
#include"lib/stringinfo.h"
2324
#include"miscadmin.h"
2425
#include"nodes/nodeFuncs.h"
@@ -1846,16 +1847,25 @@ OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
18461847
* the caller should assume the result is NULL, but we'll call the input
18471848
* function anyway if it's not strict. So this is almost but not quite
18481849
* the same as FunctionCall3.
1850+
*
1851+
* One important difference from the bare function call is that we will
1852+
* push any active SPI context, allowing SPI-using I/O functions to be
1853+
* called from other SPI functions without extra notation. This is a hack,
1854+
* but the alternative of expecting all SPI functions to do SPI_push/SPI_pop
1855+
* around I/O calls seems worse.
18491856
*/
18501857
Datum
18511858
InputFunctionCall(FmgrInfo*flinfo,char*str,Oidtypioparam,int32typmod)
18521859
{
18531860
FunctionCallInfoDatafcinfo;
18541861
Datumresult;
1862+
boolpushed;
18551863

18561864
if (str==NULL&&flinfo->fn_strict)
18571865
return (Datum)0;/* just return null result */
18581866

1867+
pushed=SPI_push_conditional();
1868+
18591869
InitFunctionCallInfoData(fcinfo,flinfo,3,NULL,NULL);
18601870

18611871
fcinfo.arg[0]=CStringGetDatum(str);
@@ -1881,6 +1891,8 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
18811891
fcinfo.flinfo->fn_oid);
18821892
}
18831893

1894+
SPI_pop_conditional(pushed);
1895+
18841896
returnresult;
18851897
}
18861898

@@ -1889,13 +1901,22 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
18891901
*
18901902
* Do not call this on NULL datums.
18911903
*
1892-
* This ismerewindow dressing for FunctionCall1, butits use is recommended
1893-
*anyway so that code invoking output functions can be identified easily.
1904+
* This isalmost justwindow dressing for FunctionCall1, butit includes
1905+
*SPI context pushing for the same reasons as InputFunctionCall.
18941906
*/
18951907
char*
18961908
OutputFunctionCall(FmgrInfo*flinfo,Datumval)
18971909
{
1898-
returnDatumGetCString(FunctionCall1(flinfo,val));
1910+
char*result;
1911+
boolpushed;
1912+
1913+
pushed=SPI_push_conditional();
1914+
1915+
result=DatumGetCString(FunctionCall1(flinfo,val));
1916+
1917+
SPI_pop_conditional(pushed);
1918+
1919+
returnresult;
18991920
}
19001921

19011922
/*
@@ -1904,18 +1925,22 @@ OutputFunctionCall(FmgrInfo *flinfo, Datum val)
19041925
* "buf" may be NULL to indicate we are reading a NULL. In this case
19051926
* the caller should assume the result is NULL, but we'll call the receive
19061927
* function anyway if it's not strict. So this is almost but not quite
1907-
* the same as FunctionCall3.
1928+
* the same as FunctionCall3. Also, this includes SPI context pushing for
1929+
* the same reasons as InputFunctionCall.
19081930
*/
19091931
Datum
19101932
ReceiveFunctionCall(FmgrInfo*flinfo,StringInfobuf,
19111933
Oidtypioparam,int32typmod)
19121934
{
19131935
FunctionCallInfoDatafcinfo;
19141936
Datumresult;
1937+
boolpushed;
19151938

19161939
if (buf==NULL&&flinfo->fn_strict)
19171940
return (Datum)0;/* just return null result */
19181941

1942+
pushed=SPI_push_conditional();
1943+
19191944
InitFunctionCallInfoData(fcinfo,flinfo,3,NULL,NULL);
19201945

19211946
fcinfo.arg[0]=PointerGetDatum(buf);
@@ -1941,6 +1966,8 @@ ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
19411966
fcinfo.flinfo->fn_oid);
19421967
}
19431968

1969+
SPI_pop_conditional(pushed);
1970+
19441971
returnresult;
19451972
}
19461973

@@ -1949,14 +1976,24 @@ ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
19491976
*
19501977
* Do not call this on NULL datums.
19511978
*
1952-
* This is little more than window dressing for FunctionCall1, but its use is
1953-
* recommended anyway so that code invoking output functions can be identified
1954-
* easily.Note however that it does guarantee a non-toasted result.
1979+
* This is little more than window dressing for FunctionCall1, but it does
1980+
* guarantee a non-toasted result, which strictly speaking the underlying
1981+
* function doesn't. Also, this includes SPI context pushing for the same
1982+
* reasons as InputFunctionCall.
19551983
*/
19561984
bytea*
19571985
SendFunctionCall(FmgrInfo*flinfo,Datumval)
19581986
{
1959-
returnDatumGetByteaP(FunctionCall1(flinfo,val));
1987+
bytea*result;
1988+
boolpushed;
1989+
1990+
pushed=SPI_push_conditional();
1991+
1992+
result=DatumGetByteaP(FunctionCall1(flinfo,val));
1993+
1994+
SPI_pop_conditional(pushed);
1995+
1996+
returnresult;
19601997
}
19611998

19621999
/*

‎src/include/executor/spi.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.69 2009/01/0713:44:37 tgl Exp $
9+
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.70 2009/01/0720:38:56 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -66,6 +66,8 @@ extern intSPI_connect(void);
6666
externintSPI_finish(void);
6767
externvoidSPI_push(void);
6868
externvoidSPI_pop(void);
69+
externboolSPI_push_conditional(void);
70+
externvoidSPI_pop_conditional(boolpushed);
6971
externvoidSPI_restore_connection(void);
7072
externintSPI_execute(constchar*src,boolread_only,longtcount);
7173
externintSPI_execute_plan(SPIPlanPtrplan,Datum*Values,constchar*Nulls,

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.227 2009/01/0713:44:37 tgl Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.228 2009/01/0720:38:56 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -4690,27 +4690,11 @@ make_tuple_from_row(PLpgSQL_execstate *estate,
46904690
staticchar*
46914691
convert_value_to_string(Datumvalue,Oidvaltype)
46924692
{
4693-
char*str;
46944693
Oidtypoutput;
46954694
booltypIsVarlena;
46964695

46974696
getTypeOutputInfo(valtype,&typoutput,&typIsVarlena);
4698-
4699-
/*
4700-
* We do SPI_push to allow the datatype output function to use SPI.
4701-
* However we do not mess around with CommandCounterIncrement or advancing
4702-
* the snapshot, which means that a stable output function would not see
4703-
* updates made so far by our own function. The use-case for such
4704-
* scenarios seems too narrow to justify the cycles that would be
4705-
* expended.
4706-
*/
4707-
SPI_push();
4708-
4709-
str=OidOutputFunctionCall(typoutput,value);
4710-
4711-
SPI_pop();
4712-
4713-
returnstr;
4697+
returnOidOutputFunctionCall(typoutput,value);
47144698
}
47154699

47164700
/* ----------
@@ -4736,25 +4720,14 @@ exec_cast_value(Datum value, Oid valtype,
47364720
char*extval;
47374721

47384722
extval=convert_value_to_string(value,valtype);
4739-
4740-
/* Allow input function to use SPI ... see notes above */
4741-
SPI_push();
4742-
47434723
value=InputFunctionCall(reqinput,extval,
47444724
reqtypioparam,reqtypmod);
4745-
4746-
SPI_pop();
4747-
47484725
pfree(extval);
47494726
}
47504727
else
47514728
{
4752-
SPI_push();
4753-
47544729
value=InputFunctionCall(reqinput,NULL,
47554730
reqtypioparam,reqtypmod);
4756-
4757-
SPI_pop();
47584731
}
47594732
}
47604733

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp