@@ -434,9 +434,8 @@ For installation information, see the [Node-oracledb Installation Instructions][
434434 - 15.3.6 [Connection Pool Pinging](#connpoolpinging)
435435 - 15.3.7 [Connection Tagging and Session State](#connpooltagging)
436436 - 15.3.7.1 [Node.js Session Callback](#sessionfixupnode)
437- - 15.3.7.2 [Connection Tagging](#sessionfixuptagging)
438- - 15.3.7.3 [Node.js Session Tagging Callback](#sessiontaggingnode)
439- - 15.3.7.4 [PL/SQL Session Tagging Callback](#sessiontaggingplsql)
437+ - 15.3.7.2 [Node.js Session Tagging Callback](#sessiontaggingnode)
438+ - 15.3.7.3 [PL/SQL Session Tagging Callback](#sessiontaggingplsql)
440439 - 15.3.8 [Heterogeneous Connection Pools and Pool Proxy Authentication](#connpoolproxy)
441440 - 15.4 [External Authentication](#extauth)
442441 - 15.5 [Database Resident Connection Pooling (DRCP)](#drcp)
@@ -9546,154 +9545,148 @@ It will not be called in other cases. Using a callback saves the cost
95469545of setting session state if a previous user of a connection has
95479546already set it. The caller of `pool.getConnection()` can always
95489547assume the correct state is set. The `sessionCallback` can also be a
9549- PL/SQL procedure, described in [PL/SQL Session Tagging
9550- Callback](#sessiontaggingplsql).
9548+ PL/SQL procedure.
95519549
9552- There are three common scenarios for `sessionCallback`:
9553-
9554- - When all connections in the pool should have the same state: use a
9555- [Node.js callback without tagging](#sessionfixupnode).
9556-
9557- - When connections in the pool require different state for different
9558- users: use a [Node.js callback with tagging](#sessiontaggingnode).
9550+ Connection tagging and `sessionCallback` are new features in
9551+ node-oracledb 3.1.
95599552
9560- - When using [DRCP](#drcp): use a [PL/SQL callback and
9561- tagging](#sessiontaggingplsql).
9553+ There are three common scenarios for `sessionCallback`:
95629554
9563- ###### <a name="sessionfixupnode"></a> 15.3.7.1 Node.js Session Callback
9555+ - When all connections in the pool should have the same state use a simple
9556+ [Node.js Session Callback](#sessionfixupnode) without tagging.
9557+
9558+ - When connections in the pool require different state for different users use
9559+ a [Node.js Session Tagging Callback](#sessiontaggingnode).
9560+
9561+ - When using [DRCP](#drcp) then use a [PL/SQL Session Tagging
9562+ Callback](#sessiontaggingplsql).
9563+
9564+ ###### <a name="sessionfixuptagging"></a> Connection Tagging
9565+
9566+ Pooled connections can be tagged to record their session state by setting the
9567+ property [`connection.tag`](#propconntag) to a user chosen string that
9568+ represents the state you have set in the connection. A
9569+ `pool.getConnection({tag: 'mytag'})` call can request a connection that has the
9570+ specified tag. If no available connections with that tag exist in the pool, an
9571+ untagged connection or a newly created connection will be returned. If the
9572+ optional `getConnection()` attribute `matchAnyTag` is *true*, then a connection
9573+ that has a different tag may be returned.
9574+
9575+ The [`sessionCallback`](#createpoolpoolattrssessioncallback) function is
9576+ invoked before `pool.getConnection()` returns if the requested tag is not
9577+ identical to the actual tag of the pooled connection. The callback can compare
9578+ the requested tag with the current actual tag in `connection.tag`. Any desired
9579+ state change can be made to the connection and `connection.tag` can be updated
9580+ to record the change. The best practice recommendation is to set the tag in
9581+ the callback function but, if required, a tag can be set anytime prior to
9582+ closing the connection. To clear a connection's tag set `connection.tag` to an
9583+ empty string.
9584+
9585+ You would use tagging where you want `pool.getConnection()` to return a
9586+ connection which has one of several different states. If all connections
9587+ should have the same state then you can simply set `sessionCallback` and not
9588+ use tagging. Also, it may not be worthwhile using a large number of different
9589+ tags, or using tagging where connections are being [dropped](#connectionclose)
9590+ and recreated frequently since the chance of `pool.getConnection()` returning
9591+ an already initialized connection with the requested tag could be low, so most
9592+ `pool.getConnection()` calls would return a connection needing its session
9593+ reset, and tag management will just add overhead.
9594+
9595+ When node-oracledb is using Oracle Client libraries 12.2 or later, then
9596+ node-oracledb uses 'multi-property tags' and the tag string must be of the form
9597+ of one or more "name=value" pairs separated by a semi-colon, for example
9598+ `"loc=uk;lang=cy"`. The Oracle [session pool][6] used by node-oracledb has
9599+ various heuristics to determine which connection is returned to the
9600+ application. Refer to the [multi-property tags documentation][125]. The
9601+ callback function can parse the requested multi-property tag and compare it
9602+ with the connection's actual properties in [`connection.tag`](#propconntag) to
9603+ determine what exact state to set and what value to update `connection.tag` to.
9604+
9605+ ##### <a name="sessionfixupnode"></a> 15.3.7.1 Node.js Session Callback
9606+
9607+ When all connections in the pool should have the same state, a simple callback
9608+ can be used.
95649609
95659610This example sets two NLS settings in each pooled connection. They
95669611are only set the very first time connections are established to the
95679612database. The `requestedTag` parameter is ignored because it is only
95689613valid when tagging is being used:
95699614
95709615```javascript
9571- function initSession(connection, requestedTag, cb ) {
9616+ function initSession(connection, requestedTag, callbackFn ) {
95729617 connection.execute(
95739618 `alter session set nls_date_format = 'YYYY-MM-DD' nls_language = AMERICAN`,
9574- cb );
9619+ callbackFn );
95759620}
95769621
95779622try {
95789623 const pool = await oracledb.createPool({
9579- user: 'hr',
9580- password: mypw, // mypw contains the hr schema password
9581- connectString: 'localhost/XEPDB1',
9582- sessionCallback: initSession
9583- });
9624+ user: 'hr',
9625+ password: mypw, // mypw contains the hr schema password
9626+ connectString: 'localhost/XEPDB1',
9627+ sessionCallback: initSession
9628+ });
95849629 . . .
95859630}
95869631```
95879632
9588- If you need to execute multiple SQL statements in the callback, use an
9589- anonymous PL/SQL block to save [round-trips](#roundtrips) of repeated
9590- `execute()` calls:
9633+ Note that a single ALTER SESSION statement is used to set multiple properties,
9634+ avoiding [round-trips](#roundtrips) of repeated `execute()` calls. If you need
9635+ to execute multiple SQL statements, then use an anonymous PL/SQL block for the
9636+ same reason:
95919637
95929638```javascript
9593- connection.execute(
9594- `begin
9595- execute immediate
9596- 'alter session set nls_date_format = ''YYYY-MM-DD'' nls_language = AMERICAN';
9597- -- other SQL statements could be put here
9598- end;`,
9599- cb);
9639+ function initSession(connection, requestedTag, callbackFn) {
9640+ connection.clientId = "Chris";
9641+ connection.execute(
9642+ `begin
9643+ execute immediate 'alter session set nls_date_format = ''YYYY-MM-DD'' nls_language = AMERICAN';
9644+ insert into user_log (id, ts) values (sys_context('userenv', 'client_identifier'), systimestamp);
9645+ commit;
9646+ end;`,
9647+ callbackFn);
9648+ }
96009649```
96019650
96029651See [`sessionfixup.js`][126] for a runnable example.
96039652
9604- Connection tagging and `sessionCallback` are new features in
9605- node-oracledb 3.1.
9653+ ##### <a name="sessiontaggingnode"></a> 15.3.7.2 Node.js Session Tagging Callback
96069654
9607- ###### <a name="sessionfixuptagging"></a> 15.3.7.2 Connection Tagging
9608-
9609- Pooled connections can be tagged to record their session state by
9610- setting the property [`connection.tag`](#propconntag) to a string. A
9611- `pool.getConnection({tag: 'mytag'})` call can request a connection
9612- that has the specified tag. If no available connections with that tag
9613- exist in the pool, an untagged connection or a connection with a new
9614- session will be returned. If the optional `getConnection()` attribute
9615- `matchAnyTag` is *true*, then a connection that has a different tag
9616- may be returned.
9617-
9618- The [`sessionCallback`](#createpoolpoolattrssessioncallback) function
9619- is invoked before `pool.getConnection()` returns if the requested tag
9620- is not identical to the actual tag of the pooled connection. The
9621- callback can compare the requested tag with the current actual tag in
9622- `connection.tag`. Any desired state change can be made to the
9623- connection and `connection.tag` can be updated to record the change.
9624- The best practice recommendation is to set the tag in the callback
9625- function but, if required, a tag can be set anytime prior to closing
9626- the connection. To clear a connection's tag set `connection.tag` to
9627- an empty string.
9628-
9629- You would use tagging where you want `pool.getConnection()` to return
9630- a connection which has one of several different states. If all
9631- connections should have the same state then you can simply set
9632- `sessionCallback`, as shown [earlier](#sessionfixupnode), and not use
9633- tagging. Also, it may not be worthwhile using huge numbers of
9634- different tags or using tagging where connections are being
9635- [dropped](#connectionclose) or recreated frequently since the chance
9636- of `pool.getConnection()` returning an already initialized connection
9637- with the requested tag could be low, so most `pool.getConnection()`
9638- calls would return a connection needing its session reset, and tag
9639- management will just add overhead.
9655+ When connections in the pool require different state for different users and
9656+ you are not using DRCP, then use a JavaScript callback with tagging.
96409657
9641- When node-oracledb is using Oracle Client libraries 12.2 or later,
9642- then node-oracledb uses 'multi-property tags' and the tag string must
9643- be of the form of one or more "name=value" pairs separated by a
9644- semi-colon, for example `"loc=uk;lang=cy"`. The Oracle [session
9645- pool][6] used by node-oracledb has various heuristics to determine
9646- which connection is returned to the application. Refer to the
9647- [multi-property tags documentation][125]. The callback function can
9648- parse the requested multi-property tag and compare it with the
9649- connection's actual properties in [`connection.tag`](#propconntag) to
9650- determine what exact state to set and what value to update
9651- `connection.tag` to.
9652-
9653- ###### <a name="sessiontaggingnode"></a> 15.3.7.3 Node.js Session Tagging Callback
9654-
9655- This example Node.js callback function ensures the connection contains
9656- valid settings for an application-specific "location=USA" property and
9657- ignores any other properties in the tag that represent session state
9658- set by other parts of the application (not shown) that are using the
9659- same pool:
9658+ This example Node.js callback function ensures the connection contains valid
9659+ settings for an application-specific "USER_TZ=X" property where X is a valid
9660+ Oracle timezone:
96609661
96619662```javascript
9662- const sessionTag = "location=USA";
9663-
9664- function initSession(connection, requestedTag, cb) {
9665- const seen = connection.tag ? connection.tag.split(";").includes(requestedTag) : false;
9666- if (seen) {
9667- cb()
9668- } else {
9669- connection.execute(
9670- `ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YY' NLS_LANGUAGE = AMERICAN`,
9671- (err) => {
9672- // Update the tag the record the connection's new state
9673- const k = requestedTag.substr(0, requestedTag.indexOf('=')+1);
9674- if (connection.tag.indexOf(k) >= 0) {
9675- // Update value of an existing, matching property in the tag
9676- const re = new RegExp(k + "[^;]*");
9677- connection.tag = connection.tag.replace(re, requestedTag);
9678- } else {
9679- // the requested property was not previously set in the tag
9680- connection.tag = requestedTag + ';' + connection.tag;
9681- }
9682- cb();
9683- });
9663+ function initSession(connection, requestedTag, callbackFn) {
9664+ const tagParts = requestedTag.split('=');
9665+ if (tagParts[0] != 'USER_TZ') {
9666+ callbackFn(new Error('Error: Only property USER_TZ is supported'));
9667+ return;
96849668 }
9669+
9670+ connection.execute(
9671+ `ALTER SESSION SET TIME_ZONE = '${tagParts[1]}'`,
9672+ (err) => {
9673+ // Record the connection's new state and return
9674+ connection.tag = requestedTag;
9675+ callbackFn(err);
9676+ }
9677+ );
96859678}
96869679
96879680try {
96889681 await oracledb.createPool({
9689- user: 'hr',
9690- password: mypw, // mypw contains the hr schema password
9691- connectString: 'localhost/XEPDB1',
9692- sessionCallback: initSession
9693- });
9682+ user: 'hr',
9683+ password: mypw, // mypw contains the hr schema password
9684+ connectString: 'localhost/XEPDB1',
9685+ sessionCallback: initSession
9686+ });
96949687
9695- // Request a connection with a given tag from the pool cache, but accept any tag being returned.
9696- const connection = await oracledb.getConnection({poolAlias: 'default', tag: sessionTag, matchAnyTag: true });
9688+ // Get a connection with a given tag (and corresponding session state) from the pool
9689+ const connection = await oracledb.getConnection({poolAlias: 'default', tag: "USER_TZ=UTC" });
96979690
96989691 . . . // Use the connection
96999692
@@ -9703,9 +9696,26 @@ try {
97039696 . . .
97049697```
97059698
9706- For runnable examples, see [`sessiontagging1.js`][127] and [`sessiontagging2.js`][128].
9699+ The `initSession()` session callback function is only invoked by
9700+ `getConnection()` if the node-oracledb connection pool cannot find a connection
9701+ with the requested tag. The session callback function adjusts the connection
9702+ state and records the matching tag.
9703+
9704+ Other parts of the application may request connections with different tags.
9705+ Eventually the pool would contain connections with various different states
9706+ (and equivalent tags). Each `getConnection()` call will attempt to return a
9707+ connection which already has the requested tag. If a matching free connection
9708+ cannot be found, the pool may grow or the session state from another connection
9709+ is cleared. Then `initSession()` is called so that the desired connection
9710+ state can be set.
9711+
9712+ For runnable examples, see [`sessiontagging1.js`][127] and
9713+ [`sessiontagging2.js`][128].
9714+
9715+ ##### <a name="sessiontaggingplsql"></a> 15.3.7.3 PL/SQL Session Tagging Callback
97079716
9708- ###### <a name="sessiontaggingplsql"></a> 15.3.7.4 PL/SQL Session Tagging Callback
9717+ When using [DRCP](#drcp), tagging is most efficient when using a PL/SQL
9718+ callback.
97099719
97109720When node-oracledb is using Oracle Client libraries 12.2 or later,
97119721`sessionCallback` can be a string containing the name of a PL/SQL
0 commit comments