3030#include " ../dsql/errd_proto.h"
3131#include " ../dsql/gen_proto.h"
3232#include " ../dsql/make_proto.h"
33+ #include " ../dsql/metd_proto.h"
3334#include " ../dsql/pass1_proto.h"
35+ #include < unordered_set>
3436
3537using namespace Firebird ;
3638using namespace Jrd ;
@@ -72,7 +74,7 @@ void DsqlCompilerScratch::qualifyNewName(QualifiedName& name) const
7274 }
7375}
7476
75- void DsqlCompilerScratch::qualifyExistingName (QualifiedName& name, ObjectType objectType )
77+ void DsqlCompilerScratch::qualifyExistingName (QualifiedName& name, std::initializer_list< ObjectType> objectTypes )
7678{
7779 if (!(name.schema .isEmpty () && name.object .hasData ()))
7880 return ;
@@ -96,10 +98,123 @@ void DsqlCompilerScratch::qualifyExistingName(QualifiedName& name, ObjectType ob
9698 }
9799 }
98100
99- attachment->qualifyExistingName (tdbb, name, objectType , cachedDdlSchemaSearchPath);
101+ attachment->qualifyExistingName (tdbb, name, objectTypes , cachedDdlSchemaSearchPath);
100102 }
101103 else
102- attachment->qualifyExistingName (tdbb, name, objectType);
104+ attachment->qualifyExistingName (tdbb, name, objectTypes);
105+ }
106+
107+
108+ std::variant<std::monostate, dsql_prc*, dsql_rel*, dsql_udf*> DsqlCompilerScratch::resolveRoutineOrRelation (
109+ QualifiedName& name, std::initializer_list<ObjectType> objectTypes)
110+ {
111+ const std::unordered_set<ObjectType> objectTypesSet (objectTypes);
112+ const bool searchProcedures = objectTypesSet.find (obj_procedure) != objectTypesSet.end ();
113+ const bool searchRelations = objectTypesSet.find (obj_relation) != objectTypesSet.end ();
114+ const bool searchFunctions = objectTypesSet.find (obj_udf) != objectTypesSet.end ();
115+ fb_assert ((searchProcedures || searchRelations) != searchFunctions);
116+
117+ std::variant<std::monostate, dsql_prc*, dsql_rel*, dsql_udf*> object;
118+
119+ const auto notFound = [&]()
120+ {
121+ return std::holds_alternative<std::monostate>(object);
122+ };
123+
124+ const auto setObject = [&](const auto value)
125+ {
126+ if (value)
127+ object = value;
128+ };
129+
130+ // search subroutine: name
131+ if (name.schema .isEmpty () &&
132+ name.package .isEmpty ())
133+ {
134+ if (searchProcedures)
135+ {
136+ if (const auto subProcedure = getSubProcedure (name.object ))
137+ setObject (subProcedure->dsqlProcedure );
138+ }
139+
140+ if (searchFunctions)
141+ {
142+ if (const auto subFunction = getSubFunction (name.object ))
143+ setObject (subFunction->dsqlFunction );
144+ }
145+ }
146+
147+ // search packaged routine in the same package: name, same_package.name
148+ if (notFound () &&
149+ package.object .hasData () &&
150+ name.package .isEmpty () &&
151+ (name.schema .isEmpty () ||
152+ (!name.isUnambiguous () && name.schema == package.object )))
153+ {
154+ const QualifiedName routineName (name.object , package.schema , package.object );
155+
156+ if (searchProcedures)
157+ setObject (METD_get_procedure (getTransaction (), this , routineName));
158+
159+ if (searchFunctions)
160+ setObject (METD_get_function (getTransaction (), this , routineName));
161+ }
162+
163+ // search standalone routine or relation: name, name1%schema.name2, name1.name2
164+ if (notFound () &&
165+ name.package .isEmpty ())
166+ {
167+ auto qualifiedName = name;
168+ qualifyExistingName (qualifiedName, objectTypes);
169+
170+ if (searchProcedures)
171+ setObject (METD_get_procedure (getTransaction (), this , qualifiedName));
172+
173+ if (searchRelations)
174+ setObject (METD_get_relation (getTransaction (), this , qualifiedName));
175+
176+ if (searchFunctions)
177+ setObject (METD_get_function (getTransaction (), this , qualifiedName));
178+ }
179+
180+ // search packaged routine: name1%package.name2, name1.name2.name3
181+ if (notFound () &&
182+ name.package .hasData ())
183+ {
184+ auto qualifiedName = name;
185+ qualifyExistingName (qualifiedName, objectTypes);
186+
187+ if (searchProcedures)
188+ setObject (METD_get_procedure (getTransaction (), this , qualifiedName));
189+
190+ if (searchFunctions)
191+ setObject (METD_get_function (getTransaction (), this , qualifiedName));
192+ }
193+
194+ // search packaged routine: name1.name2
195+ if (notFound () &&
196+ !name.isUnambiguous () &&
197+ name.schema .hasData () &&
198+ name.package .isEmpty ())
199+ {
200+ QualifiedName qualifiedName (name.object , {}, name.schema );
201+ qualifyExistingName (qualifiedName, objectTypes);
202+
203+ if (searchProcedures)
204+ setObject (METD_get_procedure (getTransaction (), this , qualifiedName));
205+
206+ if (searchFunctions)
207+ setObject (METD_get_function (getTransaction (), this , qualifiedName));
208+ }
209+
210+ if (const auto procedure = std::get_if<dsql_prc*>(&object))
211+ name = (*procedure)->prc_name ;
212+ else if (const auto relation = std::get_if<dsql_rel*>(&object))
213+ name = (*relation)->rel_name ;
214+ else if (const auto function = std::get_if<dsql_udf*>(&object))
215+ name = (*function)->udf_name ;
216+
217+ return object;
103218}
104219
105220
0 commit comments