@@ -640,6 +640,137 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
640640 return relId ;
641641}
642642
643+ /* safe version of RangeVarGetRelidExtended */
644+ Oid
645+ RangeVarGetRelidExtendedSafe (const RangeVar * relation , LOCKMODE lockmode ,
646+ uint32 flags , RangeVarGetRelidCallback callback , void * callback_arg ,
647+ Node * escontext )
648+ {
649+ uint64 inval_count ;
650+ Oid relId ;
651+ Oid oldRelId = InvalidOid ;
652+ bool retry = false;
653+ bool missing_ok = (flags & RVR_MISSING_OK ) != 0 ;
654+
655+ /* verify that flags do no conflict */
656+ Assert (!((flags & RVR_NOWAIT ) && (flags & RVR_SKIP_LOCKED )));
657+
658+ /*
659+ * We check the catalog name and then ignore it.
660+ */
661+ if (relation -> catalogname )
662+ {
663+ if (strcmp (relation -> catalogname , get_database_name (MyDatabaseId )) != 0 )
664+ ereturn (escontext , InvalidOid ,
665+ errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
666+ errmsg ("cross-database references are not implemented: \"%s.%s.%s\"" ,
667+ relation -> catalogname , relation -> schemaname ,
668+ relation -> relname ));
669+ }
670+
671+ for (;;)
672+ {
673+ inval_count = SharedInvalidMessageCounter ;
674+
675+ if (relation -> relpersistence == RELPERSISTENCE_TEMP )
676+ {
677+ if (!OidIsValid (myTempNamespace ))
678+ relId = InvalidOid ;
679+ else
680+ {
681+ if (relation -> schemaname )
682+ {
683+ Oid namespaceId ;
684+
685+ namespaceId = LookupExplicitNamespace (relation -> schemaname , missing_ok );
686+
687+ /*
688+ * For missing_ok, allow a non-existent schema name to
689+ * return InvalidOid.
690+ */
691+ if (namespaceId != myTempNamespace )
692+ ereturn (escontext , InvalidOid ,
693+ errcode (ERRCODE_INVALID_TABLE_DEFINITION ),
694+ errmsg ("temporary tables cannot specify a schema name" ));
695+ }
696+
697+ relId = get_relname_relid (relation -> relname , myTempNamespace );
698+ }
699+ }
700+ else if (relation -> schemaname )
701+ {
702+ Oid namespaceId ;
703+
704+ /* use exact schema given */
705+ namespaceId = LookupExplicitNamespace (relation -> schemaname , missing_ok );
706+ if (missing_ok && !OidIsValid (namespaceId ))
707+ relId = InvalidOid ;
708+ else
709+ relId = get_relname_relid (relation -> relname , namespaceId );
710+ }
711+ else
712+ {
713+ /* search the namespace path */
714+ relId = RelnameGetRelid (relation -> relname );
715+ }
716+
717+ if (callback )
718+ callback (relation , relId , oldRelId , callback_arg );
719+
720+ if (lockmode == NoLock )
721+ break ;
722+
723+ if (retry )
724+ {
725+ if (relId == oldRelId )
726+ break ;
727+ if (OidIsValid (oldRelId ))
728+ UnlockRelationOid (oldRelId , lockmode );
729+ }
730+
731+ if (!OidIsValid (relId ))
732+ AcceptInvalidationMessages ();
733+ else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED )))
734+ LockRelationOid (relId , lockmode );
735+ else if (!ConditionalLockRelationOid (relId , lockmode ))
736+ {
737+ if (relation -> schemaname )
738+ ereport (DEBUG1 ,
739+ errcode (ERRCODE_LOCK_NOT_AVAILABLE ),
740+ errmsg ("could not obtain lock on relation \"%s.%s\"" ,
741+ relation -> schemaname , relation -> relname ));
742+ else
743+ ereport (DEBUG1 ,
744+ errcode (ERRCODE_LOCK_NOT_AVAILABLE ),
745+ errmsg ("could not obtain lock on relation \"%s\"" ,
746+ relation -> relname ));
747+
748+ return InvalidOid ;
749+ }
750+
751+ if (inval_count == SharedInvalidMessageCounter )
752+ break ;
753+
754+ retry = true;
755+ oldRelId = relId ;
756+ }
757+
758+ if (!OidIsValid (relId ))
759+ {
760+ if (relation -> schemaname )
761+ ereturn (escontext , InvalidOid ,
762+ errcode (ERRCODE_UNDEFINED_TABLE ),
763+ errmsg ("relation \"%s.%s\" does not exist" ,
764+ relation -> schemaname , relation -> relname ));
765+ else
766+ ereturn (escontext , InvalidOid ,
767+ errcode (ERRCODE_UNDEFINED_TABLE ),
768+ errmsg ("relation \"%s\" does not exist" ,
769+ relation -> relname ));
770+ }
771+ return relId ;
772+ }
773+
643774/*
644775 * RangeVarGetCreationNamespace
645776 * Given a RangeVar describing a to-be-created relation,
@@ -3650,6 +3781,42 @@ makeRangeVarFromNameList(const List *names)
36503781 return rel ;
36513782}
36523783
3784+ /*
3785+ * makeRangeVarFromNameListSafe
3786+ * Utility routine to convert a qualified-name list into RangeVar form.
3787+ * The result maybe NULL.
3788+ */
3789+ RangeVar *
3790+ makeRangeVarFromNameListSafe (const List * names , Node * escontext )
3791+ {
3792+ RangeVar * rel = makeRangeVar (NULL , NULL , -1 );
3793+
3794+ switch (list_length (names ))
3795+ {
3796+ case 1 :
3797+ rel -> relname = strVal (linitial (names ));
3798+ break ;
3799+ case 2 :
3800+ rel -> schemaname = strVal (linitial (names ));
3801+ rel -> relname = strVal (lsecond (names ));
3802+ break ;
3803+ case 3 :
3804+ rel -> catalogname = strVal (linitial (names ));
3805+ rel -> schemaname = strVal (lsecond (names ));
3806+ rel -> relname = strVal (lthird (names ));
3807+ break ;
3808+ default :
3809+ errsave (escontext ,
3810+ errcode (ERRCODE_SYNTAX_ERROR ),
3811+ errmsg ("improper relation name (too many dotted names): %s" ,
3812+ NameListToString (names )));
3813+ rel = NULL ;
3814+ break ;
3815+ }
3816+
3817+ return rel ;
3818+ }
3819+
36533820/*
36543821 * NameListToString
36553822 * Utility routine to convert a qualified-name list into a string.
0 commit comments