diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 5b225ccf4f5f1..31321f27b0ba4 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -24872,7 +24872,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype); - + format_type @@ -25570,7 +25570,7 @@ SELECT collation for ('foo' COLLATE "de_DE"); - + to_regtype @@ -25578,13 +25578,53 @@ SELECT collation for ('foo' COLLATE "de_DE"); regtype - Translates a textual type name to its OID. A similar result is - obtained by casting the string to type regtype (see - ); however, this function will return - NULL rather than throwing an error if the name is - not found. + Parses a string of text, extracts a potential type name from it, and + translates that name into an OID. A similar result is obtained by + casting the string to type regtype (see + ). Failure to extract a valid potential + type name results in an error. For example: + +SELECT to_regtype('interval nonesuch'); +ERROR: syntax error at or near "nonesuch" +LINE 1: select to_regtype('interval nonesuch'); + ^ +CONTEXT: invalid type name "interval nonesuch" + + However, if the extracted name is not known to the system, this function + will return NULL. For example: + +SELECT to_regtype('party'); + to_regtype +------------ + + + + + + + + + to_regtypemod + + to_regtypemod ( text ) + integer + + + Parses a string of text, extracts a potential type name from it, and + translates its type modifier, if any. Failure to extract a valid + potential type name results in an error; however, if the extracted name + is not known to the system, this function will return + NULL. Complements , and + can be passed to . For example: + +SELECT format_type(to_regtype('varchar(32)'), to_regtypemod('varchar(32)')); + format_type +----------------------- + character varying(32) + + diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl index 94afdc5491dd8..a0c299f067b6b 100644 --- a/src/backend/catalog/genbki.pl +++ b/src/backend/catalog/genbki.pl @@ -1098,7 +1098,7 @@ sub lookup_oids { warn sprintf "unresolved OID reference \"%s\" in %s.dat field %s line %s\n", - $lookupname, $catname, $attname, $bki_values->{line_number}; + $lookupname || '', $catname || '', $attname || '', $bki_values->{line_number} || ''; $num_errors++; } } diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 1e3bf3f5fd6f6..75b8429e0d240 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -1220,6 +1220,35 @@ to_regtype(PG_FUNCTION_ARGS) PG_RETURN_DATUM(result); } + +/* + * to_regtypemod() complements to_regtype, returning the typmod for the type, + * if any. + * + * If the type name is not found, we return NULL. + * + * Internally it relies on the Postgres core parseTypeString() function defined + * in src/backend/parser/parse_type.c. + */ +Datum +to_regtypemod(PG_FUNCTION_ARGS) +{ + char *typ_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + Oid typid; + int32 typmod; + ErrorSaveContext escontext = {T_ErrorSaveContext}; + + /* + * Parse type-name argument to obtain the encoded typmod. Return NULL + * on failure. + */ + if (!parseTypeString(typ_name, &typid, &typmod, (Node *) &escontext)) { + PG_RETURN_NULL(); + } + + PG_RETURN_INT32(typmod); +} + /* * regtypeout - converts type OID to "typ_name" */ diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 177d81a891c33..770591c7346ee 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7155,6 +7155,9 @@ { oid => '3493', descr => 'convert type name to regtype', proname => 'to_regtype', provolatile => 's', prorettype => 'regtype', proargtypes => 'text', prosrc => 'to_regtype' }, +{ oid => '8401', descr => 'convert type name to type mod', + proname => 'to_regtypemod', provolatile => 's', prorettype => 'int4', + proargtypes => 'text', prosrc => 'to_regtypemod' }, { oid => '1079', descr => 'convert text to regclass', proname => 'regclass', provolatile => 's', prorettype => 'regclass', proargtypes => 'text', prosrc => 'text_regclass' }, diff --git a/src/test/regress/expected/regproc.out b/src/test/regress/expected/regproc.out index a9420850b87ec..ff1ee5b52c531 100644 --- a/src/test/regress/expected/regproc.out +++ b/src/test/regress/expected/regproc.out @@ -544,3 +544,69 @@ SELECT * FROM pg_input_error_info('way.too.many.names', 'regtype'); ERROR: improper qualified name (too many dotted names): way.too.many.names SELECT * FROM pg_input_error_info('no_such_catalog.schema.name', 'regtype'); ERROR: cross-database references are not implemented: no_such_catalog.schema.name +-- Test to_regtypemod +SELECT to_regtypemod('text'); + to_regtypemod +--------------- + -1 +(1 row) + +SELECT to_regtypemod('timestamp(4)'); + to_regtypemod +--------------- + 4 +(1 row) + +SELECT to_regtypemod('interval(0)'); + to_regtypemod +--------------- + 2147418112 +(1 row) + +SELECT to_regtypemod('interval second(0)'); + to_regtypemod +--------------- + 268435456 +(1 row) + +SELECT to_regtypemod('timestamptz'); + to_regtypemod +--------------- + -1 +(1 row) + +SELECT to_regtypemod('timestamptz(6)'); + to_regtypemod +--------------- + 6 +(1 row) + +SELECT to_regtypemod('varchar'); + to_regtypemod +--------------- + -1 +(1 row) + +SELECT to_regtypemod('varchar(128)'); + to_regtypemod +--------------- + 132 +(1 row) + +SELECT to_regtypemod(NULL); -- returns null on null input + to_regtypemod +--------------- + +(1 row) + +SELECT to_regtypemod('year(4)'); -- error trapped, returns null + to_regtypemod +--------------- + +(1 row) + +SELECT to_regtypemod('interval nonesuch'); -- grammar error raised, not trapped +ERROR: syntax error at or near "nonesuch" +LINE 1: SELECT to_regtypemod('interval nonesuch'); + ^ +CONTEXT: invalid type name "interval nonesuch" diff --git a/src/test/regress/sql/regproc.sql b/src/test/regress/sql/regproc.sql index de2aa881a8dc0..c1717e1f8fc43 100644 --- a/src/test/regress/sql/regproc.sql +++ b/src/test/regress/sql/regproc.sql @@ -145,3 +145,17 @@ SELECT * FROM pg_input_error_info('incorrect type name syntax', 'regtype'); SELECT * FROM pg_input_error_info('numeric(1,2,3)', 'regtype'); -- bogus typmod SELECT * FROM pg_input_error_info('way.too.many.names', 'regtype'); SELECT * FROM pg_input_error_info('no_such_catalog.schema.name', 'regtype'); + +-- Test to_regtypemod +SELECT to_regtypemod('text'); +SELECT to_regtypemod('timestamp(4)'); +SELECT to_regtypemod('interval(0)'); +SELECT to_regtypemod('interval second(0)'); +SELECT to_regtypemod('timestamptz'); +SELECT to_regtypemod('timestamptz(6)'); +SELECT to_regtypemod('varchar'); +SELECT to_regtypemod('varchar(128)'); + +SELECT to_regtypemod(NULL); -- returns null on null input +SELECT to_regtypemod('year(4)'); -- error trapped, returns null +SELECT to_regtypemod('interval nonesuch'); -- grammar error raised, not trapped