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

Commit0886fc6

Browse files
committed
Add new to_reg* functions for error-free OID lookups.
These functions won't throw an error if the object doesn't exist,or if (for functions and operators) there's more than one matchingobject.Yugo Nagata and Nozomi Anzai, reviewed by Amit Khandekar, MartiRaudsepp, Amit Kapila, and me.
1 parent7ca32e2 commit0886fc6

File tree

18 files changed

+457
-19
lines changed

18 files changed

+457
-19
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15279,6 +15279,22 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
1527915279
<primary>collation for</primary>
1528015280
</indexterm>
1528115281

15282+
<indexterm>
15283+
<primary>to_regclass</primary>
15284+
</indexterm>
15285+
15286+
<indexterm>
15287+
<primary>to_regproc</primary>
15288+
</indexterm>
15289+
15290+
<indexterm>
15291+
<primary>to_regoper</primary>
15292+
</indexterm>
15293+
15294+
<indexterm>
15295+
<primary>to_regtype</primary>
15296+
</indexterm>
15297+
1528215298
<para>
1528315299
<xref linkend="functions-info-catalog-table"> lists functions that
1528415300
extract information from the system catalogs.
@@ -15449,6 +15465,26 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
1544915465
<entry><type>text</type></entry>
1545015466
<entry>get the collation of the argument</entry>
1545115467
</row>
15468+
<row>
15469+
<entry><literal><function>to_regclass(<parameter>rel_name</parameter>)</function></literal></entry>
15470+
<entry><type>regclass</type></entry>
15471+
<entry>get the oid of the named relation</entry>
15472+
</row>
15473+
<row>
15474+
<entry><literal><function>to_regproc(<parameter>func_name</parameter>)</function></literal></entry>
15475+
<entry><type>regproc</type></entry>
15476+
<entry>get the oid of the named function</entry>
15477+
</row>
15478+
<row>
15479+
<entry><literal><function>to_regoper(<parameter>operator_name</parameter>)</function></literal></entry>
15480+
<entry><type>regoper</type></entry>
15481+
<entry>get the oid of the named operator</entry>
15482+
</row>
15483+
<row>
15484+
<entry><literal><function>to_regtype(<parameter>type_name</parameter>)</function></literal></entry>
15485+
<entry><type>regtype</type></entry>
15486+
<entry>get the oid of the named type</entry>
15487+
</row>
1545215488
</tbody>
1545315489
</tgroup>
1545415490
</table>
@@ -15614,6 +15650,18 @@ SELECT collation for ('foo' COLLATE "de_DE");
1561415650
is not of a collatable data type, then an error is raised.
1561515651
</para>
1561615652

15653+
<para>
15654+
The <function>to_regclass</function>, <function>to_regproc</function>,
15655+
<function>to_regoper</function> and <function>to_regtype</function>
15656+
translate relation, function, operator, and type names to objects of
15657+
type <type>regclass</>, <type>regproc</>, <type>regoper</> and
15658+
<type>regtype</>, respectively. These functions differ from a cast from
15659+
text in that they don't accept a numeric OID, and that they return null
15660+
rather than throwing an error if the name is not found (or, for
15661+
<function>to_regproc</function> and <function>to_regoper</function>, if
15662+
the given name matches multiple objects).
15663+
</para>
15664+
1561715665
<indexterm>
1561815666
<primary>col_description</primary>
1561915667
</indexterm>

‎src/backend/catalog/namespace.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
15561556
* will be InvalidOid for a prefix or postfix oprkind.nargs is 2, too.
15571557
*/
15581558
FuncCandidateList
1559-
OpernameGetCandidates(List*names,charoprkind)
1559+
OpernameGetCandidates(List*names,charoprkind,boolmissing_schema_ok)
15601560
{
15611561
FuncCandidateListresultList=NULL;
15621562
char*resultSpace=NULL;
@@ -1573,7 +1573,9 @@ OpernameGetCandidates(List *names, char oprkind)
15731573
if (schemaname)
15741574
{
15751575
/* use exact schema given */
1576-
namespaceId=LookupExplicitNamespace(schemaname, false);
1576+
namespaceId=LookupExplicitNamespace(schemaname,missing_schema_ok);
1577+
if (missing_schema_ok&& !OidIsValid(namespaceId))
1578+
returnNULL;
15771579
}
15781580
else
15791581
{

‎src/backend/parser/parse_oper.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
407407
FuncCandidateListclist;
408408

409409
/* Get binary operators of given name */
410-
clist=OpernameGetCandidates(opname,'b');
410+
clist=OpernameGetCandidates(opname,'b', false);
411411

412412
/* No operators found? Then fail... */
413413
if (clist!=NULL)
@@ -553,7 +553,7 @@ right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
553553
FuncCandidateListclist;
554554

555555
/* Get postfix operators of given name */
556-
clist=OpernameGetCandidates(op,'r');
556+
clist=OpernameGetCandidates(op,'r', false);
557557

558558
/* No operators found? Then fail... */
559559
if (clist!=NULL)
@@ -631,7 +631,7 @@ left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
631631
FuncCandidateListclist;
632632

633633
/* Get prefix operators of given name */
634-
clist=OpernameGetCandidates(op,'l');
634+
clist=OpernameGetCandidates(op,'l', false);
635635

636636
/* No operators found? Then fail... */
637637
if (clist!=NULL)

‎src/backend/parser/parse_type.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,9 +706,12 @@ pts_error_callback(void *arg)
706706
* Given a string that is supposed to be a SQL-compatible type declaration,
707707
* such as "int4" or "integer" or "character varying(32)", parse
708708
* the string and convert it to a type OID and type modifier.
709+
* If missing_ok is true, InvalidOid is returned rather than raising an error
710+
* when the type name is not found.
709711
*/
710712
void
711-
parseTypeString(constchar*str,Oid*typeid_p,int32*typmod_p)
713+
parseTypeString(constchar*str,Oid*typeid_p,int32*typmod_p,
714+
boolmissing_ok)
712715
{
713716
StringInfoDatabuf;
714717
List*raw_parsetree_list;
@@ -717,6 +720,7 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
717720
TypeCast*typecast;
718721
TypeName*typeName;
719722
ErrorContextCallbackptserrcontext;
723+
Typetup;
720724

721725
/* make sure we give useful error for empty input */
722726
if (strspn(str," \t\n\r\f")==strlen(str))
@@ -782,7 +786,28 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p)
782786
if (typeName->setof)
783787
gotofail;
784788

785-
typenameTypeIdAndMod(NULL,typeName,typeid_p,typmod_p);
789+
tup=LookupTypeName(NULL,typeName,typmod_p,missing_ok);
790+
if (tup==NULL)
791+
{
792+
if (!missing_ok)
793+
ereport(ERROR,
794+
(errcode(ERRCODE_UNDEFINED_OBJECT),
795+
errmsg("type \"%s\" does not exist",
796+
TypeNameToString(typeName)),
797+
parser_errposition(NULL,typeName->location)));
798+
*typeid_p=InvalidOid;
799+
}
800+
else
801+
{
802+
if (!((Form_pg_type)GETSTRUCT(tup))->typisdefined)
803+
ereport(ERROR,
804+
(errcode(ERRCODE_UNDEFINED_OBJECT),
805+
errmsg("type \"%s\" is only a shell",
806+
TypeNameToString(typeName)),
807+
parser_errposition(NULL,typeName->location)));
808+
*typeid_p=HeapTupleGetOid(tup);
809+
ReleaseSysCache(tup);
810+
}
786811

787812
pfree(buf.data);
788813

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

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,31 @@ regprocin(PG_FUNCTION_ARGS)
152152
PG_RETURN_OID(result);
153153
}
154154

155+
/*
156+
* to_regproc- converts "proname" to proc OID
157+
*
158+
* If the name is not found, we return NULL.
159+
*/
160+
Datum
161+
to_regproc(PG_FUNCTION_ARGS)
162+
{
163+
char*pro_name=PG_GETARG_CSTRING(0);
164+
List*names;
165+
FuncCandidateListclist;
166+
167+
/*
168+
* Parse the name into components and see if it matches any pg_proc entries
169+
* in the current search path.
170+
*/
171+
names=stringToQualifiedNameList(pro_name);
172+
clist=FuncnameGetCandidates(names,-1,NIL, false, false, true);
173+
174+
if (clist==NULL||clist->next!=NULL)
175+
PG_RETURN_NULL();
176+
177+
PG_RETURN_OID(clist->oid);
178+
}
179+
155180
/*
156181
* regprocout- converts proc OID to "pro_name"
157182
*/
@@ -502,7 +527,7 @@ regoperin(PG_FUNCTION_ARGS)
502527
* pg_operator entries in the current search path.
503528
*/
504529
names=stringToQualifiedNameList(opr_name_or_oid);
505-
clist=OpernameGetCandidates(names,'\0');
530+
clist=OpernameGetCandidates(names,'\0', false);
506531

507532
if (clist==NULL)
508533
ereport(ERROR,
@@ -519,6 +544,31 @@ regoperin(PG_FUNCTION_ARGS)
519544
PG_RETURN_OID(result);
520545
}
521546

547+
/*
548+
* to_regoper- converts "oprname" to operator OID
549+
*
550+
* If the name is not found, we return NULL.
551+
*/
552+
Datum
553+
to_regoper(PG_FUNCTION_ARGS)
554+
{
555+
char*opr_name=PG_GETARG_CSTRING(0);
556+
List*names;
557+
FuncCandidateListclist;
558+
559+
/*
560+
* Parse the name into components and see if it matches any pg_operator
561+
* entries in the current search path.
562+
*/
563+
names=stringToQualifiedNameList(opr_name);
564+
clist=OpernameGetCandidates(names,'\0', true);
565+
566+
if (clist==NULL||clist->next!=NULL)
567+
PG_RETURN_NULL();
568+
569+
PG_RETURN_OID(clist->oid);
570+
}
571+
522572
/*
523573
* regoperout- converts operator OID to "opr_name"
524574
*/
@@ -558,7 +608,7 @@ regoperout(PG_FUNCTION_ARGS)
558608
* qualify it.
559609
*/
560610
clist=OpernameGetCandidates(list_make1(makeString(oprname)),
561-
'\0');
611+
'\0', false);
562612
if (clist!=NULL&&clist->next==NULL&&
563613
clist->oid==oprid)
564614
result=pstrdup(oprname);
@@ -872,6 +922,33 @@ regclassin(PG_FUNCTION_ARGS)
872922
PG_RETURN_OID(result);
873923
}
874924

925+
/*
926+
* to_regclass- converts "classname" to class OID
927+
*
928+
* If the name is not found, we return NULL.
929+
*/
930+
Datum
931+
to_regclass(PG_FUNCTION_ARGS)
932+
{
933+
char*class_name=PG_GETARG_CSTRING(0);
934+
Oidresult;
935+
List*names;
936+
937+
/*
938+
* Parse the name into components and see if it matches any pg_class entries
939+
* in the current search path.
940+
*/
941+
names=stringToQualifiedNameList(class_name);
942+
943+
/* We might not even have permissions on this relation; don't lock it. */
944+
result=RangeVarGetRelid(makeRangeVarFromNameList(names),NoLock, true);
945+
946+
if (OidIsValid(result))
947+
PG_RETURN_OID(result);
948+
else
949+
PG_RETURN_NULL();
950+
}
951+
875952
/*
876953
* regclassout- converts class OID to "class_name"
877954
*/
@@ -1028,11 +1105,34 @@ regtypein(PG_FUNCTION_ARGS)
10281105
* Normal case: invoke the full parser to deal with special cases such as
10291106
* array syntax.
10301107
*/
1031-
parseTypeString(typ_name_or_oid,&result,&typmod);
1108+
parseTypeString(typ_name_or_oid,&result,&typmod, false);
10321109

10331110
PG_RETURN_OID(result);
10341111
}
10351112

1113+
/*
1114+
* to_regtype- converts "typename" to type OID
1115+
*
1116+
* If the name is not found, we return NULL.
1117+
*/
1118+
Datum
1119+
to_regtype(PG_FUNCTION_ARGS)
1120+
{
1121+
char*typ_name=PG_GETARG_CSTRING(0);
1122+
Oidresult;
1123+
int32typmod;
1124+
1125+
/*
1126+
* Invoke the full parser to deal with special cases such as array syntax.
1127+
*/
1128+
parseTypeString(typ_name,&result,&typmod, true);
1129+
1130+
if (OidIsValid(result))
1131+
PG_RETURN_OID(result);
1132+
else
1133+
PG_RETURN_NULL();
1134+
}
1135+
10361136
/*
10371137
* regtypeout- converts type OID to "typ_name"
10381138
*/
@@ -1523,7 +1623,7 @@ parseNameAndArgTypes(const char *string, bool allowNone, List **names,
15231623
else
15241624
{
15251625
/* Use full parser to resolve the type name */
1526-
parseTypeString(typename,&typeid,&typmod);
1626+
parseTypeString(typename,&typeid,&typmod, false);
15271627
}
15281628
if (*nargs >=FUNC_MAX_ARGS)
15291629
ereport(ERROR,

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO201404031
56+
#defineCATALOG_VERSION_NO201404081
5757

5858
#endif

‎src/include/catalog/namespace.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ extern FuncCandidateList FuncnameGetCandidates(List *names,
7676
externboolFunctionIsVisible(Oidfuncid);
7777

7878
externOidOpernameGetOprid(List*names,Oidoprleft,Oidoprright);
79-
externFuncCandidateListOpernameGetCandidates(List*names,charoprkind);
79+
externFuncCandidateListOpernameGetCandidates(List*names,charoprkind,
80+
boolmissing_schema_ok);
8081
externboolOperatorIsVisible(Oidoprid);
8182

8283
externOidOpclassnameGetOpcid(Oidamid,constchar*opcname);

‎src/include/catalog/pg_proc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ DATA(insert OID = 44 ( regprocin PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0
173173
DESCR("I/O");
174174
DATA(insertOID=45 (regprocoutPGNSPPGUID121000fffftfs102275"24"_null__null__null__null_regprocout_null__null__null_ ));
175175
DESCR("I/O");
176+
DATA(insertOID=3494 (to_regprocPGNSPPGUID121000fffftfs1024"2275"_null__null__null__null_to_regproc_null__null__null_ ));
177+
DESCR("convert proname to regproc");
176178
DATA(insertOID=46 (textinPGNSPPGUID121000fffftfi1025"2275"_null__null__null__null_textin_null__null__null_ ));
177179
DESCR("I/O");
178180
DATA(insertOID=47 (textoutPGNSPPGUID121000fffftfi102275"25"_null__null__null__null_textout_null__null__null_ ));
@@ -3304,6 +3306,8 @@ DATA(insert OID = 2214 ( regoperinPGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
33043306
DESCR("I/O");
33053307
DATA(insertOID=2215 (regoperoutPGNSPPGUID121000fffftfs102275"2203"_null__null__null__null_regoperout_null__null__null_ ));
33063308
DESCR("I/O");
3309+
DATA(insertOID=3492 (to_regoperPGNSPPGUID121000fffftfs102203"2275"_null__null__null__null_to_regoper_null__null__null_ ));
3310+
DESCR("convert operator name to regoper");
33073311
DATA(insertOID=2216 (regoperatorinPGNSPPGUID121000fffftfs102204"2275"_null__null__null__null_regoperatorin_null__null__null_ ));
33083312
DESCR("I/O");
33093313
DATA(insertOID=2217 (regoperatoroutPGNSPPGUID121000fffftfs102275"2204"_null__null__null__null_regoperatorout_null__null__null_ ));
@@ -3312,10 +3316,14 @@ DATA(insert OID = 2218 ( regclassinPGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2
33123316
DESCR("I/O");
33133317
DATA(insertOID=2219 (regclassoutPGNSPPGUID121000fffftfs102275"2205"_null__null__null__null_regclassout_null__null__null_ ));
33143318
DESCR("I/O");
3319+
DATA(insertOID=3495 (to_regclassPGNSPPGUID121000fffftfs102205"2275"_null__null__null__null_to_regclass_null__null__null_ ));
3320+
DESCR("convert classname to regclass");
33153321
DATA(insertOID=2220 (regtypeinPGNSPPGUID121000fffftfs102206"2275"_null__null__null__null_regtypein_null__null__null_ ));
33163322
DESCR("I/O");
33173323
DATA(insertOID=2221 (regtypeoutPGNSPPGUID121000fffftfs102275"2206"_null__null__null__null_regtypeout_null__null__null_ ));
33183324
DESCR("I/O");
3325+
DATA(insertOID=3493 (to_regtypePGNSPPGUID121000fffftfs102206"2275"_null__null__null__null_to_regtype_null__null__null_ ));
3326+
DESCR("convert type name to regtype");
33193327
DATA(insertOID=1079 (regclassPGNSPPGUID121000fffftfs102205"25"_null__null__null__null_text_regclass_null__null__null_ ));
33203328
DESCR("convert text to regclass");
33213329

‎src/include/parser/parse_type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod);
4747

4848
externOidtypeidTypeRelid(Oidtype_id);
4949

50-
externvoidparseTypeString(constchar*str,Oid*typeid_p,int32*typmod_p);
50+
externvoidparseTypeString(constchar*str,Oid*typeid_p,int32*typmod_p,boolmissing_ok);
5151

5252
#defineISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
5353

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp