[PATCH v2 0/1] MR6263: odbc32: Add support for descriptor handles in SQLGet/SetStmtAttr().
-- v2: odbc32: Add support for descriptor handles in SQLGet/SetStmtAttr(). https://gitlab.winehq.org/wine/wine/-/merge_requests/6263
From: Hans Leidekker <hans(a)codeweavers.com> --- dlls/odbc32/proxyodbc.c | 137 ++++++++++++++++++++++++++++++++++--- dlls/odbc32/tests/odbc32.c | 44 +++++++++--- 2 files changed, 162 insertions(+), 19 deletions(-) diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 2a62fd88d64..299f1f8e08b 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -518,20 +518,48 @@ static SQLRETURN alloc_handle( SQLSMALLINT type, struct object *input, struct ob return ret; } -static struct statement *create_statement( struct connection *con ) +static struct descriptor *create_descriptor( struct statement *stmt ) { - struct statement *ret; + struct descriptor *ret; if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL; - init_object( &ret->hdr, SQL_HANDLE_STMT, &con->hdr ); - ret->row_count = 1; + init_object( &ret->hdr, SQL_HANDLE_DESC, &stmt->hdr ); return ret; } -static struct descriptor *create_descriptor( struct statement *stmt ) +static void free_descriptors( struct statement *stmt ) { - struct descriptor *ret; + unsigned int i; + for (i = 0; i < ARRAY_SIZE(stmt->desc); i++) + { + if (stmt->desc[i]) destroy_object( &stmt->desc[i]->hdr ); + } +} + +static SQLRETURN alloc_descriptors( struct statement *stmt ) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(stmt->desc); i++) + { + if (!(stmt->desc[i] = create_descriptor( NULL ))) + { + free_descriptors( stmt ); + return SQL_ERROR; + } + } + return SQL_SUCCESS; +} + +static struct statement *create_statement( struct connection *con ) +{ + struct statement *ret; if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL; - init_object( &ret->hdr, SQL_HANDLE_DESC, &stmt->hdr ); + init_object( &ret->hdr, SQL_HANDLE_STMT, &con->hdr ); + if (alloc_descriptors( ret )) + { + destroy_object( &ret->hdr ); + return NULL; + } + ret->row_count = 1; return ret; } @@ -2070,6 +2098,7 @@ SQLRETURN WINAPI SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) struct statement *stmt = (struct statement *)obj; free_col_bindings( stmt ); free_param_bindings( stmt ); + free_descriptors( stmt ); break; } default: break; @@ -2134,6 +2163,7 @@ SQLRETURN WINAPI SQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option) default: free_col_bindings( stmt ); free_param_bindings( stmt ); + free_descriptors( stmt ); stmt->hdr.closed = TRUE; break; } @@ -2963,6 +2993,30 @@ SQLRETURN WINAPI SQLGetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, ret = get_stmt_attr_win32_a( stmt, Attribute, Value, BufferLength, StringLength ); } + if (!ret) + { + switch (Attribute) + { + case SQL_ATTR_APP_ROW_DESC: + case SQL_ATTR_APP_PARAM_DESC: + case SQL_ATTR_IMP_ROW_DESC: + case SQL_ATTR_IMP_PARAM_DESC: + { + struct descriptor *desc = stmt->desc[Attribute - SQL_ATTR_APP_ROW_DESC]; + if (stmt->hdr.unix_handle) + { + if (sizeof(desc->hdr.unix_handle) > sizeof(SQLHDESC)) + ERR( "truncating descriptor handle, consider using a Windows driver\n" ); + desc->hdr.unix_handle = (ULONG_PTR)*(SQLHDESC *)Value; + } + else if (stmt->hdr.win32_handle) desc->hdr.win32_handle = *(SQLHDESC *)Value; + *(struct descriptor **)Value = desc; + break; + } + default: break; + } + } + TRACE("Returning %d\n", ret); unlock_object( &stmt->hdr ); return ret; @@ -3790,6 +3844,28 @@ SQLRETURN WINAPI SQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, if (!stmt) return SQL_INVALID_HANDLE; + switch (Attribute) + { + case SQL_ATTR_APP_ROW_DESC: + case SQL_ATTR_APP_PARAM_DESC: + { + struct descriptor *desc = (struct descriptor *)lock_object( Value, SQL_HANDLE_DESC ); + if (desc) + { + if (stmt->hdr.unix_handle) + { + if (sizeof(desc->hdr.unix_handle) > sizeof(Value)) + ERR( "truncating descriptor handle, consider using a Windows driver\n" ); + Value = (SQLPOINTER)(ULONG_PTR)desc->hdr.unix_handle; + } + else Value = desc->hdr.win32_handle; + unlock_object( &desc->hdr ); + } + break; + } + default: break; + } + if (stmt->hdr.unix_handle) { ret = set_stmt_attr_unix_a( stmt, Attribute, Value, StringLength ); @@ -6228,7 +6304,6 @@ SQLRETURN WINAPI SQLGetStmtAttrW(SQLHSTMT StatementHandle, SQLINTEGER Attribute, TRACE("(StatementHandle %p, Attribute %d, Value %p, BufferLength %d, StringLength %p)\n", StatementHandle, Attribute, Value, BufferLength, StringLength); - if (!Value) return SQL_ERROR; if (!stmt) return SQL_INVALID_HANDLE; if (stmt->hdr.unix_handle) @@ -6240,6 +6315,28 @@ SQLRETURN WINAPI SQLGetStmtAttrW(SQLHSTMT StatementHandle, SQLINTEGER Attribute, ret = get_stmt_attr_win32_w( stmt, Attribute, Value, BufferLength, StringLength ); } + if (!ret) + { + switch (Attribute) + { + case SQL_ATTR_APP_ROW_DESC: + case SQL_ATTR_APP_PARAM_DESC: + { + struct descriptor *desc = stmt->desc[Attribute - SQL_ATTR_APP_ROW_DESC]; + if (stmt->hdr.unix_handle) + { + if (sizeof(desc->hdr.unix_handle) > sizeof(SQLHDESC)) + ERR( "truncating descriptor handle, consider using a Windows driver\n" ); + desc->hdr.unix_handle = (ULONG_PTR)*(SQLHDESC *)Value; + } + else if (stmt->hdr.win32_handle) desc->hdr.win32_handle = *(SQLHDESC *)Value; + *(struct descriptor **)Value = desc; + break; + } + default: break; + } + } + TRACE("Returning %d\n", ret); unlock_object( &stmt->hdr ); return ret; @@ -7450,6 +7547,30 @@ SQLRETURN WINAPI SQLSetStmtAttrW(SQLHSTMT StatementHandle, SQLINTEGER Attribute, if (!stmt) return SQL_INVALID_HANDLE; + switch (Attribute) + { + case SQL_ATTR_APP_ROW_DESC: + case SQL_ATTR_APP_PARAM_DESC: + case SQL_ATTR_IMP_ROW_DESC: + case SQL_ATTR_IMP_PARAM_DESC: + { + struct descriptor *desc = (struct descriptor *)lock_object( Value, SQL_HANDLE_DESC ); + if (desc) + { + if (stmt->hdr.unix_handle) + { + if (sizeof(desc->hdr.unix_handle) > sizeof(Value)) + ERR( "truncating descriptor handle, consider using a Windows driver\n" ); + Value = (SQLPOINTER)(ULONG_PTR)desc->hdr.unix_handle; + } + else Value = desc->hdr.win32_handle; + unlock_object( &desc->hdr ); + } + break; + } + default: break; + } + if (stmt->hdr.unix_handle) { ret = set_stmt_attr_unix_w( stmt, Attribute, Value, StringLength ); diff --git a/dlls/odbc32/tests/odbc32.c b/dlls/odbc32/tests/odbc32.c index 3583e69e98e..7fdeb0ee75d 100644 --- a/dlls/odbc32/tests/odbc32.c +++ b/dlls/odbc32/tests/odbc32.c @@ -317,11 +317,12 @@ static void test_SQLExecDirect( void ) SQLHENV env; SQLHDBC con; SQLHSTMT stmt; + SQLHDESC desc; SQLRETURN ret; - SQLLEN count, len_id[2], len_name[2]; + SQLLEN count, len_id[2], len_name[2], len_octet; SQLULEN rows_fetched; - SQLINTEGER id[2], err; - SQLCHAR name[32], msg[32], state[6]; + SQLINTEGER id[2], err, size; + SQLCHAR name[32], msg[256], state[6]; SQLSMALLINT len; ret = SQLAllocEnv( &env ); @@ -344,6 +345,18 @@ static void test_SQLExecDirect( void ) ret = SQLAllocStmt( con, &stmt ); ok( ret == SQL_SUCCESS, "got %d\n", ret ); + ret = SQLError( NULL, NULL, NULL, state, &err, msg, sizeof(msg), &len ); + ok( ret == SQL_INVALID_HANDLE, "got %d\n", ret ); + + ret = SQLError( env, NULL, NULL, state, &err, msg, sizeof(msg), &len ); + ok( ret == SQL_NO_DATA, "got %d\n", ret ); + + ret = SQLError( env, con, NULL, state, &err, msg, sizeof(msg), &len ); + ok( ret == SQL_NO_DATA, "got %d\n", ret ); + + ret = SQLError( env, con, stmt, state, &err, msg, sizeof(msg), &len ); + ok( ret == SQL_NO_DATA, "got %d\n", ret ); + SQLExecDirect( stmt, (SQLCHAR *)"USE winetest", ARRAYSIZE("USE winetest") - 1 ); SQLExecDirect( stmt, (SQLCHAR *)"DROP TABLE winetest", ARRAYSIZE("DROP TABLE winetest") - 1 ); ret = SQLExecDirect( stmt, (SQLCHAR *)"CREATE TABLE winetest ( Id int, Name varchar(255) )", @@ -471,17 +484,26 @@ static void test_SQLExecDirect( void ) ret = SQLExecDirect( stmt, (SQLCHAR *)"DROP TABLE winetest", ARRAYSIZE("DROP TABLE winetest") - 1 ); ok( ret == SQL_SUCCESS, "got %d\n", ret ); - ret = SQLError( NULL, NULL, NULL, state, &err, msg, sizeof(msg), &len ); - ok( ret == SQL_INVALID_HANDLE, "got %d\n", ret ); + desc = (SQLHDESC)0xdeadbeef; + size = 0xdeadbeef; + ret = SQLGetStmtAttr( stmt, SQL_ATTR_APP_ROW_DESC, &desc, sizeof(desc), &size ); + if (ret == SQL_ERROR) diag( stmt, SQL_HANDLE_STMT ); + ok( ret == SQL_SUCCESS, "got %d\n", ret ); + ok( desc != (SQLHDESC)0xdeadbeef, "desc not set\n" ); + ok( size == 0xdeadbeef, "got %d\n", size ); - ret = SQLError( env, NULL, NULL, state, &err, msg, sizeof(msg), &len ); - ok( ret == SQL_NO_DATA, "got %d\n", ret ); + ret = SQLSetDescField( desc, 1, SQL_DESC_OCTET_LENGTH_PTR, &len_octet, 0 ); + if (ret == SQL_ERROR) diag( stmt, SQL_HANDLE_DESC ); + ok( ret == SQL_SUCCESS, "got %d\n", ret ); - ret = SQLError( env, con, NULL, state, &err, msg, sizeof(msg), &len ); - ok( ret == SQL_NO_DATA, "got %d\n", ret ); + ret = SQLSetStmtAttr( stmt, SQL_ATTR_APP_ROW_DESC, NULL, sizeof(desc) ); + ok( ret == SQL_SUCCESS, "got %d\n", ret ); - ret = SQLError( env, con, stmt, state, &err, msg, sizeof(msg), &len ); - ok( ret == SQL_NO_DATA, "got %d\n", ret ); + ret = SQLSetStmtAttr( stmt, SQL_ATTR_APP_ROW_DESC, desc, 0 ); + ok( ret == SQL_SUCCESS, "got %d\n", ret ); + + ret = SQLSetStmtAttr( stmt, SQL_ATTR_IMP_ROW_DESC, NULL, sizeof(desc) ); + ok( ret == SQL_ERROR, "got %d\n", ret ); ret = SQLFreeStmt( stmt, SQL_DROP ); ok( ret == SQL_SUCCESS, "got %d\n", ret ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6263
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147711 Your paranoid android. === debian11 (build log) === ../wine/dlls/odbc32/proxyodbc.c:532:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:532:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:534:17: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:534:49: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:541:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:541:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:543:19: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:3005:43: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:6325:43: error: ‘struct statement’ has no member named ‘desc’ Task: The win32 Wine build failed === debian11b (build log) === ../wine/dlls/odbc32/proxyodbc.c:532:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:532:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:534:17: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:534:49: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:541:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:541:36: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:543:19: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:3005:43: error: ‘struct statement’ has no member named ‘desc’ ../wine/dlls/odbc32/proxyodbc.c:6325:43: error: ‘struct statement’ has no member named ‘desc’ Task: The wow64 Wine build failed
participants (3)
-
Hans Leidekker -
Hans Leidekker (@hans) -
Marvin