Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling stored procedure directly #547

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
7e70acb
read all responses before proceed
xiangyushawn Aug 9, 2017
30822e9
use a new method to determind if there are pending responses
xiangyushawn Aug 9, 2017
2c41c21
use raiserror instead of throw
xiangyushawn Aug 9, 2017
edd32b4
check if reach the end of the current packet
xiangyushawn Aug 9, 2017
f7d87f0
fix another failure for batching: if error happens, driver re-tries a…
xiangyushawn Aug 10, 2017
ed54cf2
add tests to validate how many times the column is updated by SP
xiangyushawn Aug 10, 2017
ef5c9b7
throw exception also fixes batch issue
xiangyushawn Aug 15, 2017
1e9b7a5
refactor code and use existing method
xiangyushawn Aug 18, 2017
53be4ab
refactor code
xiangyushawn Sep 13, 2017
edb19d2
Merge branch 'redundant-String-toString' of https://github.com/JamieM…
AfsanehR-zz Sep 29, 2017
afab91e
Merge branch 'cleanupTables' of https://github.com/v-afrafi/mssql-jdb…
AfsanehR-zz Oct 2, 2017
34d7b55
Merge branch 'dev' of https://github.com/Microsoft/mssql-jdbc into dev
AfsanehR-zz Oct 3, 2017
a159921
Merge branch 'dev' of https://github.com/Microsoft/mssql-jdbc into dev
AfsanehR-zz Oct 3, 2017
de21e71
Merge branch 'replace-bare-literals' of https://github.com/JamieMagee…
AfsanehR-zz Oct 6, 2017
845493a
Merge branch 'allow-at-sign-prefixed-param-names' of https://github.c…
AfsanehR-zz Oct 6, 2017
65aca83
Merge branch 'dev' of https://github.com/Microsoft/mssql-jdbc into dev
AfsanehR-zz Oct 6, 2017
8a217f6
Merge branch 'allow-at-sign-prefixed-param-names' of https://github.c…
AfsanehR-zz Oct 6, 2017
ad53d7a
Merge branch 'SQLServerDataTableImprovement-497' of https://github.co…
AfsanehR-zz Oct 6, 2017
385296f
Merge branch 'process-all-responses-before-proceed' of https://github…
AfsanehR-zz Oct 25, 2017
4223ccc
Merge branch 'dev' of https://github.com/Microsoft/mssql-jdbc into dev
AfsanehR-zz Oct 25, 2017
35e7195
Merge branch 'dev' of https://github.com/Microsoft/mssql-jdbc into dev
AfsanehR-zz Oct 31, 2017
de742d0
first commits of calling stored procedure directly
AfsanehR-zz Oct 31, 2017
9e28925
first commit of executing stored procedure directly
AfsanehR-zz Oct 31, 2017
e366910
cleaning up code
AfsanehR-zz Oct 31, 2017
d39f431
fixed an issue with not resetting TVPType check
AfsanehR-zz Oct 31, 2017
f02476f
resetting the access to returnValueAccessed
AfsanehR-zz Oct 31, 2017
a694b7f
remove the dependecy on expectedValueReturn and use inoutParams inste…
AfsanehR-zz Nov 1, 2017
9bc7257
cleaned up AE test and removed a wrong assertion
AfsanehR-zz Nov 1, 2017
b04eb93
make ae tests failures more clear in asserts
AfsanehR-zz Nov 1, 2017
7cbc486
fixed the failure for AE tests. Writing datetime as datetime if jdbct…
AfsanehR-zz Nov 6, 2017
839fc82
remove unused code
AfsanehR-zz Nov 8, 2017
263702d
fix the logging of calling procedure
AfsanehR-zz Nov 10, 2017
f8409ca
check for valid stored procedure calls like "exec proc 1, ?" where we…
AfsanehR-zz Nov 16, 2017
3f76e02
remove the metadata lookup for named parameters
AfsanehR-zz Nov 23, 2017
4439983
resolve conflicts with dev branch
AfsanehR-zz Nov 23, 2017
fb2c765
Merge branch 'dev' of https://github.com/Microsoft/mssql-jdbc into st…
AfsanehR-zz Nov 23, 2017
8b8a26a
added a fix for mix of setting input and output params
AfsanehR-zz Nov 24, 2017
5a757d9
added enum to make getterSetter Methods more clear plus other review …
AfsanehR-zz Nov 28, 2017
63f47d8
Merge branch 'dev' into storedProcedure
cheenamalhotra Feb 23, 2018
196671f
Merge branch 'dev' into storedProcedure
cheenamalhotra Jun 19, 2018
c9609e5
Merge branch 'dev' into storedProcedure
cheenamalhotra Feb 4, 2019
d92c133
Changes as per PR for storedProcedure calls
Feb 4, 2019
634f7cc
Fixes for breaking tests.
Feb 5, 2019
c198d11
Merge branch 'ms-dev' into af-storedProcedure
Feb 5, 2019
bdf49a1
Merge branch 'storedProcedure' into af-storedProcedure
Feb 5, 2019
8c68b58
Fix Statement Test
Feb 5, 2019
1a0373f
Code formatting
Feb 5, 2019
c9ad021
Merge branch 'dev' into storedProcedure
cheenamalhotra Mar 18, 2019
8442168
Merge branch 'dev' into storedProcedure
cheenamalhotra May 19, 2019
324d2b0
Merge branch 'dev' into storedProcedure
cheenamalhotra Jun 5, 2019
ac53c28
Fix conflict issues
cheenamalhotra Jun 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6479,6 +6479,7 @@ private boolean nextPacket() throws SQLServerException {
return true;
}


/**
* Reads the next packet of the TDS channel.
*
Expand Down
27 changes: 20 additions & 7 deletions src/main/java/com/microsoft/sqlserver/jdbc/Parameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ final CryptoMetadata getCryptoMetadata() {
private boolean shouldHonorAEForParameter = false;
private boolean userProvidesPrecision = false;
private boolean userProvidesScale = false;

private boolean isReturnValue = false;

// The parameter type definition
private String typeDefinition = null;
boolean renewDefinition = false;
Expand All @@ -72,6 +73,16 @@ boolean isOutput() {
return null != registeredOutDTV;
}

/** Checks if a parameter is return type*/
boolean isReturnValue() {
return isReturnValue;
}

/** Sets a parameter to be a return type */
void setReturnValue(boolean isReturnValue) {
this.isReturnValue = isReturnValue;
}

// Since a parameter can have only one type definition for both sending its value to the server (IN)
// and getting its value from the server (OUT), we use the JDBC type of the IN parameter value if there
// is one; otherwise we use the registered OUT param JDBC type.
Expand Down Expand Up @@ -207,9 +218,9 @@ final void skipValue(TDSReader tdsReader,
boolean isDiscard) throws SQLServerException {
if (null == getterDTV)
getterDTV = new DTV();

deriveTypeInfo(tdsReader);

getterDTV.skipValue(typeInfo, tdsReader, isDiscard);
}

Expand Down Expand Up @@ -254,7 +265,7 @@ void setFromReturnStatus(int returnStatus,
if (null == getterDTV)
getterDTV = new DTV();

getterDTV.setValue(null, JDBCType.INTEGER, returnStatus, JavaType.INTEGER, null, null, null, con, getForceEncryption());
getterDTV.setValue(null, this.getJdbcType(), returnStatus, JavaType.INTEGER, null, null, null, con, getForceEncryption());
}

void setValue(JDBCType jdbcType,
Expand Down Expand Up @@ -407,10 +418,12 @@ Object getValue(JDBCType jdbcType,
InputStreamGetterArgs getterArgs,
Calendar cal,
TDSReader tdsReader) throws SQLServerException {
if (null == getterDTV)
if (null == getterDTV) {
getterDTV = new DTV();

deriveTypeInfo(tdsReader);
}
if (null != tdsReader) {
deriveTypeInfo(tdsReader);
}
// If the parameter is not encrypted or column encryption is turned off (either at connection or
// statement level), cryptoMeta would be null.
return getterDTV.getValue(jdbcType, outScale, getterArgs, cal, typeInfo, cryptoMeta, tdsReader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,15 @@ public class SQLServerCallableStatement extends SQLServerPreparedStatement imple

/** Currently active Stream Note only one stream can be active at a time */
private Closeable activeStream;

/** Checks if return values is already accessed in stored procedure */
private boolean returnValueIsAccessed = false;

// Internal function used in tracing
String getClassNameInternal() {
return "SQLServerCallableStatement";
}


/**
* Create a new callable statement.
Expand All @@ -85,6 +89,7 @@ String getClassNameInternal() {
int nRSConcur,
SQLServerStatementColumnEncryptionSetting stmtColEncSetting) throws SQLServerException {
super(connection, sql, nRSType, nRSConcur, stmtColEncSetting);
returnValueIsAccessed = false;
}

public void registerOutParameter(int index,
Expand Down Expand Up @@ -156,14 +161,22 @@ private Parameter getOutParameter(int i) throws SQLServerException {
processResults();

// if this item has been indexed already leave!
if (inOutParam[i - 1] == lastParamAccessed || inOutParam[i - 1].isValueGotten())
if (inOutParam[i - 1] == lastParamAccessed || inOutParam[i - 1].isValueGotten()) {
// if it is a return value, increment the nOutParamsAssigned. Checking for isCursorable here is because the driver is executing
// the stored procedure for cursorable ones differently ( calling sp_cursorexecute r sp_cursorprepexec.
if (bReturnValueSyntax && inOutParam[i - 1].isValueGotten() && inOutParam[i - 1].isReturnValue() && !returnValueIsAccessed
&& !isCursorable(executeMethod) && !SQLServerPreparedStatement.isTVPType) {
nOutParamsAssigned++;
returnValueIsAccessed = true;
}
return inOutParam[i - 1];
}
if (inOutParam[i - 1].isReturnValue() && bReturnValueSyntax && !isCursorable(executeMethod) && !isTVPType)
return inOutParam[i - 1];

// Skip OUT parameters (buffering them as we go) until we
// reach the one we're looking for.
while (outParamIndex != i - 1)
skipOutParameters(1, false);

return inOutParam[i - 1];
}

Expand Down Expand Up @@ -212,18 +225,21 @@ final void processOutParameters() throws SQLServerException {
}

// Next, if there are any unindexed parameters left then discard them too.
assert nOutParamsAssigned <= nOutParams;
if (nOutParamsAssigned < nOutParams)
skipOutParameters(nOutParams - nOutParamsAssigned, true);

// Finally, skip the last-indexed parameter. If there were no unindexed parameters
// in the previous step, then this is the last-indexed parameter left from the first
// step. If we skipped unindexed parameters in the previous step, then this is the
// last-indexed parameter left at the end of that step.
if (outParamIndex >= 0) {
inOutParam[outParamIndex].skipValue(resultsReader(), true);
inOutParam[outParamIndex].resetOutputValue();
outParamIndex = -1;
if (nOutParamsAssigned <= nOutParams) {
if (bReturnValueSyntax && (nOutParamsAssigned == 0) && !isCursorable(executeMethod))
nOutParamsAssigned++;
if (nOutParamsAssigned < nOutParams)
skipOutParameters(nOutParams - nOutParamsAssigned, true);

// Finally, skip the last-indexed parameter. If there were no unindexed parameters
// in the previous step, then this is the last-indexed parameter left from the first
// step. If we skipped unindexed parameters in the previous step, then this is the
// last-indexed parameter left at the end of that step.
if (outParamIndex >= 0) {
inOutParam[outParamIndex].skipValue(resultsReader(), true);
inOutParam[outParamIndex].resetOutputValue();
outParamIndex = -1;
}
}
}

Expand Down Expand Up @@ -289,57 +305,67 @@ boolean onRetValue(TDSReader tdsReader) throws SQLServerException {

OutParamHandler outParamHandler = new OutParamHandler();

if (bReturnValueSyntax && (nOutParamsAssigned == 0) && !isCursorable(executeMethod) && !isTVPType)
nOutParamsAssigned++;
// Index the application OUT parameters
assert numParamsToSkip <= nOutParams - nOutParamsAssigned;
for (int paramsSkipped = 0; paramsSkipped < numParamsToSkip; ++paramsSkipped) {
// Discard the last-indexed parameter by skipping over it and
// discarding the value if it is no longer needed.
if (-1 != outParamIndex) {
inOutParam[outParamIndex].skipValue(resultsReader(), discardValues);
if (discardValues)
inOutParam[outParamIndex].resetOutputValue();
}

// Look for the next parameter value in the response.
outParamHandler.reset();
TDSParser.parse(resultsReader(), outParamHandler);

// If we don't find it, then most likely the server encountered some error that
// was bad enough to halt statement execution before returning OUT params, but
// not necessarily bad enough to close the connection.
if (!outParamHandler.foundParam()) {
// If we were just going to discard the OUT parameters we found anyway,
// then it's no problem that we didn't find any of them. For exmaple,
// when we are closing or reexecuting this CallableStatement (that is,
// calling in through processResponse), we don't care that execution
// failed to return the OUT parameters.
if (discardValues)
break;
// assert numParamsToSkip <= nOutParams - nOutParamsAssigned ;
if (numParamsToSkip <= nOutParams - nOutParamsAssigned) {
for (int paramsSkipped = 0; paramsSkipped < numParamsToSkip; ++paramsSkipped) {

// Discard the last-indexed parameter by skipping over it and
// discarding the value if it is no longer needed.
if (-1 != outParamIndex ) {
inOutParam[outParamIndex].skipValue(resultsReader(), discardValues);
if (discardValues)
inOutParam[outParamIndex].resetOutputValue();
}

// If we were asked to retain the OUT parameters as we skip past them,
// then report an error if we did not find any.
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_valueNotSetForParameter"));
Object[] msgArgs = {outParamIndex + 1};
SQLServerException.makeFromDriverError(connection, this, form.format(msgArgs), null, false);
}
// Look for the next parameter value in the response.
outParamHandler.reset();
TDSParser.parse(resultsReader(), outParamHandler);

// If we don't find it, then most likely the server encountered some error that
// was bad enough to halt statement execution before returning OUT params, but
// not necessarily bad enough to close the connection.
if (!outParamHandler.foundParam()) {
// If we were just going to discard the OUT parameters we found anyway,
// then it's no problem that we didn't find any of them. For exmaple,
// when we are closing or reexecuting this CallableStatement (that is,
// calling in through processResponse), we don't care that execution
// failed to return the OUT parameters.
if (discardValues)
break;

// If we were asked to retain the OUT parameters as we skip past them,
// then report an error if we did not find any.
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_valueNotSetForParameter"));
Object[] msgArgs = {outParamIndex + 1};
SQLServerException.makeFromDriverError(connection, this, form.format(msgArgs), null, false);
}

// In Yukon and later, large Object output parameters are reordered to appear at
// the end of the stream. First group of small parameters is sent, followed by
// group of large output parameters. There is no reordering within the groups.
// In Yukon and later, large Object output parameters are reordered to appear at
// the end of the stream. First group of small parameters is sent, followed by
// group of large output parameters. There is no reordering within the groups.

// Note that parameter ordinals are 0-indexed and that the return status is not
// considered to be an output parameter.
outParamIndex = outParamHandler.srv.getOrdinalOrLength();
// Note that parameter ordinals are 0-indexed and that the return status is not
// considered to be an output parameter.
outParamIndex = outParamHandler.srv.getOrdinalOrLength();
if (bReturnValueSyntax && !isCursorable(executeMethod) && !isTVPType) {
outParamIndex++;
}
// Statements need to have their out param indices adjusted by the number
// of sp_[cursor][prep]exec params.
else if (isCursorable(executeMethod) || isTVPType) {
outParamIndex -= outParamIndexAdjustment;
}
if ((outParamIndex < 0 || outParamIndex >= inOutParam.length) || (!inOutParam[outParamIndex].isOutput())) {
getStatementLogger()
.info(toString() + " Unexpected outParamIndex: " + outParamIndex + "; adjustment: " + outParamIndexAdjustment);
connection.throwInvalidTDS();
}

// Statements need to have their out param indices adjusted by the number
// of sp_[cursor][prep]exec params.
outParamIndex -= outParamIndexAdjustment;
if ((outParamIndex < 0 || outParamIndex >= inOutParam.length) || (!inOutParam[outParamIndex].isOutput())) {
getStatementLogger().info(toString() + " Unexpected outParamIndex: " + outParamIndex + "; adjustment: " + outParamIndexAdjustment);
connection.throwInvalidTDS();
++nOutParamsAssigned;
}

++nOutParamsAssigned;
}
}

Expand Down Expand Up @@ -424,7 +450,14 @@ private Parameter getterGetParam(int index) throws SQLServerException {

private Object getValue(int parameterIndex,
JDBCType jdbcType) throws SQLServerException {
return getterGetParam(parameterIndex).getValue(jdbcType, null, null, resultsReader());
Parameter param = getterGetParam(parameterIndex);
if (!param.isValueGotten() || !param.isReturnValue()) {
return param.getValue(jdbcType, null, null, resultsReader());
}
else {
// if we have already retrieved the value, we have the typeInfo and we do not need to get it again
return param.getValue(param.getJdbcType(), null, null, null);
}
}

private Object getValue(int parameterIndex,
Expand Down Expand Up @@ -1386,8 +1419,7 @@ public NClob getNClob(String parameterName) throws SQLException {
return getArray(findColumn(sCol));
}

/* JDBC 3.0 */

/* JDBC 3.0 */
/**
* Find a column's index given its name.
*
Expand Down Expand Up @@ -1459,7 +1491,6 @@ public NClob getNClob(String parameterName) throws SQLException {
} else {
columnNameWithoutAtSign = columnName;
}

// In order to be as accurate as possible when locating parameter name
// indexes, as well as be deterministic when running on various client
// locales, we search for parameter names using the following scheme:
Expand Down Expand Up @@ -1504,7 +1535,7 @@ public NClob getNClob(String parameterName) throws SQLException {
return matchPos + 1;
else
return matchPos;
}
}

public void setTimestamp(String sCol,
java.sql.Timestamp x,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ static ParsedSQLCacheItem parseAndCacheSQL(Sha1HashKey key, String sql) throws
String parsedSql = translator.translate(sql);
String procName = translator.getProcedureName(); // may return null
boolean returnValueSyntax = translator.hasReturnValueSyntax();
int paramCount = countParams(parsedSql);
int paramCount = countParams(sql);

ParsedSQLCacheItem cacheItem = new ParsedSQLCacheItem (parsedSql, paramCount, procName, returnValueSyntax);
parsedSQLCache.putIfAbsent(key, cacheItem);
Expand All @@ -287,15 +287,15 @@ static ParsedSQLCacheItem parseAndCacheSQL(Sha1HashKey key, String sql) throws
* @param sql
* SQL text to parse for number of parameters to intialize.
*/
private static int countParams(String sql) {
static int countParams(String sql) {
int nParams = 0;

// Figure out the expected number of parameters by counting the
// parameter placeholders in the SQL string.
int offset = -1;
while ((offset = ParameterUtils.scanSQLForChar('?', sql, ++offset)) < sql.length())
++nParams;

return nParams;
}

Expand Down
Loading