Skip to content

Commit ed0ee4f

Browse files
Added support for caching the database version in pooled connections
with Oracle Client 19 and earlier (later Oracle Clients handle this caching internally). This optimization eliminates a round-trip previously often required when reusing a pooled connection.
1 parent a7c3b45 commit ed0ee4f

File tree

4 files changed

+59
-14
lines changed

4 files changed

+59
-14
lines changed

doc/src/releasenotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ ODPI-C Release notes
44
Version 4.2.1 (TBD)
55
-------------------
66

7+
#) Added support for caching the database version in pooled connections with
8+
Oracle Client 19 and earlier (later Oracle Clients handle this caching
9+
internally). This optimization eliminates a round-trip previously often
10+
required when reusing a pooled connection.
711
#) All errors identified as causing a dead connection now populate
812
:member:`dpiErrorInfo.sqlState` with the value `01002` instead of only a
913
hard-coded list of errors.

doc/src/user_guide/round_trips.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,15 @@ back.
8888
- Maybe
8989
- The first call when requesting the release string always requires a
9090
round-trip. If the release string is not requested and Oracle Client
91-
20.3 or higher is being used, no round-trip is required; otherwise, a
92-
round-trip is required. Subsequent calls with any client version do not
93-
require a round-trip.
91+
20.3 or higher is being used, no round-trip is required. Similarly for
92+
earlier versions, if the release string is not requested and a pooled
93+
connection is used that previously had a call to this function made, no
94+
round-trip is required; otherwise, a round-trip is required. Subsequent
95+
calls with any client version do not require a round-trip.
9496
* - :func:`dpiConn_getSodaDb()`
95-
- No
96-
-
97+
- Maybe
98+
- An internal call to check the server version is made. The notes on the
99+
function :func:`dpiConn_getServerVersion()` apply.
97100
* - :func:`dpiConn_getStmtCacheSize()`
98101
- No
99102
-

src/dpiConn.c

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -695,24 +695,44 @@ int dpiConn__getServerVersion(dpiConn *conn, int wantReleaseString,
695695
dpiError *error)
696696
{
697697
char buffer[512], *releaseString;
698+
dpiVersionInfo *tempVersionInfo;
698699
uint32_t serverRelease, mode;
699700
uint32_t releaseStringLength;
701+
int ociCanCache;
700702

701703
// nothing to do if the server version has been cached earlier
702704
if (conn->releaseString ||
703705
(conn->versionInfo.versionNum > 0 && !wantReleaseString))
704706
return DPI_SUCCESS;
705707

706-
// the server version is not available in the cache so a call is required
707-
// to get it; as of Oracle Client 20.3, a special mode is available that
708-
// causes OCI to cache server version information; this mode can be used
709-
// exclusively once 20.3 is the minimum version supported by ODPI-C; until
710-
// that time, since ODPI-C already caches server version information
711-
// itself, this mode is only used when the release string is not requested,
712-
// in order to avoid the round-trip in that particular case
713-
if ((conn->env->versionInfo->versionNum > 20 ||
708+
// the server version is not available in the cache so it must be
709+
// determined; as of Oracle Client 20.3, a special mode is available that
710+
// causes OCI to cache the server version information, so this mode can be
711+
// used if the release string information is not desired and the client
712+
// supports it
713+
ociCanCache = ((conn->env->versionInfo->versionNum > 20 ||
714714
(conn->env->versionInfo->versionNum == 20 &&
715-
conn->env->versionInfo->releaseNum >= 3)) && !wantReleaseString) {
715+
conn->env->versionInfo->releaseNum >= 3)) && !wantReleaseString);
716+
717+
// for earlier versions where the OCI cache is not available, pooled
718+
// connections can cache the information on the session in order to avoid
719+
// the round trip, but again only if the release string is not desired;
720+
// nothing further needs to be done if this cache is present
721+
if (conn->pool && !ociCanCache && !wantReleaseString) {
722+
tempVersionInfo = NULL;
723+
if (dpiOci__contextGetValue(conn, DPI_CONTEXT_SERVER_VERSION,
724+
(uint32_t) (sizeof(DPI_CONTEXT_SERVER_VERSION) - 1),
725+
(void**) &tempVersionInfo, 1, error) < 0)
726+
return DPI_FAILURE;
727+
if (tempVersionInfo) {
728+
memcpy(&conn->versionInfo, tempVersionInfo,
729+
sizeof(conn->versionInfo));
730+
return DPI_SUCCESS;
731+
}
732+
}
733+
734+
// calculate the server version by making the appropriate call
735+
if (ociCanCache) {
716736
mode = DPI_OCI_SRVRELEASE2_CACHED;
717737
releaseString = NULL;
718738
releaseStringLength = 0;
@@ -756,6 +776,21 @@ int dpiConn__getServerVersion(dpiConn *conn, int wantReleaseString,
756776
conn->versionInfo.portReleaseNum,
757777
conn->versionInfo.portUpdateNum);
758778

779+
// for earlier versions where the OCI cache is not available, store the
780+
// version information on the session in order to avoid the round-trip the
781+
// next time the pooled session is acquired from the pool
782+
if (conn->pool && !ociCanCache) {
783+
if (dpiOci__memoryAlloc(conn, (void**) &tempVersionInfo,
784+
sizeof(conn->versionInfo), 1, error) < 0)
785+
return DPI_FAILURE;
786+
memcpy(tempVersionInfo, &conn->versionInfo, sizeof(conn->versionInfo));
787+
if (dpiOci__contextSetValue(conn, DPI_CONTEXT_SERVER_VERSION,
788+
(uint32_t) (sizeof(DPI_CONTEXT_SERVER_VERSION) - 1),
789+
tempVersionInfo, 1, error) < 0) {
790+
dpiOci__memoryFree(conn, tempVersionInfo, error);
791+
}
792+
}
793+
759794
return DPI_SUCCESS;
760795
}
761796

src/dpiImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ extern unsigned long dpiDebugLevel;
8484
// define context name for ping interval
8585
#define DPI_CONTEXT_LAST_TIME_USED "DPI_LAST_TIME_USED"
8686

87+
// define context name for server version information
88+
#define DPI_CONTEXT_SERVER_VERSION "DPI_SERVER_VERSION"
89+
8790
// define size of buffer used for numbers transferred to/from Oracle as text
8891
#define DPI_NUMBER_AS_TEXT_CHARS 172
8992

0 commit comments

Comments
 (0)