From 481421ac1948289ab98f9af6f43533a5cd459761 Mon Sep 17 00:00:00 2001 From: Adalbert Makarovych Date: Wed, 9 Nov 2022 19:02:54 +0200 Subject: [PATCH] Performance improvements Summary: Changed to convert from UTF8 to UTF16 only once instead of two times. Changed to clean internal buffers lazily instead of cleaning them each time. **Design doc/spec**: **Docs impact**: none **Preliminary Reviewer(s)**: **Final Reviewer**: Test Plan: https://app.circleci.com/pipelines/github/memsql/singlestore-odbc-connector/2777 Reviewers: pmishchenko-ua Reviewed By: pmishchenko-ua Subscribers: engineering-list JIRA Issues: PLAT-6356 Differential Revision: https://grizzly.internal.memcompute.com/D59687 --- .circleci/config.yml | 2 +- CMakeLists.txt | 4 +-- ma_odbc.h | 1 + ma_platform_win32.c | 71 +++++++++++++++++++++++++++++--------------- odbc_3_api.c | 17 +++++------ 5 files changed, 58 insertions(+), 37 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e2d650ef..10277fb5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,7 +21,7 @@ version: 2.1 parameters: driver-version: type: string - default: "1.1.0" + default: "1.1.1" commands: setup-environment-linux: diff --git a/CMakeLists.txt b/CMakeLists.txt index 51e58302..303e0ada 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,10 +24,10 @@ SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment ver SET(MARIADB_ODBC_VERSION_MAJOR 1) SET(MARIADB_ODBC_VERSION_MINOR 1) -SET(MARIADB_ODBC_VERSION_PATCH 0) +SET(MARIADB_ODBC_VERSION_PATCH 1) SET(MARIADB_ODBC_VERSION_QUALITY "ga") -SET(MARIADB_ODBC_VERSION "01.01.0000") +SET(MARIADB_ODBC_VERSION "01.01.0001") IF(UNICODE OR NOT ANSI) MESSAGE(STATUS "Configuring to build Unicode driver") diff --git a/ma_odbc.h b/ma_odbc.h index 31f1d8cc..e459aeb2 100644 --- a/ma_odbc.h +++ b/ma_odbc.h @@ -316,6 +316,7 @@ struct st_ma_odbc_stmt MYSQL_BIND *result; MYSQL_BIND *params; int PutParam; + int LastSQLGetDataColumn; my_bool RebindParams; my_bool bind_done; long long AffectedRows; diff --git a/ma_platform_win32.c b/ma_platform_win32.c index 3063987f..7654dbd7 100644 --- a/ma_platform_win32.c +++ b/ma_platform_win32.c @@ -177,7 +177,6 @@ int MADB_ConvertAnsi2Unicode(Client_Charset *cc, const char *AnsiString, SQLLEN { SQLLEN RequiredLength; SQLWCHAR *Tmp= UnicodeString; - int rc= 0; if (LengthIndicator) *LengthIndicator= 0; @@ -195,39 +194,63 @@ int MADB_ConvertAnsi2Unicode(Client_Charset *cc, const char *AnsiString, SQLLEN if (AnsiLength == SQL_NTS || AnsiLength == -1) IsNull= 1; - /* calculate required length */ - RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, NULL, 0); - - /* Set LengthIndicator */ - if (LengthIndicator) - *LengthIndicator= RequiredLength - IsNull; if (!UnicodeLength) + { + // Return buffer is empty + // Get WideChar length if needed and return + if (LengthIndicator) { + RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, NULL, 0); + if (RequiredLength < 1) + { + if (Error) + MADB_SetError(Error, MADB_ERR_HY000, "Ansi to Unicode conversion error occurred", GetLastError()); + return 1; + } + + // Set LengthIndicator + *LengthIndicator= RequiredLength - IsNull; + } return 0; + } + + RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, Tmp, (int)UnicodeLength); + if (RequiredLength < 1 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // Buffer is too small + + RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, NULL, 0); + + // Set LengthIndicator + if (LengthIndicator) + *LengthIndicator= RequiredLength - IsNull; - if (RequiredLength > UnicodeLength) Tmp= (SQLWCHAR *)malloc(RequiredLength * sizeof(SQLWCHAR)); - - RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, Tmp, (int)RequiredLength); - if (RequiredLength < 1) - { - if (Error) - MADB_SetError(Error, MADB_ERR_HY000, "Ansi to Unicode conversion error occurred", GetLastError()); - rc= 1; - goto end; - } - /* Truncation */ - if (Tmp != UnicodeString) - { + RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, Tmp, (int)RequiredLength); + if (RequiredLength < 1) + { + if (Error) + MADB_SetError(Error, MADB_ERR_HY000, "Ansi to Unicode conversion error occurred", GetLastError()); + free(Tmp); + return 1; + } + wcsncpy(UnicodeString, L"", 1); wcsncat(UnicodeString, Tmp, UnicodeLength- 1); + free(Tmp); if (Error) MADB_SetError(Error, MADB_ERR_01004, NULL, 0); + } else if (RequiredLength < 1) + { + // Conversion error occurred + if (Error) + MADB_SetError(Error, MADB_ERR_HY000, "Ansi to Unicode conversion error occurred", GetLastError()); + return 1; + } else { + // Successfully converted string + // Set LengthIndicator + if (LengthIndicator) + *LengthIndicator= RequiredLength - IsNull; } -end: - if (Tmp != UnicodeString) - free(Tmp); - return rc; } /* Returns required length for result string with(if dest and dest length are provided) diff --git a/odbc_3_api.c b/odbc_3_api.c index ce3967ac..73e768e5 100644 --- a/odbc_3_api.c +++ b/odbc_3_api.c @@ -825,7 +825,6 @@ SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, SQLLEN *StrLen_or_IndPtr) { MADB_Stmt *Stmt= (MADB_Stmt*)StatementHandle; - unsigned int i; MADB_DescRecord *IrdRec; if (StatementHandle== SQL_NULL_HSTMT) @@ -856,19 +855,17 @@ SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, return MADB_SetError(&Stmt->Error, MADB_ERR_HY090, NULL, 0); } - /* reset offsets for other columns. Doing that here since "internal" calls should not do that */ - for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++) + /* reset offsets for column. Doing that here since "internal" calls should not do that */ + if (Stmt->LastSQLGetDataColumn != Col_or_Param_Num) { - if (i != Col_or_Param_Num - 1) + IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, Col_or_Param_Num - 1, MADB_DESC_READ); + if (IrdRec) { - IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, i, MADB_DESC_READ); - if (IrdRec) - { - MADB_FREE(IrdRec->InternalBuffer); - } - Stmt->CharOffset[i]= 0; + MADB_FREE(IrdRec->InternalBuffer); } + Stmt->CharOffset[Col_or_Param_Num - 1]= 0; } + Stmt->LastSQLGetDataColumn= Col_or_Param_Num; return Stmt->Methods->GetData(StatementHandle, Col_or_Param_Num, TargetType, TargetValuePtr, BufferLength, StrLen_or_IndPtr, FALSE); }