@@ -434,9 +434,8 @@ For installation information, see the [Node-oracledb Installation Instructions][
434
434
- 15.3.6 [Connection Pool Pinging](#connpoolpinging)
435
435
- 15.3.7 [Connection Tagging and Session State](#connpooltagging)
436
436
- 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)
440
439
- 15.3.8 [Heterogeneous Connection Pools and Pool Proxy Authentication](#connpoolproxy)
441
440
- 15.4 [External Authentication](#extauth)
442
441
- 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
9546
9545
of setting session state if a previous user of a connection has
9547
9546
already set it. The caller of `pool.getConnection()` can always
9548
9547
assume 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.
9551
9549
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.
9559
9552
9560
- - When using [DRCP](#drcp): use a [PL/SQL callback and
9561
- tagging](#sessiontaggingplsql).
9553
+ There are three common scenarios for `sessionCallback`:
9562
9554
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.
9564
9609
9565
9610
This example sets two NLS settings in each pooled connection. They
9566
9611
are only set the very first time connections are established to the
9567
9612
database. The `requestedTag` parameter is ignored because it is only
9568
9613
valid when tagging is being used:
9569
9614
9570
9615
```javascript
9571
- function initSession(connection, requestedTag, cb ) {
9616
+ function initSession(connection, requestedTag, callbackFn ) {
9572
9617
connection.execute(
9573
9618
`alter session set nls_date_format = 'YYYY-MM-DD' nls_language = AMERICAN`,
9574
- cb );
9619
+ callbackFn );
9575
9620
}
9576
9621
9577
9622
try {
9578
9623
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
+ });
9584
9629
. . .
9585
9630
}
9586
9631
```
9587
9632
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:
9591
9637
9592
9638
```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
+ }
9600
9649
```
9601
9650
9602
9651
See [`sessionfixup.js`][126] for a runnable example.
9603
9652
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
9606
9654
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.
9640
9657
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:
9660
9661
9661
9662
```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;
9684
9668
}
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
+ );
9685
9678
}
9686
9679
9687
9680
try {
9688
9681
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
+ });
9694
9687
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" });
9697
9690
9698
9691
. . . // Use the connection
9699
9692
@@ -9703,9 +9696,26 @@ try {
9703
9696
. . .
9704
9697
```
9705
9698
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
9707
9716
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.
9709
9719
9710
9720
When node-oracledb is using Oracle Client libraries 12.2 or later,
9711
9721
`sessionCallback` can be a string containing the name of a PL/SQL
0 commit comments