[core] Fix ODBC column size performance issue
This commit is contained in:
parent
2dfda2f409
commit
7e2c9393dc
|
@ -605,17 +605,66 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c
|
|||
for (x = 1; x <= c; x++) {
|
||||
SQLSMALLINT NameLength = 0, DataType = 0, DecimalDigits = 0, Nullable = 0;
|
||||
SQLULEN ColumnSize = 0;
|
||||
SQLLEN numRecs = 0;
|
||||
SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
|
||||
SQLINTEGER NativeError;
|
||||
SQLSMALLINT diagCount, MsgLen;
|
||||
names[y] = malloc(name_len);
|
||||
switch_assert(names[y]);
|
||||
memset(names[y], 0, name_len);
|
||||
|
||||
SQLDescribeCol(stmt, x, (SQLCHAR *) names[y], (SQLSMALLINT) name_len, &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
|
||||
|
||||
if (!ColumnSize) {
|
||||
if (ColumnSize <= 16383 || ColumnSize == 2147483647) {
|
||||
SQLCHAR val[16384] = { 0 };
|
||||
SQLLEN StrLen_or_IndPtr;
|
||||
SQLRETURN rc;
|
||||
ColumnSize = 16384;
|
||||
SQLGetData(stmt, x, SQL_C_CHAR, val, ColumnSize, NULL);
|
||||
vals[y] = strdup((char *)val);
|
||||
|
||||
/* check diag record and see if we can get real size
|
||||
* https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/using-sqlgetdiagrec-and-sqlgetdiagfield?view=sql-server-ver15
|
||||
* szSqlState = "01004" and StrLen_or_IndPtr=15794
|
||||
*/
|
||||
rc = SQLGetData(stmt, x, SQL_C_CHAR, val, ColumnSize, &StrLen_or_IndPtr);
|
||||
|
||||
if (rc == SQL_SUCCESS_WITH_INFO) {
|
||||
int truncated = 0;
|
||||
diagCount = 1;
|
||||
|
||||
SQLGetDiagField(SQL_HANDLE_STMT, stmt, 0, SQL_DIAG_NUMBER, &numRecs, 0, 0);
|
||||
|
||||
while (diagCount <= numRecs) {
|
||||
SQLGetDiagRec(SQL_HANDLE_STMT, stmt, diagCount, SqlState, &NativeError,Msg, sizeof(Msg), &MsgLen);
|
||||
if (!strcmp((char*)SqlState,"01004")){
|
||||
truncated = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
diagCount++;
|
||||
}
|
||||
|
||||
if (truncated) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sql data truncated - %s\n",SqlState);
|
||||
if (StrLen_or_IndPtr && StrLen_or_IndPtr <= 268435456) {
|
||||
ColumnSize = StrLen_or_IndPtr + 1;
|
||||
vals[y] = malloc(ColumnSize);
|
||||
switch_assert(vals[y]);
|
||||
memset(vals[y], 0, ColumnSize);
|
||||
SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *) vals[y], ColumnSize, NULL);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLGetData failed");
|
||||
vals[y] = NULL;
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLGetData failed");
|
||||
vals[y] = NULL;
|
||||
}
|
||||
} else if (rc == SQL_SUCCESS){
|
||||
vals[y] = strdup((char *)val);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLGetData failed");
|
||||
vals[y] = NULL;
|
||||
}
|
||||
} else {
|
||||
ColumnSize++;
|
||||
|
||||
|
@ -633,7 +682,7 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(c
|
|||
|
||||
for (x = 0; x < y; x++) {
|
||||
free(names[x]);
|
||||
free(vals[x]);
|
||||
switch_safe_free(vals[x]);
|
||||
}
|
||||
free(names);
|
||||
free(vals);
|
||||
|
|
Loading…
Reference in New Issue