Skip to content

Commit 0d72c1b

Browse files
committed
Two Phase Commit support in Thin mode
1 parent 4977cde commit 0d72c1b

File tree

13 files changed

+509
-61
lines changed

13 files changed

+509
-61
lines changed

doc/src/api_manual/connection.rst

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -315,23 +315,13 @@ The properties of a *Connection* object are listed below.
315315
This read/write attribute is a string that specifies the internal name
316316
that is used by the connection when logging two-phase commit transactions.
317317

318-
.. note::
319-
320-
This property can only be used in the node-oracledb Thick mode. See
321-
:ref:`enablingthick`.
322-
323318
.. attribute:: connection.tpcExternalName
324319

325320
.. versionadded:: 5.3
326321

327322
This read/write attribute is a string that specifies the external name
328323
that is used by the connection when logging two-phase commit transactions.
329324

330-
.. note::
331-
332-
This property can only be used in the node-oracledb Thick mode. See
333-
:ref:`enablingthick`.
334-
335325
.. attribute:: connection.transactionInProgress
336326

337327
.. versionadded:: 6.3
@@ -2343,11 +2333,6 @@ Connection Methods
23432333

23442334
See :ref:`Two-Phase Commits (TPC) <twopc>`.
23452335

2346-
.. note::
2347-
2348-
This method is only supported in node-oracledb Thick mode. See
2349-
:ref:`enablingthick`.
2350-
23512336
The parameters of the ``connection.tpcBegin()`` method are:
23522337

23532338
.. _tpcbegin:
@@ -2427,11 +2412,6 @@ Connection Methods
24272412
ignored and ``tpcCommit()`` has the same behavior as a regular
24282413
``connection.commit()`` call.
24292414

2430-
.. note::
2431-
2432-
This method is only supported in node-oracledb Thick mode. See
2433-
:ref:`enablingthick`.
2434-
24352415
Note: When using an external transaction manager with two-phase commits,
24362416
:attr:`autocommitting <oracledb.autoCommit>` should be disabled.
24372417

@@ -2497,11 +2477,6 @@ Connection Methods
24972477
If ``xid`` is not passed, the transaction identifier used by the
24982478
previous ``connection.tpcBegin()`` call is used.
24992479

2500-
.. note::
2501-
2502-
This method is only supported in node-oracledb Thick mode. See
2503-
:ref:`enablingthick`.
2504-
25052480
The parameters of the ``connection.tpcEnd()`` method are:
25062481

25072482
.. _tpcend:
@@ -2623,11 +2598,6 @@ Connection Methods
26232598

26242599
Returns a boolean indicating the transaction requires a commit.
26252600

2626-
.. note::
2627-
2628-
This method is only supported in node-oracledb Thick mode. See
2629-
:ref:`enablingthick`.
2630-
26312601
After calling this function, no further activity should take place on
26322602
this connection until either
26332603
:meth:`connection.tpcCommit()` or
@@ -2700,11 +2670,6 @@ Connection Methods
27002670
(XIDs) suitable for use with :meth:`connection.tpcCommit()`
27012671
or :meth:`connection.tpcRollback()`.
27022672

2703-
.. note::
2704-
2705-
This method is only supported in node-oracledb Thick mode. See
2706-
:ref:`enablingthick`.
2707-
27082673
This function is a convenience wrapper that queries the view
27092674
``DBA_PENDING_TRANSACTIONS``. It requires SELECT privilege on that view.
27102675

doc/src/release_notes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ Thin Mode Changes
4343
provided for `Issue #1565 <https://github.com/oracle/node-oracledb/issues/
4444
1565>`__.
4545

46+
#) Added :ref:`Two-Phase Commits <tpc>` support.
47+
4648
Thick Mode Changes
4749
+++++++++++++++++++
4850

doc/src/user_guide/appendix_a.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ node-oracledb Thin and Thick modes. For more details see :ref:`modediff`.
243243
- No
244244
- Yes
245245
* - Two-phase Commit (TPC) (see :ref:`twopc`)
246-
- No
246+
- Yes
247247
- Yes
248248
* - REF CURSORs (see :ref:`refcursors`)
249249
- Yes

doc/src/user_guide/two_phase_commit.rst

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ support distributed transactions. See `Two-Phase Commit Mechanism
99
<https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-8152084F-4760
1010
-4B89-A91C-9A84F81C23D1>`__ in the Oracle Database documentation.
1111

12-
.. note::
13-
14-
In this release, TPC is only supported in node-oracledb Thick mode. See
15-
:ref:`enablingthick`.
16-
1712
Distributed transaction protocols attempt to keep multiple data sources
1813
consistent with one another by ensuring updates to the data sources
1914
participating in a distributed transaction are all performed, or none of

lib/connection.js

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,7 +1412,7 @@ class Connection extends EventEmitter {
14121412
async tpcBegin(xid, flag, timeout) {
14131413
errors.assertArgCount(arguments, 1, 3);
14141414
errors.assertParamValue(nodbUtil.isXid(xid), 1);
1415-
1415+
const normalizedXid = nodbUtil.normalizeXid(xid);
14161416
if (arguments.length < 3) {
14171417
timeout = 60; // seconds
14181418
} else {
@@ -1423,9 +1423,14 @@ class Connection extends EventEmitter {
14231423
flag = constants.TPC_BEGIN_NEW;
14241424
} else {
14251425
errors.assertParamValue(typeof flag === 'number', 2);
1426+
const options = [constants.TPC_BEGIN_NEW, constants.TPC_BEGIN_JOIN,
1427+
constants.TPC_BEGIN_RESUME, constants.TPC_BEGIN_PROMOTE];
1428+
if (options.indexOf(flag) < 0) {
1429+
errors.throwErr(errors.ERR_INVALID_TPC_BEGIN_FLAGS);
1430+
}
14261431
}
14271432
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1428-
await this._impl.tpcBegin(xid, flag, timeout);
1433+
await this._impl.tpcBegin(normalizedXid, flag, timeout);
14291434
}
14301435

14311436
//---------------------------------------------------------------------------
@@ -1441,11 +1446,13 @@ class Connection extends EventEmitter {
14411446
} else {
14421447
errors.assertParamValue(typeof onePhase === 'boolean', 2);
14431448
}
1449+
let normalizedXid;
14441450
if (arguments.length >= 1) {
14451451
errors.assertParamValue(nodbUtil.isXid(xid), 1);
1452+
normalizedXid = nodbUtil.normalizeXid(xid);
14461453
}
14471454
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1448-
await this._impl.tpcCommit(xid, onePhase);
1455+
await this._impl.tpcCommit(normalizedXid, onePhase);
14491456
}
14501457

14511458
//---------------------------------------------------------------------------
@@ -1460,14 +1467,19 @@ class Connection extends EventEmitter {
14601467
flag = constants.TPC_END_NORMAL;
14611468
} else {
14621469
errors.assertParamValue(typeof flag === 'number', 2);
1470+
const options = [constants.TPC_END_NORMAL, constants.TPC_END_SUSPEND];
1471+
if (!options.includes(flag)) {
1472+
errors.throwErr(errors.ERR_INVALID_TPC_END_FLAGS);
1473+
}
14631474
}
1464-
1475+
let normalizedXid;
14651476
if (arguments.length >= 1) {
14661477
errors.assertParamValue(nodbUtil.isXid(xid), 1);
1478+
normalizedXid = nodbUtil.normalizeXid(xid);
14671479
}
14681480
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
14691481

1470-
await this._impl.tpcEnd(xid, flag);
1482+
await this._impl.tpcEnd(normalizedXid, flag);
14711483
}
14721484

14731485
//---------------------------------------------------------------------------
@@ -1479,9 +1491,10 @@ class Connection extends EventEmitter {
14791491
async tpcForget(xid) {
14801492
errors.assertArgCount(arguments, 1, 1);
14811493
errors.assertParamValue(nodbUtil.isXid(xid), 1);
1494+
const normalizedXid = nodbUtil.normalizeXid(xid);
14821495
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
14831496

1484-
await this._impl.tpcForget(xid);
1497+
await this._impl.tpcForget(normalizedXid);
14851498
}
14861499

14871500
//---------------------------------------------------------------------------
@@ -1491,12 +1504,14 @@ class Connection extends EventEmitter {
14911504
//---------------------------------------------------------------------------
14921505
async tpcPrepare(xid) {
14931506
errors.assertArgCount(arguments, 0, 1);
1507+
let normalizedXid;
14941508
if (arguments.length >= 1) {
14951509
errors.assertParamValue(nodbUtil.isXid(xid), 1);
1510+
normalizedXid = nodbUtil.normalizeXid(xid);
14961511
}
14971512
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
14981513

1499-
return await this._impl.tpcPrepare(xid);
1514+
return await this._impl.tpcPrepare(normalizedXid);
15001515
}
15011516

15021517
//---------------------------------------------------------------------------
@@ -1541,12 +1556,14 @@ class Connection extends EventEmitter {
15411556
//---------------------------------------------------------------------------
15421557
async tpcRollback(xid) {
15431558
errors.assertArgCount(arguments, 0, 1);
1559+
let normalizedXid;
15441560
if (arguments.length == 1) {
15451561
errors.assertParamValue(nodbUtil.isXid(xid), 1);
1562+
normalizedXid = nodbUtil.normalizeXid(xid);
15461563
}
15471564
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
15481565

1549-
await this._impl.tpcRollback(xid);
1566+
await this._impl.tpcRollback(normalizedXid);
15501567
}
15511568

15521569
//---------------------------------------------------------------------------

lib/errors.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ const ERR_VECTOR_VERSION_NOT_SUPPORTED = 145;
156156
const ERR_OBJECT_IS_NOT_A_COLLECTION = 146;
157157
const ERR_CURSOR_HAS_BEEN_CLOSED = 147;
158158
const ERR_DML_RETURNING_DUP_BINDS = 149;
159+
const ERR_INVALID_TPC_BEGIN_FLAGS = 150;
160+
const ERR_INVALID_TPC_END_FLAGS = 151;
161+
const ERR_UNKNOWN_TRANSACTION_STATE = 152;
162+
const ERR_INVALID_TRANSACTION_SIZE = 153;
163+
const ERR_INVALID_BRANCH_SIZE = 154;
159164

160165
// Oracle Net layer errors start from 500
161166
const ERR_CONNECTION_CLOSED = 500;
@@ -441,6 +446,16 @@ messages.set(ERR_CURSOR_HAS_BEEN_CLOSED, // NJS-147
441446
'cursor has been closed by the database');
442447
messages.set(ERR_DML_RETURNING_DUP_BINDS, // NJS-149
443448
'the bind variable placeholder "%s" cannot be used both before and after the RETURNING clause in a DML RETURNING statement');
449+
messages.set(ERR_INVALID_TPC_BEGIN_FLAGS, // NJS-150
450+
'invalid flags for tpcBegin() in Two Phase Commit');
451+
messages.set(ERR_INVALID_TPC_END_FLAGS, // NJS-151
452+
'invalid flags for tpcEnd() in Two Phase Commit');
453+
messages.set(ERR_UNKNOWN_TRANSACTION_STATE, // NJS-152
454+
'internal error: unknown transaction state {state} in Two Phase Commit');
455+
messages.set(ERR_INVALID_TRANSACTION_SIZE, // NJS-153
456+
'size of the transaction ID is %d and cannot exceed 64');
457+
messages.set(ERR_INVALID_BRANCH_SIZE, // NJS-154
458+
'size of the branch ID is %d and cannot exceed 64');
444459

445460
// Oracle Net layer errors
446461

@@ -868,6 +883,11 @@ module.exports = {
868883
ERR_OBJECT_IS_NOT_A_COLLECTION,
869884
ERR_CURSOR_HAS_BEEN_CLOSED,
870885
ERR_DML_RETURNING_DUP_BINDS,
886+
ERR_INVALID_TPC_BEGIN_FLAGS,
887+
ERR_INVALID_TPC_END_FLAGS,
888+
ERR_UNKNOWN_TRANSACTION_STATE,
889+
ERR_INVALID_TRANSACTION_SIZE,
890+
ERR_INVALID_BRANCH_SIZE,
871891
ERR_CONNECTION_CLOSED_CODE: `${ERR_PREFIX}-${ERR_CONNECTION_CLOSED}`,
872892
WRN_COMPILATION_CREATE,
873893
assert,

0 commit comments

Comments
 (0)