|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.128 2005/04/14 20:03:23 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.129 2005/05/03 16:51:00 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -81,6 +81,9 @@ ProcedureCreate(const char *procedureName,
|
81 | 81 | int allParamCount;
|
82 | 82 | Oid *allParams;
|
83 | 83 | bool genericInParam = false;
|
| 84 | + bool genericOutParam = false; |
| 85 | + bool internalInParam = false; |
| 86 | + bool internalOutParam = false; |
84 | 87 | Relation rel;
|
85 | 88 | HeapTuple tup;
|
86 | 89 | HeapTuple oldtup;
|
@@ -133,43 +136,59 @@ ProcedureCreate(const char *procedureName,
|
133 | 136 |
|
134 | 137 | /*
|
135 | 138 | * Do not allow return type ANYARRAY or ANYELEMENT unless at least one
|
136 |
| - * input argument is also ANYARRAY or ANYELEMENT |
| 139 | + * input argument is ANYARRAY or ANYELEMENT. Also, do not allow |
| 140 | + * return type INTERNAL unless at least one input argument is INTERNAL. |
137 | 141 | */
|
138 | 142 | for (i = 0; i < parameterCount; i++)
|
139 | 143 | {
|
140 |
| - if (parameterTypes->values[i] == ANYARRAYOID || |
141 |
| - parameterTypes->values[i] == ANYELEMENTOID) |
| 144 | + switch (parameterTypes->values[i]) |
142 | 145 | {
|
143 |
| - genericInParam = true; |
144 |
| - break; |
| 146 | + case ANYARRAYOID: |
| 147 | + case ANYELEMENTOID: |
| 148 | + genericInParam = true; |
| 149 | + break; |
| 150 | + case INTERNALOID: |
| 151 | + internalInParam = true; |
| 152 | + break; |
145 | 153 | }
|
146 | 154 | }
|
147 | 155 |
|
148 |
| - if (!genericInParam) |
| 156 | + if (allParameterTypes != PointerGetDatum(NULL)) |
149 | 157 | {
|
150 |
| - bool genericOutParam = false; |
151 |
| - |
152 |
| - if (allParameterTypes != PointerGetDatum(NULL)) |
| 158 | + for (i = 0; i < allParamCount; i++) |
153 | 159 | {
|
154 |
| - for (i = 0; i < allParamCount; i++) |
| 160 | + /* |
| 161 | + * We don't bother to distinguish input and output params here, |
| 162 | + * so if there is, say, just an input INTERNAL param then we will |
| 163 | + * still set internalOutParam. This is OK since we don't really |
| 164 | + * care. |
| 165 | + */ |
| 166 | + switch (allParams[i]) |
155 | 167 | {
|
156 |
| - if (allParams[i] == ANYARRAYOID || |
157 |
| - allParams[i] == ANYELEMENTOID) |
158 |
| - { |
| 168 | + case ANYARRAYOID: |
| 169 | + case ANYELEMENTOID: |
159 | 170 | genericOutParam = true;
|
160 | 171 | break;
|
161 |
| - } |
| 172 | + case INTERNALOID: |
| 173 | + internalOutParam = true; |
| 174 | + break; |
162 | 175 | }
|
163 | 176 | }
|
164 |
| - |
165 |
| - if (returnType == ANYARRAYOID || returnType == ANYELEMENTOID || |
166 |
| - genericOutParam) |
167 |
| - ereport(ERROR, |
168 |
| - (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
169 |
| - errmsg("cannot determine result data type"), |
170 |
| - errdetail("A function returning \"anyarray\" or \"anyelement\" must have at least one argument of either type."))); |
171 | 177 | }
|
172 | 178 |
|
| 179 | + if ((returnType == ANYARRAYOID || returnType == ANYELEMENTOID || |
| 180 | + genericOutParam) && !genericInParam) |
| 181 | + ereport(ERROR, |
| 182 | + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
| 183 | + errmsg("cannot determine result data type"), |
| 184 | + errdetail("A function returning \"anyarray\" or \"anyelement\" must have at least one argument of either type."))); |
| 185 | + |
| 186 | + if ((returnType == INTERNALOID || internalOutParam) && !internalInParam) |
| 187 | + ereport(ERROR, |
| 188 | + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
| 189 | + errmsg("unsafe use of INTERNAL pseudo-type"), |
| 190 | + errdetail("A function returning \"internal\" must have at least one \"internal\" argument."))); |
| 191 | + |
173 | 192 | /*
|
174 | 193 | * don't allow functions of complex types that have the same name as
|
175 | 194 | * existing attributes of the type
|
|
0 commit comments