#------------------------------------------------------------------------------ # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # SessionCallback.py # # Demonstrate how to use a session callback written in Python. The callback is # invoked whenever a newly created session is acquired from the pool, or when # the requested tag does not match the tag that is associated with the # session. It is generally used to set session state, so that the application # can count on known session state, which allows the application to reduce the # number of round trips made to the database. # # This script requires cx_Oracle 7.1 and higher. #------------------------------------------------------------------------------ from __future__ import print_function import cx_Oracle import SampleEnv # define a dictionary of NLS_DATE_FORMAT formats supported by this sample SUPPORTED_FORMATS = { "SIMPLE" : "'YYYY-MM-DD HH24:MI'", "FULL" : "'YYYY-MM-DD HH24:MI:SS'" } # define a dictionary of TIME_ZONE values supported by this sample SUPPORTED_TIME_ZONES = { "UTC" : "'UTC'", "MST" : "'-07:00'" } # define a dictionary of keys that are supported by this sample SUPPORTED_KEYS = { "NLS_DATE_FORMAT" : SUPPORTED_FORMATS, "TIME_ZONE" : SUPPORTED_TIME_ZONES } # define session callback def InitSession(conn, requestedTag): # display the requested and actual tags print("InitSession(): requested tag=%r, actual tag=%r" % \ (requestedTag, conn.tag)) # tags are expected to be in the form "key1=value1;key2=value2" # in this example, they are used to set NLS parameters and the tag is # parsed to validate it if requestedTag is not None: stateParts = [] for directive in requestedTag.split(";"): parts = directive.split("=") if len(parts) != 2: raise ValueError("Tag must contain key=value pairs") key, value = parts valueDict = SUPPORTED_KEYS.get(key) if valueDict is None: raise ValueError("Tag only supports keys: %s" % \ (", ".join(SUPPORTED_KEYS))) actualValue = valueDict.get(value) if actualValue is None: raise ValueError("Key %s only supports values: %s" % \ (key, ", ".join(valueDict))) stateParts.append("%s = %s" % (key, actualValue)) sql = "alter session set %s" % " ".join(stateParts) cursor = conn.cursor() cursor.execute(sql) # assign the requested tag to the connection so that when the connection # is closed, it will automatically be retagged; note that if the requested # tag is None (no tag was requested) this has no effect conn.tag = requestedTag # create pool with session callback defined pool = cx_Oracle.SessionPool(SampleEnv.GetMainUser(), SampleEnv.GetMainPassword(), SampleEnv.GetConnectString(), min=2, max=5, increment=1, threaded=True, sessionCallback=InitSession) # acquire session without specifying a tag; since the session returned is # newly created, the callback will be invoked but since there is no tag # specified, no session state will be changed print("(1) acquire session without tag") conn = pool.acquire() cursor = conn.cursor() cursor.execute("select to_char(current_date) from dual") result, = cursor.fetchone() print("main(): result is", repr(result)) conn.close() # acquire session, specifying a tag; since the session returned has no tag, # the callback will be invoked; session state will be changed and the tag will # be saved when the connection is closed print("(2) acquire session with tag") conn = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE") cursor = conn.cursor() cursor.execute("select to_char(current_date) from dual") result, = cursor.fetchone() print("main(): result is", repr(result)) conn.close() # acquire session, specifying the same tag; since a session exists in the pool # with this tag, it will be returned and the callback will not be invoked but # the connection will still have the session state defined previously print("(3) acquire session with same tag") conn = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE") cursor = conn.cursor() cursor.execute("select to_char(current_date) from dual") result, = cursor.fetchone() print("main(): result is", repr(result)) conn.close() # acquire session, specifying a different tag; since no session exists in the # pool with this tag, a new session will be returned and the callback will be # invoked; session state will be changed and the tag will be saved when the # connection is closed print("(4) acquire session with different tag") conn = pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC") cursor = conn.cursor() cursor.execute("select to_char(current_date) from dual") result, = cursor.fetchone() print("main(): result is", repr(result)) conn.close() # acquire session, specifying a different tag but also specifying that a # session with any tag can be acquired from the pool; a session with one of the # previously set tags will be returned and the callback will be invoked; # session state will be changed and the tag will be saved when the connection # is closed print("(4) acquire session with different tag but match any also specified") conn = pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=MST", matchanytag=True) cursor = conn.cursor() cursor.execute("select to_char(current_date) from dual") result, = cursor.fetchone() print("main(): result is", repr(result)) conn.close()