Skip to content

Commit 4f143f7

Browse files
committed
update callProcedure to handle multiple versions of a procedure with different parameters
1 parent 6ce98c6 commit 4f143f7

File tree

1 file changed

+58
-14
lines changed

1 file changed

+58
-14
lines changed

src/odbc_connection.cpp

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,8 @@ class CallProcedureAsyncWorker : public ODBCAsyncWorker {
13461346
return;
13471347
}
13481348

1349+
int proceduresFoundCount = data->storedRows.size();
1350+
13491351
data->deleteColumns(); // delete data in columns for next result set
13501352

13511353
return_code =
@@ -1393,27 +1395,69 @@ class CallProcedureAsyncWorker : public ODBCAsyncWorker {
13931395
return;
13941396
}
13951397

1396-
if (data->parameterCount != (SQLSMALLINT)data->storedRows.size()) {
1397-
SetError("[odbc] The number of parameters the procedure expects and and the number of passed parameters is not equal\0");
1398-
return;
1399-
}
1400-
14011398
#define SQLPROCEDURECOLUMNS_COLUMN_TYPE_INDEX 4
14021399
#define SQLPROCEDURECOLUMNS_DATA_TYPE_INDEX 5
14031400
#define SQLPROCEDURECOLUMNS_COLUMN_SIZE_INDEX 7
14041401
#define SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX 9
14051402
#define SQLPROCEDURECOLUMNS_NULLABLE_INDEX 11
1403+
#define SQLPROCEDURECOLUMNS_ORDINAL_POSITION 17
1404+
1405+
int strParamIdx = 0;
1406+
int endParamIdx = 0;
1407+
int priorOrdinalPos = 0;
1408+
int proceduresWithParametersCount = 0;
1409+
1410+
if (data->storedRows.size() > 0) {
1411+
proceduresWithParametersCount++;
1412+
}
1413+
1414+
for (endParamIdx = 0; endParamIdx < (SQLSMALLINT)data->storedRows.size(); endParamIdx++) {
1415+
if (endParamIdx > 0 && data->storedRows[endParamIdx][SQLPROCEDURECOLUMNS_ORDINAL_POSITION].integer_data <= priorOrdinalPos) {
1416+
// we found a boundary between different versions of the procedure name that should have different parameter counts
1417+
proceduresWithParametersCount++;
1418+
if (data->parameterCount == priorOrdinalPos)
1419+
break;
1420+
else
1421+
strParamIdx = endParamIdx;
1422+
}
1423+
priorOrdinalPos = data->storedRows[endParamIdx][SQLPROCEDURECOLUMNS_ORDINAL_POSITION].integer_data;
1424+
}
1425+
1426+
// if there was only one procedure candidate (or we're using the last one), fix the end parameter index
1427+
if (endParamIdx > (SQLSMALLINT)data->storedRows.size()) {
1428+
endParamIdx = data->storedRows.size();
1429+
}
1430+
1431+
// if we're looking for a procedure with zero parameters then reset the index variables so we don't try to bind any parameters
1432+
if (data->parameterCount == 0 && (SQLSMALLINT)(proceduresFoundCount > proceduresWithParametersCount)) {
1433+
strParamIdx = 0;
1434+
endParamIdx = 0;
1435+
}
1436+
1437+
// verify that the parameter count matches the number of rows that are matched above
1438+
if (data->parameterCount != (SQLSMALLINT)(endParamIdx - strParamIdx)) {
1439+
char errorString[255];
1440+
1441+
#ifndef UNICODE
1442+
sprintf(errorString, "[odbc] Could not find a procedure named %s with %d parameters", combinedProcedureName, data->parameterCount);
1443+
#else
1444+
sprintf(errorString, "[odbc] Could not find a procedure named %S with %d parameters", combinedProcedureName, data->parameterCount);
1445+
#endif
1446+
1447+
SetError(errorString);
1448+
return;
1449+
}
14061450

14071451
// get stored column parameter data from the result set
14081452

14091453
for (int i = 0; i < data->parameterCount; i++) {
14101454

14111455
Parameter *parameter = data->parameters[i];
14121456

1413-
data->parameters[i]->InputOutputType = data->storedRows[i][SQLPROCEDURECOLUMNS_COLUMN_TYPE_INDEX].smallint_data;
1414-
data->parameters[i]->ParameterType = data->storedRows[i][SQLPROCEDURECOLUMNS_DATA_TYPE_INDEX].smallint_data; // DataType -> ParameterType
1415-
data->parameters[i]->ColumnSize = data->storedRows[i][SQLPROCEDURECOLUMNS_COLUMN_SIZE_INDEX].integer_data; // ParameterSize -> ColumnSize
1416-
data->parameters[i]->Nullable = data->storedRows[i][SQLPROCEDURECOLUMNS_NULLABLE_INDEX].smallint_data;
1457+
data->parameters[i]->InputOutputType = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_COLUMN_TYPE_INDEX].smallint_data;
1458+
data->parameters[i]->ParameterType = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_DATA_TYPE_INDEX].smallint_data; // DataType -> ParameterType
1459+
data->parameters[i]->ColumnSize = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_COLUMN_SIZE_INDEX].integer_data; // ParameterSize -> ColumnSize
1460+
data->parameters[i]->Nullable = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_NULLABLE_INDEX].smallint_data;
14171461

14181462
// For each parameter, need to manipulate the data buffer and C type
14191463
// depending on what the InputOutputType is:
@@ -1745,36 +1789,36 @@ class CallProcedureAsyncWorker : public ODBCAsyncWorker {
17451789
data->parameters[i]->ValueType = SQL_C_CHAR;
17461790
data->parameters[i]->ParameterValuePtr = new SQLCHAR[bufferSize];
17471791
data->parameters[i]->BufferLength = bufferSize;
1748-
data->parameters[i]->DecimalDigits = data->storedRows[i][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
1792+
data->parameters[i]->DecimalDigits = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
17491793
break;
17501794

17511795
case SQL_DOUBLE:
17521796
case SQL_FLOAT:
17531797
data->parameters[i]->ValueType = SQL_C_DOUBLE;
17541798
data->parameters[i]->ParameterValuePtr = new SQLDOUBLE();
17551799
data->parameters[i]->BufferLength = sizeof(SQLDOUBLE);
1756-
data->parameters[i]->DecimalDigits = data->storedRows[i][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
1800+
data->parameters[i]->DecimalDigits = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
17571801
break;
17581802

17591803
case SQL_TINYINT:
17601804
data->parameters[i]->ValueType = SQL_C_UTINYINT;
17611805
data->parameters[i]->ParameterValuePtr = new SQLCHAR();
17621806
data->parameters[i]->BufferLength = sizeof(SQLCHAR);
1763-
data->parameters[i]->DecimalDigits = data->storedRows[i][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
1807+
data->parameters[i]->DecimalDigits = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
17641808
break;
17651809

17661810
case SQL_SMALLINT:
17671811
data->parameters[i]->ValueType = SQL_C_SSHORT;
17681812
data->parameters[i]->ParameterValuePtr = new SQLSMALLINT();
17691813
data->parameters[i]->BufferLength = sizeof(SQLSMALLINT);
1770-
data->parameters[i]->DecimalDigits = data->storedRows[i][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
1814+
data->parameters[i]->DecimalDigits = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
17711815
break;
17721816

17731817
case SQL_INTEGER:
17741818
data->parameters[i]->ValueType = SQL_C_SLONG;
17751819
data->parameters[i]->ParameterValuePtr = new SQLINTEGER();
17761820
data->parameters[i]->BufferLength = sizeof(SQLINTEGER);
1777-
data->parameters[i]->DecimalDigits = data->storedRows[i][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
1821+
data->parameters[i]->DecimalDigits = data->storedRows[i + strParamIdx][SQLPROCEDURECOLUMNS_DECIMAL_DIGITS_INDEX].smallint_data;
17781822
break;
17791823

17801824
case SQL_BIGINT:

0 commit comments

Comments
 (0)