macaddr_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
macaddr *result;
int a,
b,
count = sscanf(str, "%2x%2x%2x%2x%2x%2x%1s",
&a, &b, &c, &d, &e, &f, junk);
if (count != 6)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"", "macaddr",
str)));
if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
(c < 0) || (c > 255) || (d < 0) || (d > 255) ||
(e < 0) || (e > 255) || (f < 0) || (f > 255))
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
#define lobits(addr) \
((unsigned long)(((addr)->e<<24) | ((addr)->f<<16) | ((addr)->g<<8) | ((addr)->h)))
-static unsigned char hex2_to_uchar(const unsigned char *ptr, const unsigned char *str);
+static unsigned char hex2_to_uchar(const unsigned char *ptr, bool *badhex);
static const signed char hexlookup[128] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/*
* hex2_to_uchar - convert 2 hex digits to a byte (unsigned char)
*
- * This will ereport() if the end of the string is reached ('\0' found), or if
+ * Sets *badhex to true if the end of the string is reached ('\0' found), or if
* either character is not a valid hex digit.
- *
- * ptr is the pointer to where the digits to convert are in the string, str is
- * the entire string, which is used only for error reporting.
*/
static inline unsigned char
-hex2_to_uchar(const unsigned char *ptr, const unsigned char *str)
+hex2_to_uchar(const unsigned char *ptr, bool *badhex)
{
- unsigned char ret = 0;
+ unsigned char ret;
signed char lookup;
/* Handle the first character */
return ret;
invalid_input:
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
- str)));
-
- /* We do not actually reach here */
+ *badhex = true;
return 0;
}
macaddr8_in(PG_FUNCTION_ARGS)
{
const unsigned char *str = (unsigned char *) PG_GETARG_CSTRING(0);
+ Node *escontext = fcinfo->context;
const unsigned char *ptr = str;
+ bool badhex = false;
macaddr8 *result;
unsigned char a = 0,
b = 0,
switch (count)
{
case 1:
- a = hex2_to_uchar(ptr, str);
+ a = hex2_to_uchar(ptr, &badhex);
break;
case 2:
- b = hex2_to_uchar(ptr, str);
+ b = hex2_to_uchar(ptr, &badhex);
break;
case 3:
- c = hex2_to_uchar(ptr, str);
+ c = hex2_to_uchar(ptr, &badhex);
break;
case 4:
- d = hex2_to_uchar(ptr, str);
+ d = hex2_to_uchar(ptr, &badhex);
break;
case 5:
- e = hex2_to_uchar(ptr, str);
+ e = hex2_to_uchar(ptr, &badhex);
break;
case 6:
- f = hex2_to_uchar(ptr, str);
+ f = hex2_to_uchar(ptr, &badhex);
break;
case 7:
- g = hex2_to_uchar(ptr, str);
+ g = hex2_to_uchar(ptr, &badhex);
break;
case 8:
- h = hex2_to_uchar(ptr, str);
+ h = hex2_to_uchar(ptr, &badhex);
break;
default:
/* must be trailing garbage... */
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
- str)));
+ goto fail;
}
+ if (badhex)
+ goto fail;
+
/* Move forward to where the next byte should be */
ptr += 2;
/* Have to use the same spacer throughout */
else if (spacer != *ptr)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
- str)));
+ goto fail;
/* move past the spacer */
ptr++;
/* If we found a space and then non-space, it's invalid */
if (*ptr)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
- str)));
+ goto fail;
}
}
}
e = 0xFE;
}
else if (count != 8)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
- str)));
+ goto fail;
result = (macaddr8 *) palloc0(sizeof(macaddr8));
result->h = h;
PG_RETURN_MACADDR8_P(result);
+
+fail:
+ ereturn(escontext, (Datum) 0,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
+ str)));
}
/*
* Common INET/CIDR input routine
*/
static inet *
-network_in(char *src, bool is_cidr)
+network_in(char *src, bool is_cidr, Node *escontext)
{
int bits;
inet *dst;
bits = pg_inet_net_pton(ip_family(dst), src, ip_addr(dst),
is_cidr ? ip_addrsize(dst) : -1);
if ((bits < 0) || (bits > ip_maxbits(dst)))
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
/* translator: first %s is inet or cidr */
errmsg("invalid input syntax for type %s: \"%s\"",
if (is_cidr)
{
if (!addressOK(ip_addr(dst), bits, ip_family(dst)))
- ereport(ERROR,
+ ereturn(escontext, NULL,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid cidr value: \"%s\"", src),
errdetail("Value has bits set to right of mask.")));
{
char *src = PG_GETARG_CSTRING(0);
- PG_RETURN_INET_P(network_in(src, false));
+ PG_RETURN_INET_P(network_in(src, false, fcinfo->context));
}
Datum
{
char *src = PG_GETARG_CSTRING(0);
- PG_RETURN_INET_P(network_in(src, true));
+ PG_RETURN_INET_P(network_in(src, true, fcinfo->context));
}
clean_ipv6_addr(port->raddr.addr.ss_family, remote_host);
- PG_RETURN_INET_P(network_in(remote_host, false));
+ PG_RETURN_INET_P(network_in(remote_host, false, NULL));
}
clean_ipv6_addr(port->laddr.addr.ss_family, local_host);
- PG_RETURN_INET_P(network_in(local_host, false));
+ PG_RETURN_INET_P(network_in(local_host, false, NULL));
}
bit_in(PG_FUNCTION_ARGS)
{
char *input_string = PG_GETARG_CSTRING(0);
-
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
#endif
int32 atttypmod = PG_GETARG_INT32(2);
+ Node *escontext = fcinfo->context;
VarBit *result; /* The resulting bit string */
char *sp; /* pointer into the character string */
bits8 *r; /* pointer into the result */
else
{
if (slen > VARBITMAXLEN / 4)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("bit string length exceeds the maximum allowed (%d)",
VARBITMAXLEN)));
if (atttypmod <= 0)
atttypmod = bitlen;
else if (bitlen != atttypmod)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
errmsg("bit string length %d does not match type bit(%d)",
bitlen, atttypmod)));
if (*sp == '1')
*r |= x;
else if (*sp != '0')
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("\"%.*s\" is not a valid binary digit",
pg_mblen(sp), sp)));
else if (*sp >= 'a' && *sp <= 'f')
x = (bits8) (*sp - 'a') + 10;
else
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("\"%.*s\" is not a valid hexadecimal digit",
pg_mblen(sp), sp)));
varbit_in(PG_FUNCTION_ARGS)
{
char *input_string = PG_GETARG_CSTRING(0);
-
#ifdef NOT_USED
Oid typelem = PG_GETARG_OID(1);
#endif
int32 atttypmod = PG_GETARG_INT32(2);
+ Node *escontext = fcinfo->context;
VarBit *result; /* The resulting bit string */
char *sp; /* pointer into the character string */
bits8 *r; /* pointer into the result */
else
{
if (slen > VARBITMAXLEN / 4)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("bit string length exceeds the maximum allowed (%d)",
VARBITMAXLEN)));
if (atttypmod <= 0)
atttypmod = bitlen;
else if (bitlen > atttypmod)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("bit string too long for type bit varying(%d)",
atttypmod)));
if (*sp == '1')
*r |= x;
else if (*sp != '0')
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("\"%.*s\" is not a valid binary digit",
pg_mblen(sp), sp)));
else if (*sp >= 'a' && *sp <= 'f')
x = (bits8) (*sp - 'a') + 10;
else
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("\"%.*s\" is not a valid hexadecimal digit",
pg_mblen(sp), sp)));
1001 | 0101 | 1001 | 0101
(1 row)
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('01010001', 'bit(10)');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('01010001', 'bit(10)');
+ pg_input_error_message
+-------------------------------------------------
+ bit string length 8 does not match type bit(10)
+(1 row)
+
+SELECT pg_input_is_valid('01010Z01', 'bit(8)');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('01010Z01', 'bit(8)');
+ pg_input_error_message
+---------------------------------
+ "Z" is not a valid binary digit
+(1 row)
+
+SELECT pg_input_is_valid('x01010Z01', 'bit(32)');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('x01010Z01', 'bit(32)');
+ pg_input_error_message
+--------------------------------------
+ "Z" is not a valid hexadecimal digit
+(1 row)
+
+SELECT pg_input_is_valid('01010Z01', 'varbit');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('01010Z01', 'varbit');
+ pg_input_error_message
+---------------------------------
+ "Z" is not a valid binary digit
+(1 row)
+
+SELECT pg_input_is_valid('x01010Z01', 'varbit');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('x01010Z01', 'varbit');
+ pg_input_error_message
+--------------------------------------
+ "Z" is not a valid hexadecimal digit
+(1 row)
+
ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
(91 rows)
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('1234', 'cidr');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('1234', 'cidr');
+ pg_input_error_message
+--------------------------------------------
+ invalid input syntax for type cidr: "1234"
+(1 row)
+
+SELECT pg_input_is_valid('192.168.198.200/24', 'cidr');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('192.168.198.200/24', 'cidr');
+ pg_input_error_message
+------------------------------------------
+ invalid cidr value: "192.168.198.200/24"
+(1 row)
+
+SELECT pg_input_is_valid('1234', 'inet');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('1234', 'inet');
+ pg_input_error_message
+--------------------------------------------
+ invalid input syntax for type inet: "1234"
+(1 row)
+
(12 rows)
DROP TABLE macaddr_data;
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('08:00:2b:01:02:ZZ', 'macaddr');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('08:00:2b:01:02:ZZ', 'macaddr');
+ pg_input_error_message
+------------------------------------------------------------
+ invalid input syntax for type macaddr: "08:00:2b:01:02:ZZ"
+(1 row)
+
+SELECT pg_input_is_valid('08:00:2b:01:02:', 'macaddr');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('08:00:2b:01:02:', 'macaddr');
+ pg_input_error_message
+----------------------------------------------------------
+ invalid input syntax for type macaddr: "08:00:2b:01:02:"
+(1 row)
+
(20 rows)
DROP TABLE macaddr8_data;
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('08:00:2b:01:02:03:04:ZZ', 'macaddr8');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('08:00:2b:01:02:03:04:ZZ', 'macaddr8');
+ pg_input_error_message
+-------------------------------------------------------------------
+ invalid input syntax for type macaddr8: "08:00:2b:01:02:03:04:ZZ"
+(1 row)
+
+SELECT pg_input_is_valid('08:00:2b:01:02:03:04:', 'macaddr8');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT pg_input_error_message('08:00:2b:01:02:03:04:', 'macaddr8');
+ pg_input_error_message
+-----------------------------------------------------------------
+ invalid input syntax for type macaddr8: "08:00:2b:01:02:03:04:"
+(1 row)
+
\d bit_defaults
INSERT INTO bit_defaults DEFAULT VALUES;
TABLE bit_defaults;
+
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('01010001', 'bit(10)');
+SELECT pg_input_error_message('01010001', 'bit(10)');
+SELECT pg_input_is_valid('01010Z01', 'bit(8)');
+SELECT pg_input_error_message('01010Z01', 'bit(8)');
+SELECT pg_input_is_valid('x01010Z01', 'bit(32)');
+SELECT pg_input_error_message('x01010Z01', 'bit(32)');
+
+SELECT pg_input_is_valid('01010Z01', 'varbit');
+SELECT pg_input_error_message('01010Z01', 'varbit');
+SELECT pg_input_is_valid('x01010Z01', 'varbit');
+SELECT pg_input_error_message('x01010Z01', 'varbit');
('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/0'::inet),
('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128'::inet)
) AS i(a) ORDER BY a;
+
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('1234', 'cidr');
+SELECT pg_input_error_message('1234', 'cidr');
+SELECT pg_input_is_valid('192.168.198.200/24', 'cidr');
+SELECT pg_input_error_message('192.168.198.200/24', 'cidr');
+
+SELECT pg_input_is_valid('1234', 'inet');
+SELECT pg_input_error_message('1234', 'inet');
SELECT b | '01:02:03:04:05:06' FROM macaddr_data;
DROP TABLE macaddr_data;
+
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('08:00:2b:01:02:ZZ', 'macaddr');
+SELECT pg_input_error_message('08:00:2b:01:02:ZZ', 'macaddr');
+SELECT pg_input_is_valid('08:00:2b:01:02:', 'macaddr');
+SELECT pg_input_error_message('08:00:2b:01:02:', 'macaddr');
SELECT b | '01:02:03:04:05:06' FROM macaddr8_data;
DROP TABLE macaddr8_data;
+
+-- test non-error-throwing API for some core types
+SELECT pg_input_is_valid('08:00:2b:01:02:03:04:ZZ', 'macaddr8');
+SELECT pg_input_error_message('08:00:2b:01:02:03:04:ZZ', 'macaddr8');
+SELECT pg_input_is_valid('08:00:2b:01:02:03:04:', 'macaddr8');
+SELECT pg_input_error_message('08:00:2b:01:02:03:04:', 'macaddr8');