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

Commit3b9d2de

Browse files
committed
Convert a few more datatype input functions to report errors softly.
Convert the remaining string-category input functions(bpcharin, varcharin, byteain) to the new style.Discussion:https://postgr.es/m/3038346.1671060258@sss.pgh.pa.us
1 parent90161da commit3b9d2de

File tree

14 files changed

+203
-30
lines changed

14 files changed

+203
-30
lines changed

‎src/backend/utils/adt/encode.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,26 +171,28 @@ hex_encode(const char *src, size_t len, char *dst)
171171
return (uint64)len*2;
172172
}
173173

174-
staticinlinechar
175-
get_hex(constchar*cp)
174+
staticinlinebool
175+
get_hex(constchar*cp,char*out)
176176
{
177177
unsignedcharc= (unsignedchar)*cp;
178178
intres=-1;
179179

180180
if (c<127)
181181
res=hexlookup[c];
182182

183-
if (res<0)
184-
ereport(ERROR,
185-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
186-
errmsg("invalid hexadecimal digit: \"%.*s\"",
187-
pg_mblen(cp),cp)));
183+
*out= (char)res;
188184

189-
return (char)res;
185+
return (res >=0);
190186
}
191187

192188
uint64
193189
hex_decode(constchar*src,size_tlen,char*dst)
190+
{
191+
returnhex_decode_safe(src,len,dst,NULL);
192+
}
193+
194+
uint64
195+
hex_decode_safe(constchar*src,size_tlen,char*dst,Node*escontext)
194196
{
195197
constchar*s,
196198
*srcend;
@@ -208,16 +210,23 @@ hex_decode(const char *src, size_t len, char *dst)
208210
s++;
209211
continue;
210212
}
211-
v1=get_hex(s) <<4;
213+
if (!get_hex(s,&v1))
214+
ereturn(escontext,0,
215+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
216+
errmsg("invalid hexadecimal digit: \"%.*s\"",
217+
pg_mblen(s),s)));
212218
s++;
213219
if (s >=srcend)
214-
ereport(ERROR,
220+
ereturn(escontext,0,
215221
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
216222
errmsg("invalid hexadecimal data: odd number of digits")));
217-
218-
v2=get_hex(s);
223+
if (!get_hex(s,&v2))
224+
ereturn(escontext,0,
225+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
226+
errmsg("invalid hexadecimal digit: \"%.*s\"",
227+
pg_mblen(s),s)));
219228
s++;
220-
*p++=v1 |v2;
229+
*p++=(v1 <<4) |v2;
221230
}
222231

223232
returnp-dst;

‎src/backend/utils/adt/varchar.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,13 @@ anychar_typmodout(int32 typmod)
122122
*
123123
* If the input string is too long, raise an error, unless the extra
124124
* characters are spaces, in which case they're truncated. (per SQL)
125+
*
126+
* If escontext points to an ErrorSaveContext node, that is filled instead
127+
* of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
128+
* to detect errors.
125129
*/
126130
staticBpChar*
127-
bpchar_input(constchar*s,size_tlen,int32atttypmod)
131+
bpchar_input(constchar*s,size_tlen,int32atttypmod,Node*escontext)
128132
{
129133
BpChar*result;
130134
char*r;
@@ -153,7 +157,7 @@ bpchar_input(const char *s, size_t len, int32 atttypmod)
153157
for (j=mbmaxlen;j<len;j++)
154158
{
155159
if (s[j]!=' ')
156-
ereport(ERROR,
160+
ereturn(escontext,NULL,
157161
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
158162
errmsg("value too long for type character(%d)",
159163
(int)maxlen)));
@@ -195,14 +199,13 @@ Datum
195199
bpcharin(PG_FUNCTION_ARGS)
196200
{
197201
char*s=PG_GETARG_CSTRING(0);
198-
199202
#ifdefNOT_USED
200203
Oidtypelem=PG_GETARG_OID(1);
201204
#endif
202205
int32atttypmod=PG_GETARG_INT32(2);
203206
BpChar*result;
204207

205-
result=bpchar_input(s,strlen(s),atttypmod);
208+
result=bpchar_input(s,strlen(s),atttypmod,fcinfo->context);
206209
PG_RETURN_BPCHAR_P(result);
207210
}
208211

@@ -228,7 +231,6 @@ Datum
228231
bpcharrecv(PG_FUNCTION_ARGS)
229232
{
230233
StringInfobuf= (StringInfo)PG_GETARG_POINTER(0);
231-
232234
#ifdefNOT_USED
233235
Oidtypelem=PG_GETARG_OID(1);
234236
#endif
@@ -238,7 +240,7 @@ bpcharrecv(PG_FUNCTION_ARGS)
238240
intnbytes;
239241

240242
str=pq_getmsgtext(buf,buf->len-buf->cursor,&nbytes);
241-
result=bpchar_input(str,nbytes,atttypmod);
243+
result=bpchar_input(str,nbytes,atttypmod,NULL);
242244
pfree(str);
243245
PG_RETURN_BPCHAR_P(result);
244246
}
@@ -448,11 +450,12 @@ bpchartypmodout(PG_FUNCTION_ARGS)
448450
* If the input string is too long, raise an error, unless the extra
449451
* characters are spaces, in which case they're truncated. (per SQL)
450452
*
451-
* Uses the C string to text conversion function, which is only appropriate
452-
* if VarChar and text are equivalent types.
453+
* If escontext points to an ErrorSaveContext node, that is filled instead
454+
* of throwing an error; the caller must check SOFT_ERROR_OCCURRED()
455+
* to detect errors.
453456
*/
454457
staticVarChar*
455-
varchar_input(constchar*s,size_tlen,int32atttypmod)
458+
varchar_input(constchar*s,size_tlen,int32atttypmod,Node*escontext)
456459
{
457460
VarChar*result;
458461
size_tmaxlen;
@@ -468,7 +471,7 @@ varchar_input(const char *s, size_t len, int32 atttypmod)
468471
for (j=mbmaxlen;j<len;j++)
469472
{
470473
if (s[j]!=' ')
471-
ereport(ERROR,
474+
ereturn(escontext,NULL,
472475
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
473476
errmsg("value too long for type character varying(%d)",
474477
(int)maxlen)));
@@ -477,6 +480,10 @@ varchar_input(const char *s, size_t len, int32 atttypmod)
477480
len=mbmaxlen;
478481
}
479482

483+
/*
484+
* We can use cstring_to_text_with_len because VarChar and text are
485+
* binary-compatible types.
486+
*/
480487
result= (VarChar*)cstring_to_text_with_len(s,len);
481488
returnresult;
482489
}
@@ -489,14 +496,13 @@ Datum
489496
varcharin(PG_FUNCTION_ARGS)
490497
{
491498
char*s=PG_GETARG_CSTRING(0);
492-
493499
#ifdefNOT_USED
494500
Oidtypelem=PG_GETARG_OID(1);
495501
#endif
496502
int32atttypmod=PG_GETARG_INT32(2);
497503
VarChar*result;
498504

499-
result=varchar_input(s,strlen(s),atttypmod);
505+
result=varchar_input(s,strlen(s),atttypmod,fcinfo->context);
500506
PG_RETURN_VARCHAR_P(result);
501507
}
502508

@@ -522,7 +528,6 @@ Datum
522528
varcharrecv(PG_FUNCTION_ARGS)
523529
{
524530
StringInfobuf= (StringInfo)PG_GETARG_POINTER(0);
525-
526531
#ifdefNOT_USED
527532
Oidtypelem=PG_GETARG_OID(1);
528533
#endif
@@ -532,7 +537,7 @@ varcharrecv(PG_FUNCTION_ARGS)
532537
intnbytes;
533538

534539
str=pq_getmsgtext(buf,buf->len-buf->cursor,&nbytes);
535-
result=varchar_input(str,nbytes,atttypmod);
540+
result=varchar_input(str,nbytes,atttypmod,NULL);
536541
pfree(str);
537542
PG_RETURN_VARCHAR_P(result);
538543
}

‎src/backend/utils/adt/varlena.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ Datum
295295
byteain(PG_FUNCTION_ARGS)
296296
{
297297
char*inputText=PG_GETARG_CSTRING(0);
298+
Node*escontext=fcinfo->context;
298299
char*tp;
299300
char*rp;
300301
intbc;
@@ -307,7 +308,8 @@ byteain(PG_FUNCTION_ARGS)
307308

308309
bc= (len-2) /2+VARHDRSZ;/* maximum possible length */
309310
result=palloc(bc);
310-
bc=hex_decode(inputText+2,len-2,VARDATA(result));
311+
bc=hex_decode_safe(inputText+2,len-2,VARDATA(result),
312+
escontext);
311313
SET_VARSIZE(result,bc+VARHDRSZ);/* actual length */
312314

313315
PG_RETURN_BYTEA_P(result);
@@ -331,7 +333,7 @@ byteain(PG_FUNCTION_ARGS)
331333
/*
332334
* one backslash, not followed by another or ### valid octal
333335
*/
334-
ereport(ERROR,
336+
ereturn(escontext, (Datum)0,
335337
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
336338
errmsg("invalid input syntax for type %s","bytea")));
337339
}
@@ -372,7 +374,7 @@ byteain(PG_FUNCTION_ARGS)
372374
/*
373375
* We should never get here. The first pass should not allow it.
374376
*/
375-
ereport(ERROR,
377+
ereturn(escontext, (Datum)0,
376378
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
377379
errmsg("invalid input syntax for type %s","bytea")));
378380
}

‎src/include/utils/builtins.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ extern interrdomainconstraint(Oid datatypeOid, const char *conname);
3434
/* encode.c */
3535
externuint64hex_encode(constchar*src,size_tlen,char*dst);
3636
externuint64hex_decode(constchar*src,size_tlen,char*dst);
37+
externuint64hex_decode_safe(constchar*src,size_tlen,char*dst,
38+
Node*escontext);
3739

3840
/* int.c */
3941
externint2vector*buildint2vector(constint16*int2s,intn);

‎src/test/regress/expected/char.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,25 @@ SELECT * FROM CHAR_TBL;
119119
abcd
120120
(4 rows)
121121

122+
-- Also try it with non-error-throwing API
123+
SELECT pg_input_is_valid('abcd ', 'char(4)');
124+
pg_input_is_valid
125+
-------------------
126+
t
127+
(1 row)
128+
129+
SELECT pg_input_is_valid('abcde', 'char(4)');
130+
pg_input_is_valid
131+
-------------------
132+
f
133+
(1 row)
134+
135+
SELECT pg_input_error_message('abcde', 'char(4)');
136+
pg_input_error_message
137+
--------------------------------------
138+
value too long for type character(4)
139+
(1 row)
140+
122141
--
123142
-- Also test "char", which is an ad-hoc one-byte type. It can only
124143
-- really store ASCII characters, but we allow high-bit-set characters

‎src/test/regress/expected/char_1.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,25 @@ SELECT * FROM CHAR_TBL;
119119
abcd
120120
(4 rows)
121121

122+
-- Also try it with non-error-throwing API
123+
SELECT pg_input_is_valid('abcd ', 'char(4)');
124+
pg_input_is_valid
125+
-------------------
126+
t
127+
(1 row)
128+
129+
SELECT pg_input_is_valid('abcde', 'char(4)');
130+
pg_input_is_valid
131+
-------------------
132+
f
133+
(1 row)
134+
135+
SELECT pg_input_error_message('abcde', 'char(4)');
136+
pg_input_error_message
137+
--------------------------------------
138+
value too long for type character(4)
139+
(1 row)
140+
122141
--
123142
-- Also test "char", which is an ad-hoc one-byte type. It can only
124143
-- really store ASCII characters, but we allow high-bit-set characters

‎src/test/regress/expected/char_2.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,25 @@ SELECT * FROM CHAR_TBL;
119119
abcd
120120
(4 rows)
121121

122+
-- Also try it with non-error-throwing API
123+
SELECT pg_input_is_valid('abcd ', 'char(4)');
124+
pg_input_is_valid
125+
-------------------
126+
t
127+
(1 row)
128+
129+
SELECT pg_input_is_valid('abcde', 'char(4)');
130+
pg_input_is_valid
131+
-------------------
132+
f
133+
(1 row)
134+
135+
SELECT pg_input_error_message('abcde', 'char(4)');
136+
pg_input_error_message
137+
--------------------------------------
138+
value too long for type character(4)
139+
(1 row)
140+
122141
--
123142
-- Also test "char", which is an ad-hoc one-byte type. It can only
124143
-- really store ASCII characters, but we allow high-bit-set characters

‎src/test/regress/expected/strings.out

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,31 @@ SELECT E'De\\123dBeEf'::bytea;
273273
DeSdBeEf
274274
(1 row)
275275

276+
-- Test non-error-throwing API too
277+
SELECT pg_input_is_valid(E'\\xDeAdBeE', 'bytea');
278+
pg_input_is_valid
279+
-------------------
280+
f
281+
(1 row)
282+
283+
SELECT pg_input_error_message(E'\\xDeAdBeE', 'bytea');
284+
pg_input_error_message
285+
------------------------------------------------
286+
invalid hexadecimal data: odd number of digits
287+
(1 row)
288+
289+
SELECT pg_input_error_message(E'\\xDeAdBeEx', 'bytea');
290+
pg_input_error_message
291+
--------------------------------
292+
invalid hexadecimal digit: "x"
293+
(1 row)
294+
295+
SELECT pg_input_error_message(E'foo\\99bar', 'bytea');
296+
pg_input_error_message
297+
-------------------------------------
298+
invalid input syntax for type bytea
299+
(1 row)
300+
276301
--
277302
-- test conversions between various string types
278303
-- E021-10 implicit casting among the character data types

‎src/test/regress/expected/varchar.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,22 @@ SELECT * FROM VARCHAR_TBL;
111111
abcd
112112
(4 rows)
113113

114+
-- Also try it with non-error-throwing API
115+
SELECT pg_input_is_valid('abcd ', 'varchar(4)');
116+
pg_input_is_valid
117+
-------------------
118+
t
119+
(1 row)
120+
121+
SELECT pg_input_is_valid('abcde', 'varchar(4)');
122+
pg_input_is_valid
123+
-------------------
124+
f
125+
(1 row)
126+
127+
SELECT pg_input_error_message('abcde', 'varchar(4)');
128+
pg_input_error_message
129+
----------------------------------------------
130+
value too long for type character varying(4)
131+
(1 row)
132+

‎src/test/regress/expected/varchar_1.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,22 @@ SELECT * FROM VARCHAR_TBL;
111111
abcd
112112
(4 rows)
113113

114+
-- Also try it with non-error-throwing API
115+
SELECT pg_input_is_valid('abcd ', 'varchar(4)');
116+
pg_input_is_valid
117+
-------------------
118+
t
119+
(1 row)
120+
121+
SELECT pg_input_is_valid('abcde', 'varchar(4)');
122+
pg_input_is_valid
123+
-------------------
124+
f
125+
(1 row)
126+
127+
SELECT pg_input_error_message('abcde', 'varchar(4)');
128+
pg_input_error_message
129+
----------------------------------------------
130+
value too long for type character varying(4)
131+
(1 row)
132+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp