Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Sergey.

Asked: July 18, 2018 - 6:38 am UTC

Last updated: July 23, 2018 - 11:56 am UTC

Version: 11.2

Viewed 1000+ times

You Asked

Hi!
What is the best way to get context value in Oracle?
We have sys_context, which allows get value from context, but it forces to hardcode constants for namespaces and keys.
Is there more graceful solution for it?
For myself I've made a separate package (wrapper) with getters for every context key, which also hides namespaces:

create package ctx_api as
 procedure set_user_id(p_val in varchar2);
 function  get_user_id return varchar2;
end;
/
create package body ctx_api as
 с_ctx_ns constant varchar2(30):='app_ctx';
 c_ctx_user_id constant varchar2(30):='user_id';
 --
 procedure set_user_id(p_val in varchar2)
   is 
   begin
      Dbms_Session.Set_Context(с_ctx_ns , c_ctx_user_id, p_val);
   end;
 --
 function get_user_id return varchar2 is
   begin
     return sys_context(с_ctx_ns , c_ctx_user_id );
   end;
 --
end;
/


Is it good idea?

and Chris said...

The question is, what are you hoping to gain by doing this?

What precise benefit are you hoping to gain by using:

 с_ctx_ns constant varchar2(30):='app_ctx';
 c_ctx_user_id constant varchar2(30):='user_id';


As opposed to placing the values directly in the sys_context call, like so:

sys_context( 'app_ctx', 'user_id' );


?

If your answer is some waffle about "avoiding hard-coding", then you're probably doing this for the wrong reason.

If it's because you want define namespaces and keys in one place, thus making code maintenance easier, that sounds like a good plan to me.

So back to you:

What benefits are you hoping to gain by using this method? And how does this compare to other approaches?

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Sergey Provkin, July 20, 2018 - 10:53 am UTC

Thank you very much for your answer!

If we use some values as constants in our code (numbers or strings etc) this value must be declared as constant because
1. It can be needed anywhere else
2. the value of this constant can be changed sometimes
3. this makes code more clean and understandable (
c_green
much more better than just '1' for example)

I was taught in such way.

This is centralization, one point of control, encapsulation. We just provide the interface.

In situation like
sys_context('APP_NS', 'USER_Id')
vs
sys_context('APP_NS', 'USERID')


sys_context(my_pkg.c_ns, my_pkg.c_user_id)
protects from error
ctx_api.get_user_id
excludes error

In this case we also avoiding hard code.

So this are the aims which I've tried to reach:
1. gather code which works with context in one place
2. encapsulate details
3. Avoid misprints

Also, there can be a lot of constants, application can be huge.
I'm worrying about redundancy\practicalness.
I understand, that this wrapper is additional call, additional context switch and it can't be easily used in views for example

Writing answer I payed attention to constant naming. Of course
c_user_id constant varchar2(30):='user_id'
is redundant.
In this case changing value changes meaning and requires to change name too. So c
_updater
or
c_user
is more useful in such case.

What I'm interested for is
1. Does this approach make sense
2. With relation to your experience, is it totally bad or it can be useful.
3. What way will be better?

Chris Saxon
July 23, 2018 - 11:56 am UTC

It sounds like you've thought this through :)

APIs are generally A Good Thing for the reasons you've identified.

But.

It's important to remember when using this method:

You have to ensure all developers use the API, instead of calling sys_context directly!

Otherwise you end up with "worst of both worlds". You've got the extra effort to create and maintain your API. Plus the pain of hunting through the rest your source code should you change the sys_context call.

In my experience, if someone can bypass an API, eventually they will. If you're able to put processes in place to stop direct access to sys_context (outside your API) this can work well.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library