Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 147d4bf

Browse files
committed
Modify all callers of datatype input and receive functions so that if these
functions are not strict, they will be called (passing a NULL first parameter) during any attempt to input a NULL value of their datatype. Currently, all our input functions are strict and so this commit does not change any behavior. However, this will make it possible to build domain input functions that centralize checking of domain constraints, thereby closing numerous holes in our domain support, as per previous discussion. While at it, I took the opportunity to introduce convenience functions InputFunctionCall, OutputFunctionCall, etc to use in code that calls I/O functions. This eliminates a lot of grotty-looking casts, but the main motivation is to make it easier to grep for these places if we ever need to touch them again.
1 parent eaef111 commit 147d4bf

File tree

23 files changed

+602
-396
lines changed

23 files changed

+602
-396
lines changed

doc/src/sgml/ref/create_type.sgml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.61 2006/02/28 22:37:25 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.62 2006/04/04 19:35:32 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -97,8 +97,7 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
9797
<para>
9898
The <replaceable class="parameter">input_function</replaceable>
9999
converts the type's external textual representation to the internal
100-
representation used by the
101-
operators and functions defined for the type.
100+
representation used by the operators and functions defined for the type.
102101
<replaceable class="parameter">output_function</replaceable>
103102
performs the reverse transformation. The input function may be
104103
declared as taking one argument of type <type>cstring</type>,
@@ -110,9 +109,16 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
110109
and the third is the <literal>typmod</> of the destination column, if known
111110
(-1 will be passed if not).
112111
The input function must return a value of the data type itself.
112+
Usually, an input function should be declared STRICT; if it is not,
113+
it will be called with a NULL first parameter when reading a NULL
114+
input value. The function must still return NULL in this case, unless
115+
it raises an error.
116+
(This case is mainly meant to support domain input functions, which
117+
may need to reject NULL inputs.)
113118
The output function must be
114119
declared as taking one argument of the new data type.
115120
The output function must return type <type>cstring</type>.
121+
Output functions are not invoked for NULL values.
116122
</para>
117123

118124
<para>
@@ -133,13 +139,20 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
133139
holding the received byte string; the optional arguments are the
134140
same as for the text input function.
135141
The receive function must return a value of the data type itself.
142+
Usually, a receive function should be declared STRICT; if it is not,
143+
it will be called with a NULL first parameter when reading a NULL
144+
input value. The function must still return NULL in this case, unless
145+
it raises an error.
146+
(This case is mainly meant to support domain receive functions, which
147+
may need to reject NULL inputs.)
136148
Similarly, the optional
137149
<replaceable class="parameter">send_function</replaceable> converts
138150
from the internal representation to the external binary representation.
139151
If this function is not supplied, the type cannot participate in binary
140152
output. The send function must be
141153
declared as taking one argument of the new data type.
142154
The send function must return type <type>bytea</type>.
155+
Send functions are not invoked for NULL values.
143156
</para>
144157

145158
<para>

src/backend/access/common/printtup.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.94 2006/03/05 15:58:20 momjian Exp $
12+
* $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.95 2006/04/04 19:35:33 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -331,8 +331,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
331331
/* Text output */
332332
char *outputstr;
333333

334-
outputstr = DatumGetCString(FunctionCall1(&thisState->finfo,
335-
attr));
334+
outputstr = OutputFunctionCall(&thisState->finfo, attr);
336335
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
337336
pfree(outputstr);
338337
}
@@ -341,9 +340,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
341340
/* Binary output */
342341
bytea *outputbytes;
343342

344-
outputbytes = DatumGetByteaP(FunctionCall1(&thisState->finfo,
345-
attr));
346-
/* We assume the result will not have been toasted */
343+
outputbytes = SendFunctionCall(&thisState->finfo, attr);
347344
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
348345
pq_sendbytes(&buf, VARDATA(outputbytes),
349346
VARSIZE(outputbytes) - VARHDRSZ);
@@ -429,8 +426,7 @@ printtup_20(TupleTableSlot *slot, DestReceiver *self)
429426
else
430427
attr = origattr;
431428

432-
outputstr = DatumGetCString(FunctionCall1(&thisState->finfo,
433-
attr));
429+
outputstr = OutputFunctionCall(&thisState->finfo, attr);
434430
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
435431
pfree(outputstr);
436432

@@ -542,8 +538,7 @@ debugtup(TupleTableSlot *slot, DestReceiver *self)
542538
else
543539
attr = origattr;
544540

545-
value = DatumGetCString(OidFunctionCall1(typoutput,
546-
attr));
541+
value = OidOutputFunctionCall(typoutput, attr);
547542

548543
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
549544

@@ -632,8 +627,7 @@ printtup_internal_20(TupleTableSlot *slot, DestReceiver *self)
632627
else
633628
attr = origattr;
634629

635-
outputbytes = DatumGetByteaP(FunctionCall1(&thisState->finfo,
636-
attr));
630+
outputbytes = SendFunctionCall(&thisState->finfo, attr);
637631
/* We assume the result will not have been toasted */
638632
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
639633
pq_sendbytes(&buf, VARDATA(outputbytes),

src/backend/bootstrap/bootstrap.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.213 2006/03/07 01:03:12 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.214 2006/04/04 19:35:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -826,11 +826,11 @@ InsertOneValue(char *value, int i)
826826
if (ap == NULL)
827827
elog(ERROR, "could not find atttypid %u in Typ list", typoid);
828828

829-
/* XXX this should match getTypeIOParam() */
830-
if (ap->am_typ.typtype == 'c')
831-
typioparam = typoid;
832-
else
829+
/* XXX this logic should match getTypeIOParam() */
830+
if (OidIsValid(ap->am_typ.typelem))
833831
typioparam = ap->am_typ.typelem;
832+
else
833+
typioparam = typoid;
834834

835835
typinput = ap->am_typ.typinput;
836836
typoutput = ap->am_typ.typoutput;
@@ -850,19 +850,18 @@ InsertOneValue(char *value, int i)
850850
elog(ERROR, "type oid %u not found", typoid);
851851
elog(DEBUG5, "Typ == NULL, typeindex = %u", typeindex);
852852

853-
/* XXX there are no composite types in TypInfo */
854-
typioparam = TypInfo[typeindex].elem;
853+
/* XXX this logic should match getTypeIOParam() */
854+
if (OidIsValid(TypInfo[typeindex].elem))
855+
typioparam = TypInfo[typeindex].elem;
856+
else
857+
typioparam = typoid;
855858

856859
typinput = TypInfo[typeindex].inproc;
857860
typoutput = TypInfo[typeindex].outproc;
858861
}
859862

860-
values[i] = OidFunctionCall3(typinput,
861-
CStringGetDatum(value),
862-
ObjectIdGetDatum(typioparam),
863-
Int32GetDatum(-1));
864-
prt = DatumGetCString(OidFunctionCall1(typoutput,
865-
values[i]));
863+
values[i] = OidInputFunctionCall(typinput, value, typioparam, -1);
864+
prt = OidOutputFunctionCall(typoutput, values[i]);
866865
elog(DEBUG4, "inserted -> %s", prt);
867866
pfree(prt);
868867
}

src/backend/commands/copy.c

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.261 2006/03/23 00:19:29 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.262 2006/04/04 19:35:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1382,8 +1382,8 @@ CopyTo(CopyState cstate)
13821382
{
13831383
if (!cstate->binary)
13841384
{
1385-
string = DatumGetCString(FunctionCall1(&out_functions[attnum - 1],
1386-
value));
1385+
string = OutputFunctionCall(&out_functions[attnum - 1],
1386+
value);
13871387
if (cstate->csv_mode)
13881388
CopyAttributeOutCSV(cstate, string,
13891389
force_quote[attnum - 1],
@@ -1395,9 +1395,8 @@ CopyTo(CopyState cstate)
13951395
{
13961396
bytea *outputbytes;
13971397

1398-
outputbytes = DatumGetByteaP(FunctionCall1(&out_functions[attnum - 1],
1399-
value));
1400-
/* We assume the result will not have been toasted */
1398+
outputbytes = SendFunctionCall(&out_functions[attnum - 1],
1399+
value);
14011400
CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ);
14021401
CopySendData(cstate, VARDATA(outputbytes),
14031402
VARSIZE(outputbytes) - VARHDRSZ);
@@ -1459,6 +1458,13 @@ copy_in_error_callback(void *arg)
14591458
cstate->cur_attname, attval);
14601459
pfree(attval);
14611460
}
1461+
else if (cstate->cur_attname)
1462+
{
1463+
/* error is relevant to a particular column, value is NULL */
1464+
errcontext("COPY %s, line %d, column %s: NULL input",
1465+
cstate->cur_relname, cstate->cur_lineno,
1466+
cstate->cur_attname);
1467+
}
14621468
else
14631469
{
14641470
/* error is relevant to a particular line */
@@ -1854,19 +1860,16 @@ CopyFrom(CopyState cstate)
18541860
string = cstate->null_print;
18551861
}
18561862

1857-
/* If we read an SQL NULL, no need to do anything */
1863+
cstate->cur_attname = NameStr(attr[m]->attname);
1864+
cstate->cur_attval = string;
1865+
values[m] = InputFunctionCall(&in_functions[m],
1866+
string,
1867+
typioparams[m],
1868+
attr[m]->atttypmod);
18581869
if (string != NULL)
1859-
{
1860-
cstate->cur_attname = NameStr(attr[m]->attname);
1861-
cstate->cur_attval = string;
1862-
values[m] = FunctionCall3(&in_functions[m],
1863-
CStringGetDatum(string),
1864-
ObjectIdGetDatum(typioparams[m]),
1865-
Int32GetDatum(attr[m]->atttypmod));
18661870
nulls[m] = ' ';
1867-
cstate->cur_attname = NULL;
1868-
cstate->cur_attval = NULL;
1869-
}
1871+
cstate->cur_attname = NULL;
1872+
cstate->cur_attval = NULL;
18701873
}
18711874

18721875
Assert(fieldno == nfields);
@@ -2900,7 +2903,7 @@ CopyReadBinaryAttribute(CopyState cstate,
29002903
if (fld_size == -1)
29012904
{
29022905
*isnull = true;
2903-
return (Datum) 0;
2906+
return ReceiveFunctionCall(flinfo, NULL, typioparam, typmod);
29042907
}
29052908
if (fld_size < 0)
29062909
ereport(ERROR,
@@ -2924,10 +2927,8 @@ CopyReadBinaryAttribute(CopyState cstate,
29242927
cstate->attribute_buf.data[fld_size] = '\0';
29252928

29262929
/* Call the column type's binary input converter */
2927-
result = FunctionCall3(flinfo,
2928-
PointerGetDatum(&cstate->attribute_buf),
2929-
ObjectIdGetDatum(typioparam),
2930-
Int32GetDatum(typmod));
2930+
result = ReceiveFunctionCall(flinfo, &cstate->attribute_buf,
2931+
typioparam, typmod);
29312932

29322933
/* Trouble if it didn't eat the whole buffer */
29332934
if (cstate->attribute_buf.cursor != cstate->attribute_buf.len)

src/backend/executor/execTuples.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.92 2006/03/05 15:58:26 momjian Exp $
18+
* $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.93 2006/04/04 19:35:34 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -928,6 +928,7 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc)
928928
/*
929929
* BuildTupleFromCStrings - build a HeapTuple given user data in C string form.
930930
* values is an array of C strings, one for each attribute of the return tuple.
931+
* A NULL string pointer indicates we want to create a NULL field.
931932
*/
932933
HeapTuple
933934
BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
@@ -937,35 +938,25 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
937938
Datum *dvalues;
938939
char *nulls;
939940
int i;
940-
Oid attioparam;
941-
int32 atttypmod;
942941
HeapTuple tuple;
943942

944943
dvalues = (Datum *) palloc(natts * sizeof(Datum));
945944
nulls = (char *) palloc(natts * sizeof(char));
946945

947-
/* Call the "in" function for each non-null, non-dropped attribute */
946+
/* Call the "in" function for each non-dropped attribute */
948947
for (i = 0; i < natts; i++)
949948
{
950949
if (!tupdesc->attrs[i]->attisdropped)
951950
{
952951
/* Non-dropped attributes */
952+
dvalues[i] = InputFunctionCall(&attinmeta->attinfuncs[i],
953+
values[i],
954+
attinmeta->attioparams[i],
955+
attinmeta->atttypmods[i]);
953956
if (values[i] != NULL)
954-
{
955-
attioparam = attinmeta->attioparams[i];
956-
atttypmod = attinmeta->atttypmods[i];
957-
958-
dvalues[i] = FunctionCall3(&attinmeta->attinfuncs[i],
959-
CStringGetDatum(values[i]),
960-
ObjectIdGetDatum(attioparam),
961-
Int32GetDatum(atttypmod));
962957
nulls[i] = ' ';
963-
}
964958
else
965-
{
966-
dvalues[i] = (Datum) 0;
967959
nulls[i] = 'n';
968-
}
969960
}
970961
else
971962
{

src/backend/executor/nodeAgg.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
* Portions Copyright (c) 1994, Regents of the University of California
6262
*
6363
* IDENTIFICATION
64-
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.138 2006/03/05 15:58:26 momjian Exp $
64+
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.139 2006/04/04 19:35:34 tgl Exp $
6565
*
6666
*-------------------------------------------------------------------------
6767
*/
@@ -1407,10 +1407,8 @@ GetAggInitVal(Datum textInitVal, Oid transtype)
14071407

14081408
getTypeInputInfo(transtype, &typinput, &typioparam);
14091409
strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal));
1410-
initVal = OidFunctionCall3(typinput,
1411-
CStringGetDatum(strInitVal),
1412-
ObjectIdGetDatum(typioparam),
1413-
Int32GetDatum(-1));
1410+
initVal = OidInputFunctionCall(typinput, strInitVal,
1411+
typioparam, -1);
14141412
pfree(strInitVal);
14151413
return initVal;
14161414
}

src/backend/executor/spi.c

Lines changed: 5 additions & 6 deletions
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.149 2006/03/14 22:48:19 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.150 2006/04/04 19:35:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -629,9 +629,9 @@ SPI_fname(TupleDesc tupdesc, int fnumber)
629629
char *
630630
SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
631631
{
632+
char *result;
632633
Datum origval,
633-
val,
634-
result;
634+
val;
635635
bool isnull;
636636
Oid typoid,
637637
foutoid;
@@ -666,14 +666,13 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
666666
else
667667
val = origval;
668668

669-
result = OidFunctionCall1(foutoid,
670-
val);
669+
result = OidOutputFunctionCall(foutoid, val);
671670

672671
/* Clean up detoasted copy, if any */
673672
if (val != origval)
674673
pfree(DatumGetPointer(val));
675674

676-
return DatumGetCString(result);
675+
return result;
677676
}
678677

679678
Datum

src/backend/nodes/print.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.78 2006/03/05 15:58:28 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.79 2006/04/04 19:35:34 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHOR DATE MAJOR EVENT
@@ -357,8 +357,7 @@ print_expr(Node *expr, List *rtable)
357357
getTypeOutputInfo(c->consttype,
358358
&typoutput, &typIsVarlena);
359359

360-
outputstr = DatumGetCString(OidFunctionCall1(typoutput,
361-
c->constvalue));
360+
outputstr = OidOutputFunctionCall(typoutput, c->constvalue);
362361
printf("%s", outputstr);
363362
pfree(outputstr);
364363
}

0 commit comments

Comments
 (0)