@@ -607,6 +607,109 @@ static PyObject *Connection_ChangePasswordExternal(
607
607
}
608
608
609
609
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
+
610
713
//-----------------------------------------------------------------------------
611
714
// Connection_Connect()
612
715
// Create a new connection object by connecting to the database.
@@ -620,7 +723,8 @@ static int Connection_Connect(
620
723
PyObject * moduleObj , // session "module" value
621
724
PyObject * actionObj , // session "action" value
622
725
PyObject * clientinfoObj , // session "clientinfo" value
623
- PyObject * editionObj ) // session "edition" value
726
+ PyObject * editionObj , // session "edition" value
727
+ PyObject * appContextObj ) // app context value
624
728
{
625
729
ub4 credentialType = OCI_CRED_EXT ;
626
730
udt_Buffer buffer ;
@@ -735,6 +839,7 @@ static int Connection_Connect(
735
839
"Connection_Connect(): set session handle" ) < 0 )
736
840
return -1 ;
737
841
842
+ // set module (deprecated)
738
843
if (moduleObj ) {
739
844
if (cxBuffer_FromObject (& buffer , moduleObj ,
740
845
self -> environment -> encoding ))
@@ -748,6 +853,7 @@ static int Connection_Connect(
748
853
return -1 ;
749
854
}
750
855
856
+ // set action (deprecated)
751
857
if (actionObj ) {
752
858
if (cxBuffer_FromObject (& buffer , actionObj ,
753
859
self -> environment -> encoding ))
@@ -761,6 +867,7 @@ static int Connection_Connect(
761
867
return -1 ;
762
868
}
763
869
870
+ // set client info (deprecated)
764
871
if (clientinfoObj ) {
765
872
if (cxBuffer_FromObject (& buffer , clientinfoObj ,
766
873
self -> environment -> encoding ))
@@ -774,6 +881,7 @@ static int Connection_Connect(
774
881
return -1 ;
775
882
}
776
883
884
+ // set edition
777
885
if (editionObj ) {
778
886
if (cxBuffer_FromObject (& buffer , editionObj ,
779
887
self -> environment -> encoding ))
@@ -787,6 +895,10 @@ static int Connection_Connect(
787
895
return -1 ;
788
896
}
789
897
898
+ // set application context, if applicable
899
+ if (appContextObj && Connection_ProcessAppContext (self , appContextObj ) < 0 )
900
+ return -1 ;
901
+
790
902
// if a new password has been specified, change it which will also
791
903
// establish the session
792
904
if (newPasswordObj )
@@ -883,7 +995,7 @@ static int Connection_Init(
883
995
{
884
996
PyObject * usernameObj , * passwordObj , * dsnObj , * cclassObj , * editionObj ;
885
997
PyObject * threadedObj , * twophaseObj , * eventsObj , * newPasswordObj ;
886
- PyObject * moduleObj , * actionObj , * clientinfoObj ;
998
+ PyObject * moduleObj , * actionObj , * clientinfoObj , * appContextObj ;
887
999
int threaded , twophase , events ;
888
1000
char * encoding , * nencoding ;
889
1001
ub4 connectMode , purity ;
@@ -894,24 +1006,24 @@ static int Connection_Init(
894
1006
static char * keywordList [] = { "user" , "password" , "dsn" , "mode" ,
895
1007
"handle" , "pool" , "threaded" , "twophase" , "events" , "cclass" ,
896
1008
"purity" , "newpassword" , "encoding" , "nencoding" , "module" ,
897
- "action" , "clientinfo" , "edition" , NULL };
1009
+ "action" , "clientinfo" , "edition" , "appcontext" , NULL };
898
1010
899
1011
// parse arguments
900
1012
pool = NULL ;
901
1013
handle = NULL ;
902
1014
connectMode = OCI_STMT_CACHE ;
903
1015
threadedObj = twophaseObj = eventsObj = newPasswordObj = NULL ;
904
1016
usernameObj = passwordObj = dsnObj = cclassObj = editionObj = NULL ;
905
- moduleObj = actionObj = clientinfoObj = NULL ;
1017
+ moduleObj = actionObj = clientinfoObj = appContextObj = NULL ;
906
1018
threaded = twophase = events = purity = 0 ;
907
1019
encoding = nencoding = NULL ;
908
1020
purity = OCI_ATTR_PURITY_DEFAULT ;
909
1021
if (!PyArg_ParseTupleAndKeywords (args , keywordArgs ,
910
- "|OOOiiO!OOOOiOssOOOO " , keywordList , & usernameObj , & passwordObj ,
1022
+ "|OOOiiO!OOOOiOssOOOOO " , keywordList , & usernameObj , & passwordObj ,
911
1023
& dsnObj , & connectMode , & handle , & g_SessionPoolType , & pool ,
912
1024
& threadedObj , & twophaseObj , & eventsObj , & cclassObj , & purity ,
913
1025
& newPasswordObj , & encoding , & nencoding , & moduleObj , & actionObj ,
914
- & clientinfoObj , & editionObj ))
1026
+ & clientinfoObj , & editionObj , & appContextObj ))
915
1027
return -1 ;
916
1028
if (threadedObj ) {
917
1029
threaded = PyObject_IsTrue (threadedObj );
@@ -957,7 +1069,7 @@ static int Connection_Init(
957
1069
purity );
958
1070
return Connection_Connect (self , connectMode , twophase , passwordObj ,
959
1071
newPasswordObj , moduleObj , actionObj , clientinfoObj ,
960
- editionObj );
1072
+ editionObj , appContextObj );
961
1073
}
962
1074
963
1075
0 commit comments