@@ -607,6 +607,109 @@ static PyObject *Connection_ChangePasswordExternal(
607607}
608608
609609
610+ //-----------------------------------------------------------------------------
611+ // Connection_ProcessAppContext()
612+ // Process application context during the establishing of a session. This is
613+ // intended to replace setting module, action and clientinfo (which was never
614+ // intended to be supported anyway!) and is more flexible in any case.
615+ //-----------------------------------------------------------------------------
616+ static int Connection_ProcessAppContext (
617+ udt_Connection * self , // connection
618+ PyObject * appContextObj ) // app context value
619+ {
620+ void * listHandle , * entryHandle ;
621+ PyObject * entryObj ;
622+ udt_Buffer buffer ;
623+ ub4 numEntries , i ;
624+ sword status ;
625+
626+ // validate context is a list with at least one entry in it
627+ if (!appContextObj )
628+ return 0 ;
629+ if (!PyList_Check (appContextObj )) {
630+ PyErr_SetString (PyExc_TypeError ,
631+ "appcontext should be a list of 3-tuples" );
632+ return -1 ;
633+ }
634+ numEntries = (ub4 ) PyList_GET_SIZE (appContextObj );
635+ if (numEntries == 0 )
636+ return 0 ;
637+
638+ // set the number of application context entries
639+ status = OCIAttrSet (self -> sessionHandle , OCI_HTYPE_SESSION ,
640+ (void * ) & numEntries , sizeof (ub4 ),
641+ OCI_ATTR_APPCTX_SIZE , self -> environment -> errorHandle );
642+ if (Environment_CheckForError (self -> environment , status ,
643+ "Connection_ProcessAppContext(): set app context size" ) < 0 )
644+ return -1 ;
645+
646+ // get the application context list handle
647+ status = OCIAttrGet (self -> sessionHandle , OCI_HTYPE_SESSION , & listHandle , 0 ,
648+ OCI_ATTR_APPCTX_LIST , self -> environment -> errorHandle );
649+ if (Environment_CheckForError (self -> environment , status ,
650+ "Connection_ProcessAppContext(): get list handle" ) < 0 )
651+ return -1 ;
652+
653+ // set each application context entry
654+ for (i = 0 ; i < numEntries ; i ++ ) {
655+
656+ // get entry
657+ entryObj = PyList_GET_ITEM (appContextObj , i );
658+ if (!PyTuple_Check (entryObj ) || PyTuple_GET_SIZE (entryObj ) != 3 ) {
659+ PyErr_SetString (PyExc_TypeError ,
660+ "appcontext should be a list of 3-tuples" );
661+ return -1 ;
662+ }
663+
664+ // retrieve the context element descriptor
665+ status = OCIParamGet (listHandle , OCI_DTYPE_PARAM ,
666+ self -> environment -> errorHandle , & entryHandle , i + 1 );
667+ if (Environment_CheckForError (self -> environment , status ,
668+ "Connection_ProcessAppContext(): get entry handle" ) < 0 )
669+ return -1 ;
670+
671+ // set the namespace name
672+ if (cxBuffer_FromObject (& buffer , PyTuple_GET_ITEM (entryObj , 0 ),
673+ self -> environment -> encoding ) < 0 )
674+ return -1 ;
675+ status = OCIAttrSet (entryHandle , OCI_DTYPE_PARAM ,
676+ (void * ) buffer .ptr , buffer .size , OCI_ATTR_APPCTX_NAME ,
677+ self -> environment -> errorHandle );
678+ cxBuffer_Clear (& buffer );
679+ if (Environment_CheckForError (self -> environment , status ,
680+ "Connection_ProcessAppContext(): set namespace name" ) < 0 )
681+ return -1 ;
682+
683+ // set the name
684+ if (cxBuffer_FromObject (& buffer , PyTuple_GET_ITEM (entryObj , 1 ),
685+ self -> environment -> encoding ) < 0 )
686+ return -1 ;
687+ status = OCIAttrSet (entryHandle , OCI_DTYPE_PARAM ,
688+ (void * ) buffer .ptr , buffer .size , OCI_ATTR_APPCTX_ATTR ,
689+ self -> environment -> errorHandle );
690+ cxBuffer_Clear (& buffer );
691+ if (Environment_CheckForError (self -> environment , status ,
692+ "Connection_ProcessAppContext(): set name" ) < 0 )
693+ return -1 ;
694+
695+ // set the value
696+ if (cxBuffer_FromObject (& buffer , PyTuple_GET_ITEM (entryObj , 2 ),
697+ self -> environment -> encoding ) < 0 )
698+ return -1 ;
699+ status = OCIAttrSet (entryHandle , OCI_DTYPE_PARAM ,
700+ (void * ) buffer .ptr , buffer .size , OCI_ATTR_APPCTX_VALUE ,
701+ self -> environment -> errorHandle );
702+ cxBuffer_Clear (& buffer );
703+ if (Environment_CheckForError (self -> environment , status ,
704+ "Connection_ProcessAppContext(): set value" ) < 0 )
705+ return -1 ;
706+
707+ }
708+
709+ return 0 ;
710+ }
711+
712+
610713//-----------------------------------------------------------------------------
611714// Connection_Connect()
612715// Create a new connection object by connecting to the database.
@@ -620,7 +723,8 @@ static int Connection_Connect(
620723 PyObject * moduleObj , // session "module" value
621724 PyObject * actionObj , // session "action" value
622725 PyObject * clientinfoObj , // session "clientinfo" value
623- PyObject * editionObj ) // session "edition" value
726+ PyObject * editionObj , // session "edition" value
727+ PyObject * appContextObj ) // app context value
624728{
625729 ub4 credentialType = OCI_CRED_EXT ;
626730 udt_Buffer buffer ;
@@ -735,6 +839,7 @@ static int Connection_Connect(
735839 "Connection_Connect(): set session handle" ) < 0 )
736840 return -1 ;
737841
842+ // set module (deprecated)
738843 if (moduleObj ) {
739844 if (cxBuffer_FromObject (& buffer , moduleObj ,
740845 self -> environment -> encoding ))
@@ -748,6 +853,7 @@ static int Connection_Connect(
748853 return -1 ;
749854 }
750855
856+ // set action (deprecated)
751857 if (actionObj ) {
752858 if (cxBuffer_FromObject (& buffer , actionObj ,
753859 self -> environment -> encoding ))
@@ -761,6 +867,7 @@ static int Connection_Connect(
761867 return -1 ;
762868 }
763869
870+ // set client info (deprecated)
764871 if (clientinfoObj ) {
765872 if (cxBuffer_FromObject (& buffer , clientinfoObj ,
766873 self -> environment -> encoding ))
@@ -774,6 +881,7 @@ static int Connection_Connect(
774881 return -1 ;
775882 }
776883
884+ // set edition
777885 if (editionObj ) {
778886 if (cxBuffer_FromObject (& buffer , editionObj ,
779887 self -> environment -> encoding ))
@@ -787,6 +895,10 @@ static int Connection_Connect(
787895 return -1 ;
788896 }
789897
898+ // set application context, if applicable
899+ if (appContextObj && Connection_ProcessAppContext (self , appContextObj ) < 0 )
900+ return -1 ;
901+
790902 // if a new password has been specified, change it which will also
791903 // establish the session
792904 if (newPasswordObj )
@@ -883,7 +995,7 @@ static int Connection_Init(
883995{
884996 PyObject * usernameObj , * passwordObj , * dsnObj , * cclassObj , * editionObj ;
885997 PyObject * threadedObj , * twophaseObj , * eventsObj , * newPasswordObj ;
886- PyObject * moduleObj , * actionObj , * clientinfoObj ;
998+ PyObject * moduleObj , * actionObj , * clientinfoObj , * appContextObj ;
887999 int threaded , twophase , events ;
8881000 char * encoding , * nencoding ;
8891001 ub4 connectMode , purity ;
@@ -894,24 +1006,24 @@ static int Connection_Init(
8941006 static char * keywordList [] = { "user" , "password" , "dsn" , "mode" ,
8951007 "handle" , "pool" , "threaded" , "twophase" , "events" , "cclass" ,
8961008 "purity" , "newpassword" , "encoding" , "nencoding" , "module" ,
897- "action" , "clientinfo" , "edition" , NULL };
1009+ "action" , "clientinfo" , "edition" , "appcontext" , NULL };
8981010
8991011 // parse arguments
9001012 pool = NULL ;
9011013 handle = NULL ;
9021014 connectMode = OCI_STMT_CACHE ;
9031015 threadedObj = twophaseObj = eventsObj = newPasswordObj = NULL ;
9041016 usernameObj = passwordObj = dsnObj = cclassObj = editionObj = NULL ;
905- moduleObj = actionObj = clientinfoObj = NULL ;
1017+ moduleObj = actionObj = clientinfoObj = appContextObj = NULL ;
9061018 threaded = twophase = events = purity = 0 ;
9071019 encoding = nencoding = NULL ;
9081020 purity = OCI_ATTR_PURITY_DEFAULT ;
9091021 if (!PyArg_ParseTupleAndKeywords (args , keywordArgs ,
910- "|OOOiiO!OOOOiOssOOOO " , keywordList , & usernameObj , & passwordObj ,
1022+ "|OOOiiO!OOOOiOssOOOOO " , keywordList , & usernameObj , & passwordObj ,
9111023 & dsnObj , & connectMode , & handle , & g_SessionPoolType , & pool ,
9121024 & threadedObj , & twophaseObj , & eventsObj , & cclassObj , & purity ,
9131025 & newPasswordObj , & encoding , & nencoding , & moduleObj , & actionObj ,
914- & clientinfoObj , & editionObj ))
1026+ & clientinfoObj , & editionObj , & appContextObj ))
9151027 return -1 ;
9161028 if (threadedObj ) {
9171029 threaded = PyObject_IsTrue (threadedObj );
@@ -957,7 +1069,7 @@ static int Connection_Init(
9571069 purity );
9581070 return Connection_Connect (self , connectMode , twophase , passwordObj ,
9591071 newPasswordObj , moduleObj , actionObj , clientinfoObj ,
960- editionObj );
1072+ editionObj , appContextObj );
9611073}
9621074
9631075
0 commit comments