Skip to content

Commit 94add8b

Browse files
committed
Do rollback on explicit release, matching implicit release behavior. Revert driver name setting for the moment
1 parent 8048705 commit 94add8b

File tree

13 files changed

+80
-180
lines changed

13 files changed

+80
-180
lines changed

doc/api.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ This is an asynchronous call.
707707
All open connections in a connection pool are closed when a connection
708708
pool terminates.
709709

710-
Any ongoing transaction in a connection will be committed.
710+
Any ongoing transaction in a connection will be released.
711711

712712
##### Prototype
713713

@@ -928,7 +928,7 @@ Option Property | Description
928928
----------------|-------------
929929
*Number maxRows* | Number of rows to fetch for `SELECT` statements. To improve database efficiency, SQL queries should use a row limiting clause like [OFFSET / FETCH](https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#BABEAACC) or equivalent. The `maxRows` attribute can be used to stop badly coded queries from returning unexpectedly large numbers of rows.
930930
*String outFormat* | The format of rows fetched for `SELECT` statements. This can be either `ARRAY` or `OBJECT`. If specified as `ARRAY`, then each row is fetched as an array of column values. If specified as `OBJECT`, then each row is fetched as a JavaScript object.
931-
*Boolean isAutoCommit* | If it is true, then each [DML](https://docs.oracle.com/database/121/CNCPT/glossary.htm#CNCPT2042) is automatically committed. Note: Oracle Database will implicitly commit when a [DDL](https://docs.oracle.com/database/121/CNCPT/glossary.htm#CHDJJGGF) statement is executed. Any ongoing transaction will also be committed when [`release()`](#release) or [`terminate()`](#terminate) are called.
931+
*Boolean isAutoCommit* | If it is true, then each [DML](https://docs.oracle.com/database/121/CNCPT/glossary.htm#CNCPT2042) is automatically committed. Note: Oracle Database will implicitly commit when a [DDL](https://docs.oracle.com/database/121/CNCPT/glossary.htm#CHDJJGGF) statement is executed.
932932

933933
```
934934
function(Error error, [Object result])
@@ -990,7 +990,7 @@ the connection is returned to the pool.
990990
This is an asynchronous call.
991991

992992
When a connection is released, any ongoing transaction on the
993-
connection is implicitly committed.
993+
connection is rolled back.
994994

995995
##### Prototype
996996

@@ -1016,7 +1016,7 @@ Callback function parameter | Description
10161016

10171017
#### <a name="rollback"></a> 5.2.5 rollback()
10181018

1019-
This call rolls-back the current transaction in progress on the
1019+
This call rolls back the current transaction in progress on the
10201020
connection.
10211021

10221022
##### Description
@@ -1050,13 +1050,13 @@ Callback function parameter | Description
10501050
A SQL or PL/SQL statement may be executed using the *Connection*
10511051
[`execute()`](#execute) method.
10521052

1053-
By default,
1053+
10541054
[DML](https://docs.oracle.com/database/121/CNCPT/glossary.htm#CNCPT2042)
1055-
statements are not committed unless the `commit()` call is issued.
1056-
However, if the `isAutoCommit` property is *true* for the connection,
1057-
then all DML operations are committed as they are executed. The
1058-
`isAutoCommit` property can be overridden for the duration of an
1059-
`execute()` call to automatically commit a DML statement.
1055+
statements are not committed unless the `commit()` call is issued or
1056+
the `isAutoCommit` property is *true* at the time of execution. Any
1057+
ongoing transaction will be rolled back when [`release()`](#release)
1058+
or [`terminate()`](#terminate) are called, or when the application
1059+
ends.
10601060

10611061
Using bind variables in SQL statements is recommended in preference to
10621062
constructing SQL statements by string concatenation. This is for
@@ -1304,8 +1304,8 @@ may be interrupted by the [`break()`](#break) call.
13041304
After all database calls on the connection complete, the application
13051305
should use the [`release()`](#release) call to release the connection.
13061306

1307-
When a connection is released, it implicitly commits any ongoing
1308-
transactions. Therefore if a released, pooled connection is used by
1307+
When a connection is released, it rolls back any ongoing
1308+
transaction. Therefore if a released, pooled connection is used by
13091309
a subsequent [`pool.getConnection()`](#getconnection2) call, then any
13101310
[DML](https://docs.oracle.com/database/121/CNCPT/glossary.htm#CNCPT2042)
13111311
statements performed on the obtained connection are always in a new
@@ -1317,8 +1317,7 @@ database connection. The application must redo any ALTER SESSION
13171317
statements on the new connection object, as required.
13181318

13191319
When an application ends, any uncommitted transaction on a connection
1320-
will be rolled back if there is no explicit commit, or
1321-
[`release()`](#release) or [`terminate()`](#terminate) are not called.
1320+
will be rolled back if there is no explicit commit.
13221321

13231322
## <a name="oraaccess"></a> 6. External Configuration
13241323

src/dpi/include/dpi.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,6 @@
5656
#endif
5757

5858

59-
#ifndef DPIUTILS_ORACLE
60-
# include <dpiUtils.h>
61-
#endif
6259

6360
/*---------------------------------------------------------------------------
6461
COMMON PUBLIC CONSTANTS

src/dpi/src/dpiConnImpl.cpp

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,9 @@ ConnImpl::ConnImpl(EnvImpl *env, OCIEnv *envh, bool isExternalAuth,
7777
const string &connString, const string &connClass)
7878

7979
try : env_(env), pool_(NULL),
80-
envh_(envh), errh_(NULL), auth_(NULL), svch_(NULL), sessh_(NULL)
80+
envh_(envh), errh_(NULL), auth_(NULL), svch_(NULL), sessh_(NULL),
81+
hasTxn_(false)
8182
{
82-
char drvname [DPI_DRIVER_NAME_LEN ];
83-
8483
ub4 mode = isExternalAuth ? OCI_SESSGET_CREDEXT : OCI_DEFAULT;
8584

8685
ociCallEnv(OCIHandleAlloc((void *)envh_, (dvoid **)&errh_,
@@ -108,44 +107,10 @@ try : env_(env), pool_(NULL),
108107
OCI_ATTR_CONNECTION_CLASS, errh_), errh_);
109108
}
110109

111-
// Get the driver name with version details
112-
getDriverName (drvname, DPI_DRIVER_NAME_LEN );
113-
114-
// Set the driver name on Auth handle
115-
ociCall(OCIAttrSet ((void*)auth_, OCI_HTYPE_AUTHINFO,
116-
(void *)drvname, DPI_DRIVER_NAME_LEN,
117-
OCI_ATTR_DRIVER_NAME, errh_ ), errh_);
118-
119-
120-
// It is possible Sessionget can fail
121-
try
122-
{
123-
ociCall(OCISessionGet(envh_, errh_, &svch_, auth_,
124-
(OraText *)connString.data(),
125-
(ub4) connString.length(), NULL, 0, NULL, NULL, NULL,
126-
mode), errh_);
127-
}
128-
catch (dpi::Exception& e )
129-
{
130-
// Due to an error in Oracle code, in case of DRCP server and no
131-
// session-pool-connections, setting Driver-Name has no value, only
132-
// connection class should be used. Clear it and retry.
133-
if ( e.errnum () == 56609 )
134-
{
135-
ociCall(OCIAttrSet ( (void*)auth_, OCI_HTYPE_AUTHINFO,
136-
(void *)"", 0,
137-
OCI_ATTR_DRIVER_NAME, errh_ ), errh_ ) ;
138-
139-
ociCall(OCISessionGet(envh_, errh_, &svch_, auth_,
140-
(OraText *)connString.data(),
141-
(ub4) connString.length(), NULL, 0, NULL, NULL,
142-
NULL, mode), errh_);
143-
}
144-
else
145-
{
146-
throw ;
147-
}
148-
}
110+
ociCall(OCISessionGet(envh_, errh_, &svch_, auth_,
111+
(OraText *)connString.data(),
112+
(ub4) connString.length(), NULL, 0, NULL, NULL, NULL,
113+
mode), errh_);
149114

150115
ociCall(OCIAttrGet(svch_, OCI_HTYPE_SVCCTX, &sessh_, 0,
151116
OCI_ATTR_SESSION, errh_),errh_);
@@ -187,7 +152,7 @@ ConnImpl::ConnImpl(PoolImpl *pool, OCIEnv *envh, bool isExternalAuth,
187152

188153
try : env_(NULL), pool_(pool),
189154
envh_(envh), errh_(NULL), auth_(NULL),
190-
svch_(NULL), sessh_(NULL)
155+
svch_(NULL), sessh_(NULL), hasTxn_(false)
191156
{
192157
ub4 mode = isExternalAuth ? (OCI_SESSGET_CREDEXT | OCI_SESSGET_SPOOL) :
193158
OCI_SESSGET_SPOOL;
@@ -259,6 +224,12 @@ ConnImpl::~ConnImpl()
259224

260225
void ConnImpl::release()
261226
{
227+
#if OCI_MAJOR_VERSION >= 12
228+
ociCall(OCIAttrGet(sessh_, OCI_HTYPE_SESSION, &hasTxn_, NULL,
229+
OCI_ATTR_TRANSACTION_IN_PROGRESS, errh_), errh_);
230+
#endif
231+
if(hasTxn_)
232+
rollback();
262233
if (pool_)
263234
pool_->releaseConnection(this);
264235
else if (env_)
@@ -286,8 +257,6 @@ void ConnImpl::releaseStmt ( Stmt *stmt )
286257
}
287258
}
288259

289-
290-
291260
/*****************************************************************************/
292261
/*
293262
DESCRIPTION

src/dpi/src/dpiConnImpl.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,20 @@ class ConnImpl : public Conn
9898
virtual void rollback();
9999

100100
virtual void breakExecution();
101-
101+
102+
#if OCI_MAJOR_VERSION < 12
103+
inline void hasTxn(boolean connHasTxn)
104+
{
105+
// sets the flag used during connection release.
106+
hasTxn_ = connHasTxn;
107+
}
108+
inline boolean hasTxn()
109+
{
110+
// returns flag to denote active transactions.
111+
return hasTxn_;
112+
}
113+
#endif
114+
102115
private:
103116

104117
void cleanup();
@@ -112,6 +125,7 @@ class ConnImpl : public Conn
112125
OCIAuthInfo *auth_; // OCI auth handle
113126
OCISvcCtx *svch_; // OCI service handle
114127
OCISession *sessh_; // OCI Session handle. Do not free this.
128+
boolean hasTxn_; // set if transaction is in progress
115129
};
116130

117131

src/dpi/src/dpiPoolImpl.cpp

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -89,30 +89,16 @@ PoolImpl::PoolImpl(EnvImpl *env, OCIEnv *envh,
8989
int poolMin, int poolIncrement,
9090
int poolTimeout, bool isExternalAuth, int stmtCacheSize)
9191
try : env_(env), isExternalAuth_(isExternalAuth), envh_(envh), errh_(NULL),
92-
poolauth_(NULL), spoolh_(NULL), poolName_(NULL)
92+
spoolh_(NULL), poolName_(NULL)
9393
{
9494
unsigned int spoolMode = OCI_SPOOL_ATTRVAL_NOWAIT;
95-
char drvname[DPI_DRIVER_NAME_LEN];
9695

9796
ociCallEnv(OCIHandleAlloc((void *)envh_, (dvoid **)&errh_,
9897
OCI_HTYPE_ERROR, 0, (dvoid **)0), envh_);
9998

10099
ociCall(OCIHandleAlloc((void *)envh_, (dvoid **)&spoolh_,
101100
OCI_HTYPE_SPOOL, 0, (dvoid **)0), errh_);
102101

103-
ociCall(OCIHandleAlloc((void *)envh_, (dvoid **)&poolauth_,
104-
OCI_HTYPE_AUTHINFO, 0, (dvoid **)0 ), errh_);
105-
106-
// Get the driver name with version details.
107-
getDriverName ( drvname, DPI_DRIVER_NAME_LEN );
108-
109-
ociCall (OCIAttrSet ((void *)poolauth_, OCI_HTYPE_AUTHINFO,
110-
(void *)drvname, DPI_DRIVER_NAME_LEN,
111-
OCI_ATTR_DRIVER_NAME, errh_ ), errh_ );
112-
113-
ociCall (OCIAttrSet (spoolh_, OCI_HTYPE_SPOOL, poolauth_, 0,
114-
OCI_ATTR_SPOOL_AUTH, errh_ ), errh_ );
115-
116102
ociCall(OCISessionPoolCreate(envh_, errh_, spoolh_,
117103
&poolName_, &poolNameLen_,
118104
(OraText *)connString.data (),
@@ -355,13 +341,6 @@ void PoolImpl::releaseConnection(ConnImpl *conn)
355341

356342
void PoolImpl::cleanup()
357343
{
358-
359-
if ( poolauth_ )
360-
{
361-
OCIHandleFree (poolauth_, OCI_HTYPE_AUTHINFO );
362-
poolauth_ = NULL;
363-
}
364-
365344
if (poolName_)
366345
{
367346
ociCall( OCISessionPoolDestroy( spoolh_, errh_, OCI_DEFAULT), errh_);

src/dpi/src/dpiPoolImpl.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ class PoolImpl : public SPool
8888
bool isExternalAuth_; // doing external authentication
8989
OCIEnv *envh_; // OCI enviornment handle
9090
OCIError *errh_; // OCI error handle
91-
OCIAuthInfo *poolauth_; // OCI auth handle
9291
OCISPool *spoolh_; // OCI session pool handle
9392
OraText *poolName_; // pool name
9493
ub4 poolNameLen_; // pool name length

src/dpi/src/dpiStmtImpl.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ using namespace std;
5858
/*---------------------------------------------------------------------------
5959
PUBLIC METHODS
6060
---------------------------------------------------------------------------*/
61-
61+
6262

6363
/*****************************************************************************/
6464
/*
@@ -284,6 +284,11 @@ void StmtImpl::executeMany (int numIterations, bool isAutoCommit )
284284
ociCall (OCIStmtExecute (svch_, stmth_, errh_, (ub4)numIterations, (ub4)0,
285285
(OCISnapshot *)NULL, (OCISnapshot *)NULL, mode),
286286
errh_);
287+
#if OCI_MAJOR_VERSION < 12
288+
if(!conn_->hasTxn())
289+
conn_->hasTxn(true); /* Not to be reset, till thread safety is ensured in
290+
NJS */
291+
#endif
287292
}
288293

289294

src/dpi/src/dpiUtils.cpp

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -121,36 +121,6 @@ void ociCallEnv(sword rc, OCIEnv *envh)
121121
}
122122
}
123123

124-
/*****************************************************************************/
125-
/*
126-
DESCRIPTION
127-
This routine composes the driver name with version number to register with
128-
Database server.
129-
130-
PARAMETERS
131-
name - name of the driver (node-oracledb).
132-
namelen - buffer length for name.
133-
134-
RETURNS
135-
NONE
136-
137-
NOTES:
138-
This function expects a buffer of size DPI_DRIVER_NAME_LEN, composed
139-
name will be filled in this buffer and returned.
140-
*/
141-
void getDriverName (char *name, unsigned int namelen)
142-
{
143-
// Clear the buffer
144-
memset ( name, 0, namelen ) ;
145-
146-
// Compose the driver name+version
147-
snprintf ( name, namelen, "%s %d.%d.%d",
148-
DPI_DRIVER_NAME,
149-
(DPI_DRIVER_VERSION / 10000 ),
150-
(DPI_DRIVER_VERSION / 100 ),
151-
(DPI_DRIVER_VERSION % 100 )
152-
);
153-
}
154124

155125

156126

src/dpi/src/dpiUtils.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,6 @@
3737
PUBLIC CONSTANTS AND MACROS
3838
---------------------------------------------------------------------------*/
3939

40-
#define DPI_DRIVER_NAME_LEN (30) // Max lenght for driver name
41-
#define DPI_DRIVER_NAME ("node-oracledb")
42-
43-
/* Formula: 10000 x majorversion + 100 x minorversion + patchreleasenumber */
44-
/* 0.2.4 Keep the version in sync with package.json */
45-
#define DPI_DRIVER_VERSION (204)
46-
4740

4841

4942
/*---------------------------------------------------------------------------

src/njs/src/njsConnection.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -398,15 +398,14 @@ void Connection::ProcessOptions (const Arguments& args, unsigned int index,
398398
eBaton* executeBaton)
399399
{
400400
Local<Object> options;
401-
JSONValueIndicator ind;
402401
if(args[index]->IsObject() && !args[index]->IsArray())
403402
{
404403
options = args[index]->ToObject();
405-
NJS_GET_UINT_FROM_JSON ( executeBaton->maxRows, executeBaton->error, ind,
404+
NJS_GET_UINT_FROM_JSON ( executeBaton->maxRows, executeBaton->error,
406405
options, "maxRows", 2, exitProcessOptions );
407-
NJS_GET_UINT_FROM_JSON ( executeBaton->outFormat, executeBaton->error, ind,
406+
NJS_GET_UINT_FROM_JSON ( executeBaton->outFormat, executeBaton->error,
408407
options, "outFormat", 2, exitProcessOptions );
409-
NJS_GET_BOOL_FROM_JSON ( executeBaton->isAutoCommit, executeBaton->error, ind,
408+
NJS_GET_BOOL_FROM_JSON ( executeBaton->isAutoCommit, executeBaton->error,
410409
options, "isAutoCommit", 2, exitProcessOptions );
411410
}
412411
else
@@ -489,18 +488,17 @@ void Connection::GetBindUnit (Handle<Value> val, Bind* bind,
489488
eBaton* executeBaton)
490489
{
491490
HandleScope scope;
492-
JSONValueIndicator jvind;
493491
unsigned int dir = BIND_IN;
494492

495493
if(val->IsObject() && !val->IsDate())
496494
{
497495
Local<Object> bind_unit = val->ToObject();
498-
NJS_GET_UINT_FROM_JSON ( dir, executeBaton->error, jvind,
496+
NJS_GET_UINT_FROM_JSON ( dir, executeBaton->error,
499497
bind_unit, "dir", 1, exitGetBindUnit );
500-
NJS_GET_UINT_FROM_JSON ( bind->type, executeBaton->error, jvind,
498+
NJS_GET_UINT_FROM_JSON ( bind->type, executeBaton->error,
501499
bind_unit, "type", 1, exitGetBindUnit );
502500
bind->maxSize = NJS_MAX_OUT_BIND_SIZE;
503-
NJS_GET_UINT_FROM_JSON ( bind->maxSize, executeBaton->error, jvind,
501+
NJS_GET_UINT_FROM_JSON ( bind->maxSize, executeBaton->error,
504502
bind_unit, "maxSize", 1, exitGetBindUnit );
505503
if(!bind->maxSize && dir != BIND_IN)
506504
{

0 commit comments

Comments
 (0)