FirebirdSQL / firebird

Firebird server, client and tools
https://www.firebirdsql.org/
1.23k stars 212 forks source link

search path for packages #7072

Closed ibexpertHK closed 2 years ago

ibexpertHK commented 2 years ago

it is perhaps a basic idea that might be possible to implement in core engine

in general

we have for example an international company that needs to caclulate VAT rate for different location in very different ways (some developer might know this problem, pyhsical or digital, eu or non eu, vat id or b2c etc). even with proper designed tables hard to implement.

so the idea is

implement for example a procedure or function in several packages with the same name, but different package names

outside any package we implement a procedure vat(id bigint) returns val numeric(18,2) virtual package 1 called DE implements a procedure vat(id bigint) returns val numeric(18,2) override package 2 called CH implements a procedure vat(id bigint) returns val numeric(18,2) override package 3 called AT implements a procedure vat(id bigint) returns val numeric(18,2) override

in such an architecture we can always use references as they are used in existing metadata, but when a PACKAGESEARCHPATH is set, the procedure calls the first found override version and not the virtual version (which might always run an exception, depending on how the developer wants to implement it). if no search path is set, the global procedure outside packages is called

rdb$set_context('USER_SESSION', 'PACKAGESEARCHPATH', 'DE;');

with context variable people from all 3 countries can works on the same metadata in a single database, but use different implementations if needed

in current package system the only way to call the right version is to have full name, for example

if country='DE' then var=DE.vat(:id); else if country='CH' then var=CH.vat(:id); else if country='AT' then var=AT.vat(:id);

i used an execute statement for this by simply do execute statement ('select val from '||country||'.vat(:id)') (ID:=ID) into val that is a workaround which makes mulitple lines replaced by a single line, but i try to avoid not really needed execute statements

the idea is now perhaps simple, perhaps using a local set setcontext variable

the only changes might be a new keyword like virtual to let firebird know that it might have an override version in a package search path and technically execute procedure or select from procedure inside any objects detects this and searches internally for overriding versions with the same name.

would be a great advantage for using packages in the future (which is currently stilll not very common, despite of the advantages)

perhaps the same idea can later be used to have tables be part of a package. it is not so far away from multiple schema in database idea but in my proposed implementation, it can be implemented for packages perhaps faster.

aafemt commented 2 years ago

It will create a "symbol hell" when you hardly can predict or detect function being called from a wrong package. Consider a mistype "foo1()" vs "fool()".

ibexpertHK commented 2 years ago

if there is no virtual version of the same named object, it can not be used in any package to be overriden with the same name.

that can all be done by compiler, a typo can not be compiled anywhere, since original virtual version is basically rquired

asfernandes commented 2 years ago

I don't think this fit packages.

I'd go the Oracle way implementing objects.

livius2 commented 2 years ago

And if virtual functions will exist there must be limitation to prevent using such function in expression indexes.