-
Notifications
You must be signed in to change notification settings - Fork 426
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ local.properties | |
.classpath | ||
.vscode/ | ||
.settings/ | ||
.gradle/ | ||
.loadpath | ||
|
||
# External tool builders | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,13 @@ | |
<optional>true</optional> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
<version>19.0</version> | ||
<optional>false</optional> | ||
</dependency> | ||
|
||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
sehrope
Contributor
|
||
<!-- dependency for running tests --> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,9 @@ | |
import java.util.Vector; | ||
import java.util.logging.Level; | ||
|
||
import com.google.common.cache.CacheBuilder; | ||
import com.google.common.cache.Cache; | ||
|
||
/** | ||
* SQLServerPreparedStatement provides JDBC prepared statement functionality. SQLServerPreparedStatement provides methods for the user to supply | ||
* parameters as any native Java type and many Java object types. | ||
|
@@ -98,6 +101,48 @@ public class SQLServerPreparedStatement extends SQLServerStatement implements IS | |
*/ | ||
private boolean encryptionMetadataIsRetrieved = false; | ||
|
||
/** Size of the prepared statement meta data cache */ | ||
static final private int preparedStatementMetadataSQLCacheSize = 100; | ||
This comment has been minimized.
Sorry, something went wrong.
brettwooldridge
Contributor
|
||
|
||
/** Cache of prepared statement meta data */ | ||
static private Cache<String, PreparedStatementMetadataSQLCacheItem> preparedStatementSQLMetadataCache; | ||
static { | ||
preparedStatementSQLMetadataCache = CacheBuilder.newBuilder() | ||
.maximumSize(preparedStatementMetadataSQLCacheSize) | ||
.build(); | ||
} | ||
|
||
/** | ||
* Used to keep track of an individual handle ready for un-prepare. | ||
*/ | ||
private final class PreparedStatementMetadataSQLCacheItem { | ||
String preparedSQLText; | ||
int parameterCount; | ||
String procedureName; | ||
boolean bReturnValueSyntax; | ||
|
||
PreparedStatementMetadataSQLCacheItem(String preparedSQLText, int parameterCount, String procedureName, boolean bReturnValueSyntax){ | ||
this.preparedSQLText = preparedSQLText; | ||
this.parameterCount = parameterCount; | ||
this.procedureName = procedureName; | ||
this.bReturnValueSyntax = bReturnValueSyntax; | ||
} | ||
} | ||
|
||
/** Get prepared statement cache entry if exists */ | ||
public PreparedStatementMetadataSQLCacheItem getCachedPreparedStatementSQLMetadata(String initialSql){ | ||
return preparedStatementSQLMetadataCache.getIfPresent(initialSql); | ||
} | ||
|
||
/** Cache entry for this prepared statement */ | ||
public PreparedStatementMetadataSQLCacheItem metadataSQLCacheItem; | ||
|
||
/** Add cache entry for prepared statement metadata*/ | ||
public void cachePreparedStatementSQLMetaData(String initialSql, PreparedStatementMetadataSQLCacheItem newItem){ | ||
|
||
preparedStatementSQLMetadataCache.put(initialSql, newItem); | ||
} | ||
|
||
// Internal function used in tracing | ||
String getClassNameInternal() { | ||
return "SQLServerPreparedStatement"; | ||
|
@@ -128,13 +173,34 @@ String getClassNameInternal() { | |
stmtPoolable = true; | ||
sqlCommand = sql; | ||
|
||
JDBCSyntaxTranslator translator = new JDBCSyntaxTranslator(); | ||
sql = translator.translate(sql); | ||
procedureName = translator.getProcedureName(); // may return null | ||
bReturnValueSyntax = translator.hasReturnValueSyntax(); | ||
|
||
userSQL = sql; | ||
initParams(userSQL); | ||
// Save original SQL statement. | ||
sqlCommand = sql; | ||
This comment has been minimized.
Sorry, something went wrong.
brettwooldridge
Contributor
|
||
|
||
// Check for cached SQL metadata. | ||
PreparedStatementMetadataSQLCacheItem cacheItem = getCachedPreparedStatementSQLMetadata(sql); | ||
|
||
// No cached meta data found, parse. | ||
if(null == cacheItem) { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
JDBCSyntaxTranslator translator = new JDBCSyntaxTranslator(); | ||
|
||
userSQL = translator.translate(sql); | ||
procedureName = translator.getProcedureName(); // may return null | ||
bReturnValueSyntax = translator.hasReturnValueSyntax(); | ||
|
||
// Save processed SQL statement. | ||
initParams(userSQL); | ||
|
||
// Cache this entry. | ||
cacheItem = new PreparedStatementMetadataSQLCacheItem(userSQL, inOutParam.length, procedureName, bReturnValueSyntax); | ||
cachePreparedStatementSQLMetaData(sqlCommand/*original command as key*/, cacheItem); | ||
} | ||
else { | ||
// Retrieve from cache item. | ||
procedureName = cacheItem.procedureName; | ||
bReturnValueSyntax = cacheItem.bReturnValueSyntax; | ||
userSQL = cacheItem.preparedSQLText; | ||
initParams(cacheItem.parameterCount); | ||
} | ||
} | ||
|
||
/** | ||
|
@@ -217,12 +283,11 @@ final void closeInternal() { | |
} | ||
|
||
/** | ||
* Intialize the statement parameters. | ||
* Find and intialize the statement parameters. | ||
* | ||
* @param sql | ||
*/ | ||
/* L0 */ final void initParams(String sql) { | ||
encryptionMetadataIsRetrieved = false; | ||
int nParams = 0; | ||
|
||
// Figure out the expected number of parameters by counting the | ||
|
@@ -231,6 +296,15 @@ final void closeInternal() { | |
while ((offset = ParameterUtils.scanSQLForChar('?', sql, ++offset)) < sql.length()) | ||
++nParams; | ||
|
||
initParams(nParams); | ||
} | ||
|
||
/** | ||
* Intialize the statement parameters. | ||
* | ||
* @param sql | ||
*/ | ||
/* L0 */ final void initParams(int nParams) { | ||
inOutParam = new Parameter[nParams]; | ||
for (int i = 0; i < nParams; i++) { | ||
inOutParam[i] = new Parameter(Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)); | ||
|
1 comment
on commit 0a52a12
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise, nice work.
I don't think a dependency on guava is going to fly. But a simple LRU cache such as the one I wrote for jTDS is trivial to implement (associated key class). Requires external synchronization.