From 91c205e8c0332a1260f58a94fc1a216be2da8c56 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Mon, 17 Dec 2007 19:35:31 -0600 Subject: [PATCH] msi: Sort each table of the join separately. --- dlls/msi/Makefile.in | 1 - dlls/msi/alter.c | 1 + dlls/msi/create.c | 1 + dlls/msi/distinct.c | 9 ++ dlls/msi/insert.c | 1 + dlls/msi/join.c | 19 +++ dlls/msi/msipriv.h | 15 ++ dlls/msi/order.c | 376 ------------------------------------------- dlls/msi/query.h | 10 -- dlls/msi/select.c | 9 ++ dlls/msi/sql.y | 15 +- dlls/msi/streams.c | 1 + dlls/msi/table.c | 170 +++++++++++++++++++ dlls/msi/tests/db.c | 75 ++------- dlls/msi/where.c | 9 ++ 15 files changed, 258 insertions(+), 454 deletions(-) delete mode 100644 dlls/msi/order.c diff --git a/dlls/msi/Makefile.in b/dlls/msi/Makefile.in index 3a9ab1d93f0..91029241db4 100644 --- a/dlls/msi/Makefile.in +++ b/dlls/msi/Makefile.in @@ -32,7 +32,6 @@ C_SRCS = \ msi.c \ msi_main.c \ msiquery.c \ - order.c \ package.c \ preview.c \ record.c \ diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c index f7a2d7e6b87..892ad350c1d 100644 --- a/dlls/msi/alter.c +++ b/dlls/msi/alter.c @@ -241,6 +241,7 @@ static const MSIVIEWOPS alter_ops = NULL, NULL, NULL, + NULL, }; UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, column_info *colinfo, int hold ) diff --git a/dlls/msi/create.c b/dlls/msi/create.c index ae9f69c68f6..ed8713cf21a 100644 --- a/dlls/msi/create.c +++ b/dlls/msi/create.c @@ -136,6 +136,7 @@ static const MSIVIEWOPS create_ops = NULL, NULL, NULL, + NULL, }; static UINT check_columns( column_info *col_info ) diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c index 2fe5eff54bc..6a29c5a986c 100644 --- a/dlls/msi/distinct.c +++ b/dlls/msi/distinct.c @@ -267,6 +267,14 @@ static UINT DISTINCT_find_matching_rows( struct tagMSIVIEW *view, UINT col, return r; } +static UINT DISTINCT_sort(struct tagMSIVIEW *view, column_info *columns) +{ + MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW *)view; + + TRACE("%p %p\n", view, columns); + + return dv->table->ops->sort( dv->table, columns ); +} static const MSIVIEWOPS distinct_ops = { @@ -287,6 +295,7 @@ static const MSIVIEWOPS distinct_ops = NULL, NULL, NULL, + DISTINCT_sort, }; UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c index 206c3d70238..55ac2340582 100644 --- a/dlls/msi/insert.c +++ b/dlls/msi/insert.c @@ -238,6 +238,7 @@ static const MSIVIEWOPS insert_ops = NULL, NULL, NULL, + NULL, }; static UINT count_column_info( const column_info *ci ) diff --git a/dlls/msi/join.c b/dlls/msi/join.c index 325f58e36f0..7d25217d6c9 100644 --- a/dlls/msi/join.c +++ b/dlls/msi/join.c @@ -268,6 +268,24 @@ static UINT JOIN_find_matching_rows( struct tagMSIVIEW *view, UINT col, return ERROR_NO_MORE_ITEMS; } +static UINT JOIN_sort(struct tagMSIVIEW *view, column_info *columns) +{ + MSIJOINVIEW *jv = (MSIJOINVIEW *)view; + JOINTABLE *table; + UINT r; + + TRACE("%p %p\n", view, columns); + + LIST_FOR_EACH_ENTRY(table, &jv->tables, JOINTABLE, entry) + { + r = table->view->ops->sort(table->view, columns); + if (r != ERROR_SUCCESS) + return r; + } + + return ERROR_SUCCESS; +} + static const MSIVIEWOPS join_ops = { JOIN_fetch_int, @@ -287,6 +305,7 @@ static const MSIVIEWOPS join_ops = NULL, NULL, NULL, + JOIN_sort, }; UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables ) diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index d5412608a65..b8362461930 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -133,6 +133,16 @@ typedef struct tagMSIMEDIADISK LPWSTR disk_prompt; } MSIMEDIADISK; +typedef struct _column_info +{ + LPCWSTR table; + LPCWSTR column; + INT type; + BOOL temporary; + struct expr *val; + struct _column_info *next; +} column_info; + typedef const struct tagMSICOLUMNHASHENTRY *MSIITERHANDLE; typedef struct tagMSIVIEWOPS @@ -248,6 +258,11 @@ typedef struct tagMSIVIEWOPS * remove_column - removes the column represented by table name and column number from the table */ UINT (*remove_column)( struct tagMSIVIEW *view, LPCWSTR table, UINT number ); + + /* + * sort - orders the table by columns + */ + UINT (*sort)( struct tagMSIVIEW *view, column_info *columns ); } MSIVIEWOPS; struct tagMSIVIEW diff --git a/dlls/msi/order.c b/dlls/msi/order.c deleted file mode 100644 index e895d593b90..00000000000 --- a/dlls/msi/order.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2002 Mike McCormack for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "wine/debug.h" -#include "msi.h" -#include "msiquery.h" -#include "objbase.h" -#include "objidl.h" -#include "msipriv.h" -#include "winnls.h" - -#include "query.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msidb); - - -/* below is the query interface to a table */ - -typedef struct tagMSIORDERVIEW -{ - MSIVIEW view; - MSIDATABASE *db; - MSIVIEW *table; - UINT *reorder; - UINT num_cols; - UINT cols[1]; -} MSIORDERVIEW; - -static UINT ORDER_compare( MSIORDERVIEW *ov, UINT a, UINT b, UINT *swap ) -{ - UINT r, i, a_val = 0, b_val = 0; - - *swap = 0; - for( i=0; inum_cols; i++ ) - { - r = ov->table->ops->fetch_int( ov->table, a, ov->cols[i], &a_val ); - if( r != ERROR_SUCCESS ) - return r; - - r = ov->table->ops->fetch_int( ov->table, b, ov->cols[i], &b_val ); - if( r != ERROR_SUCCESS ) - return r; - - if( a_val != b_val ) - { - if( a_val > b_val ) - *swap = 1; - break; - } - } - - return ERROR_SUCCESS; -} - -static UINT ORDER_mergesort( MSIORDERVIEW *ov, UINT left, UINT right ) -{ - UINT r, centre = (left + right)/2, temp, swap = 0, i, j; - UINT *array = ov->reorder; - - if( left == right ) - return ERROR_SUCCESS; - - /* sort the left half */ - r = ORDER_mergesort( ov, left, centre ); - if( r != ERROR_SUCCESS ) - return r; - - /* sort the right half */ - r = ORDER_mergesort( ov, centre+1, right ); - if( r != ERROR_SUCCESS ) - return r; - - for( i=left, j=centre+1; (i<=centre) && (j<=right); i++ ) - { - r = ORDER_compare( ov, array[i], array[j], &swap ); - if( r != ERROR_SUCCESS ) - return r; - if( swap ) - { - temp = array[j]; - memmove( &array[i+1], &array[i], (j-i)*sizeof (UINT) ); - array[i] = temp; - j++; - centre++; - } - } - - return ERROR_SUCCESS; -} - -static UINT ORDER_verify( MSIORDERVIEW *ov, UINT num_rows ) -{ - UINT i, swap, r; - - for( i=1; ireorder[i-1], ov->reorder[i], &swap ); - if( r != ERROR_SUCCESS ) - return r; - if( !swap ) - continue; - ERR("Bad order! %d\n", i); - return ERROR_FUNCTION_FAILED; - } - - return ERROR_SUCCESS; -} - -static UINT ORDER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - - TRACE("%p %d %d %p\n", ov, row, col, val ); - - if( !ov->table ) - return ERROR_FUNCTION_FAILED; - - row = ov->reorder[ row ]; - - return ov->table->ops->fetch_int( ov->table, row, col, val ); -} - -static UINT ORDER_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW *)view; - - TRACE("%p %d %p\n", ov, row, rec ); - - if (!ov->table) - return ERROR_FUNCTION_FAILED; - - row = ov->reorder[row]; - - return ov->table->ops->get_row(ov->table, row, rec); -} - -static UINT ORDER_execute( struct tagMSIVIEW *view, MSIRECORD *record ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - UINT r, num_rows = 0, i; - - TRACE("%p %p\n", ov, record); - - if( !ov->table ) - return ERROR_FUNCTION_FAILED; - - r = ov->table->ops->execute( ov->table, record ); - if( r != ERROR_SUCCESS ) - return r; - - r = ov->table->ops->get_dimensions( ov->table, &num_rows, NULL ); - if( r != ERROR_SUCCESS ) - return r; - - ov->reorder = msi_alloc( num_rows*sizeof(UINT) ); - if( !ov->reorder ) - return ERROR_FUNCTION_FAILED; - - for( i=0; ireorder[i] = i; - - r = ORDER_mergesort( ov, 0, num_rows - 1 ); - if( r != ERROR_SUCCESS ) - return r; - - r = ORDER_verify( ov, num_rows ); - if( r != ERROR_SUCCESS ) - return r; - - return ERROR_SUCCESS; -} - -static UINT ORDER_close( struct tagMSIVIEW *view ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - - TRACE("%p\n", ov ); - - if( !ov->table ) - return ERROR_FUNCTION_FAILED; - - msi_free( ov->reorder ); - ov->reorder = NULL; - - return ov->table->ops->close( ov->table ); -} - -static UINT ORDER_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - - TRACE("%p %p %p\n", ov, rows, cols ); - - if( !ov->table ) - return ERROR_FUNCTION_FAILED; - - return ov->table->ops->get_dimensions( ov->table, rows, cols ); -} - -static UINT ORDER_get_column_info( struct tagMSIVIEW *view, - UINT n, LPWSTR *name, UINT *type ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - - TRACE("%p %d %p %p\n", ov, n, name, type ); - - if( !ov->table ) - return ERROR_FUNCTION_FAILED; - - return ov->table->ops->get_column_info( ov->table, n, name, type ); -} - -static UINT ORDER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, - MSIRECORD *rec, UINT row ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - - TRACE("%p %d %p\n", ov, eModifyMode, rec ); - - if( !ov->table ) - return ERROR_FUNCTION_FAILED; - - return ov->table->ops->modify( ov->table, eModifyMode, rec, row ); -} - -static UINT ORDER_delete( struct tagMSIVIEW *view ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - - TRACE("%p\n", ov ); - - if( ov->table ) - ov->table->ops->delete( ov->table ); - - msi_free( ov->reorder ); - ov->reorder = NULL; - - msiobj_release( &ov->db->hdr ); - msi_free( ov ); - - return ERROR_SUCCESS; -} - -static UINT ORDER_find_matching_rows( struct tagMSIVIEW *view, UINT col, - UINT val, UINT *row, MSIITERHANDLE *handle ) -{ - MSIORDERVIEW *ov = (MSIORDERVIEW*)view; - UINT r; - - TRACE("%p, %d, %u, %p\n", ov, col, val, *handle); - - if( !ov->table ) - return ERROR_FUNCTION_FAILED; - - r = ov->table->ops->find_matching_rows( ov->table, col, val, row, handle ); - - *row = ov->reorder[ *row ]; - - return r; -} - - -static const MSIVIEWOPS order_ops = -{ - ORDER_fetch_int, - NULL, - ORDER_get_row, - NULL, - NULL, - NULL, - ORDER_execute, - ORDER_close, - ORDER_get_dimensions, - ORDER_get_column_info, - ORDER_modify, - ORDER_delete, - ORDER_find_matching_rows, - NULL, - NULL, - NULL, - NULL, -}; - -static UINT ORDER_AddColumn( MSIORDERVIEW *ov, LPCWSTR name ) -{ - UINT n, count, r; - MSIVIEW *table; - - TRACE("%p adding %s\n", ov, debugstr_w( name ) ); - - if( ov->view.ops != &order_ops ) - return ERROR_FUNCTION_FAILED; - - table = ov->table; - if( !table ) - return ERROR_FUNCTION_FAILED; - if( !table->ops->get_dimensions ) - return ERROR_FUNCTION_FAILED; - if( !table->ops->get_column_info ) - return ERROR_FUNCTION_FAILED; - - r = table->ops->get_dimensions( table, NULL, &count ); - if( r != ERROR_SUCCESS ) - return r; - - if( ov->num_cols >= count ) - return ERROR_FUNCTION_FAILED; - - r = VIEW_find_column( table, name, &n ); - if( r != ERROR_SUCCESS ) - return r; - - ov->cols[ov->num_cols] = n; - TRACE("Ordering by column %s (%d)\n", debugstr_w( name ), n); - - ov->num_cols++; - - return ERROR_SUCCESS; -} - -UINT ORDER_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table, - column_info *columns ) -{ - MSIORDERVIEW *ov = NULL; - UINT count = 0, r; - column_info *x; - - TRACE("%p\n", ov ); - - r = table->ops->get_dimensions( table, NULL, &count ); - if( r != ERROR_SUCCESS ) - { - ERR("can't get table dimensions\n"); - return r; - } - - ov = msi_alloc_zero( sizeof *ov + sizeof (UINT) * count ); - if( !ov ) - return ERROR_FUNCTION_FAILED; - - /* fill the structure */ - ov->view.ops = &order_ops; - msiobj_addref( &db->hdr ); - ov->db = db; - ov->table = table; - ov->reorder = NULL; - ov->num_cols = 0; - *view = (MSIVIEW*) ov; - - for( x = columns; x ; x = x->next ) - ORDER_AddColumn( ov, x->column ); - - return ERROR_SUCCESS; -} diff --git a/dlls/msi/query.h b/dlls/msi/query.h index 4cf47c7a657..73ed502e81f 100644 --- a/dlls/msi/query.h +++ b/dlls/msi/query.h @@ -61,16 +61,6 @@ struct sql_str { INT len; }; -typedef struct _column_info -{ - LPCWSTR table; - LPCWSTR column; - UINT type; - BOOL temporary; - struct expr *val; - struct _column_info *next; -} column_info; - struct complex_expr { UINT op; diff --git a/dlls/msi/select.c b/dlls/msi/select.c index 9c5232ac1fb..070bbfa8bcf 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -334,6 +334,14 @@ static UINT SELECT_find_matching_rows( struct tagMSIVIEW *view, UINT col, return sv->table->ops->find_matching_rows( sv->table, col, val, row, handle ); } +static UINT SELECT_sort(struct tagMSIVIEW *view, column_info *columns) +{ + MSISELECTVIEW *sv = (MSISELECTVIEW *)view; + + TRACE("%p %p\n", view, columns); + + return sv->table->ops->sort( sv->table, columns ); +} static const MSIVIEWOPS select_ops = { @@ -354,6 +362,7 @@ static const MSIVIEWOPS select_ops = NULL, NULL, NULL, + SELECT_sort, }; static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name ) diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y index 59a67b50f4d..94c36cdb8a5 100644 --- a/dlls/msi/sql.y +++ b/dlls/msi/sql.y @@ -373,15 +373,16 @@ data_count: oneselect: unorderedsel TK_ORDER TK_BY selcollist { - SQL_input* sql = (SQL_input*) info; + UINT r; - $$ = NULL; if( $4 ) - ORDER_CreateView( sql->db, &$$, $1, $4 ); - else - $$ = $1; - if( !$$ ) - YYABORT; + { + r = $1->ops->sort( $1, $4 ); + if ( r != ERROR_SUCCESS) + YYABORT; + } + + $$ = $1; } | unorderedsel ; diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index a4c0a529b53..bb86fd0e84c 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -379,6 +379,7 @@ static const MSIVIEWOPS streams_ops = NULL, NULL, NULL, + NULL, }; static UINT add_streams_to_table(MSISTREAMSVIEW *sv) diff --git a/dlls/msi/table.c b/dlls/msi/table.c index c02b1f2325b..7f6f8ef1ea3 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -62,6 +62,13 @@ typedef struct tagMSICOLUMNINFO MSICOLUMNHASHENTRY **hash_table; } MSICOLUMNINFO; +typedef struct tagMSIORDERINFO +{ + UINT *reorder; + UINT num_cols; + UINT cols[1]; +} MSIORDERINFO; + struct tagMSITABLE { BYTE **data; @@ -1114,6 +1121,7 @@ typedef struct tagMSITABLEVIEW MSIDATABASE *db; MSITABLE *table; MSICOLUMNINFO *columns; + MSIORDERINFO *order; UINT num_cols; UINT row_size; WCHAR name[1]; @@ -1142,6 +1150,9 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT * return ERROR_FUNCTION_FAILED; } + if (tv->order) + row = tv->order->reorder[row]; + if (row >= tv->table->row_count) { row -= tv->table->row_count; @@ -1286,6 +1297,9 @@ static UINT TABLE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec ) if (!tv->table) return ERROR_INVALID_PARAMETER; + if (tv->order) + row = tv->order->reorder[row]; + return msi_view_get_row(tv->db, view, row, rec); } @@ -1728,6 +1742,10 @@ static UINT TABLE_find_matching_rows( struct tagMSIVIEW *view, UINT col, return ERROR_NO_MORE_ITEMS; *row = entry->row; + + if (tv->order) + *row = tv->order->reorder[*row]; + return ERROR_SUCCESS; } @@ -1860,6 +1878,157 @@ done: return r; } +static UINT order_add_column(struct tagMSIVIEW *view, MSIORDERINFO *order, LPCWSTR name) +{ + UINT n, r, count; + + r = TABLE_get_dimensions(view, NULL, &count); + if (r != ERROR_SUCCESS) + return r; + + if (order->num_cols >= count) + return ERROR_FUNCTION_FAILED; + + r = VIEW_find_column(view, name, &n); + if (r != ERROR_SUCCESS) + return r; + + order->cols[order->num_cols] = n; + TRACE("Ordering by column %s (%d)\n", debugstr_w(name), n); + + order->num_cols++; + + return ERROR_SUCCESS; +} + +static UINT order_compare(struct tagMSIVIEW *view, MSIORDERINFO *order, + UINT a, UINT b, UINT *swap) +{ + UINT r, i, a_val = 0, b_val = 0; + + *swap = 0; + for (i = 0; i < order->num_cols; i++) + { + r = TABLE_fetch_int(view, a, order->cols[i], &a_val); + if (r != ERROR_SUCCESS) + return r; + + r = TABLE_fetch_int(view, b, order->cols[i], &b_val); + if (r != ERROR_SUCCESS) + return r; + + if (a_val != b_val) + { + if (a_val > b_val) + *swap = 1; + break; + } + } + + return ERROR_SUCCESS; +} + +static UINT order_mergesort(struct tagMSIVIEW *view, MSIORDERINFO *order, + UINT left, UINT right) +{ + UINT r, i, j, temp; + UINT swap = 0, center = (left + right) / 2; + UINT *array = order->reorder; + + if (left == right) + return ERROR_SUCCESS; + + /* sort the left half */ + r = order_mergesort(view, order, left, center); + if (r != ERROR_SUCCESS) + return r; + + /* sort the right half */ + r = order_mergesort(view, order, center + 1, right); + if (r != ERROR_SUCCESS) + return r; + + for (i = left, j = center + 1; (i <= center) && (j <= right); i++) + { + r = order_compare(view, order, array[i], array[j], &swap); + if (r != ERROR_SUCCESS) + return r; + + if (swap) + { + temp = array[j]; + memmove(&array[i + 1], &array[i], (j - i) * sizeof(UINT)); + array[i] = temp; + j++; + center++; + } + } + + return ERROR_SUCCESS; +} + +static UINT order_verify(struct tagMSIVIEW *view, MSIORDERINFO *order, UINT num_rows) +{ + UINT i, swap, r; + + for (i = 1; i < num_rows; i++) + { + r = order_compare(view, order, order->reorder[i - 1], + order->reorder[i], &swap); + if (r != ERROR_SUCCESS) + return r; + + if (!swap) + continue; + + ERR("Bad order! %d\n", i); + return ERROR_FUNCTION_FAILED; + } + + return ERROR_SUCCESS; +} + +static UINT TABLE_sort(struct tagMSIVIEW *view, column_info *columns) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW *)view; + MSIORDERINFO *order; + column_info *ptr; + UINT r, i; + UINT rows, cols; + + TRACE("sorting table %s\n", debugstr_w(tv->name)); + + r = TABLE_get_dimensions(view, &rows, &cols); + if (r != ERROR_SUCCESS) + return r; + + order = msi_alloc_zero(sizeof(MSIORDERINFO) + sizeof(UINT) * cols); + if (!order) + return ERROR_OUTOFMEMORY; + + for (ptr = columns; ptr; ptr = ptr->next) + order_add_column(view, order, ptr->column); + + order->reorder = msi_alloc(rows * sizeof(UINT)); + if (!order->reorder) + return ERROR_OUTOFMEMORY; + + for (i = 0; i < rows; i++) + order->reorder[i] = i; + + r = order_mergesort(view, order, 0, rows - 1); + if (r != ERROR_SUCCESS) + return r; + + r = order_verify(view, order, rows); + if (r != ERROR_SUCCESS) + return r; + + tv->order = order; + + return ERROR_SUCCESS; +} + static const MSIVIEWOPS table_ops = { TABLE_fetch_int, @@ -1879,6 +2048,7 @@ static const MSIVIEWOPS table_ops = TABLE_release, TABLE_add_column, TABLE_remove_column, + TABLE_sort, }; UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view ) diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 125b08c1c07..05a9aa96e32 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -4610,16 +4610,10 @@ static void test_order(void) ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); val = MsiRecordGetInteger(hrec, 1); - todo_wine - { - ok(val == 3, "Expected 3, got %d\n", val); - } + ok(val == 3, "Expected 3, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 4, "Expected 3, got %d\n", val); - } + ok(val == 4, "Expected 3, got %d\n", val); MsiCloseHandle(hrec); @@ -4627,16 +4621,10 @@ static void test_order(void) ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); val = MsiRecordGetInteger(hrec, 1); - todo_wine - { - ok(val == 5, "Expected 5, got %d\n", val); - } + ok(val == 5, "Expected 5, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 6, "Expected 6, got %d\n", val); - } + ok(val == 6, "Expected 6, got %d\n", val); MsiCloseHandle(hrec); @@ -4644,16 +4632,10 @@ static void test_order(void) ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); val = MsiRecordGetInteger(hrec, 1); - todo_wine - { - ok(val == 1, "Expected 1, got %d\n", val); - } + ok(val == 1, "Expected 1, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 2, "Expected 2, got %d\n", val); - } + ok(val == 2, "Expected 2, got %d\n", val); MsiCloseHandle(hrec); @@ -4673,10 +4655,7 @@ static void test_order(void) ok(val == 1, "Expected 1, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 12, "Expected 12, got %d\n", val); - } + ok(val == 12, "Expected 12, got %d\n", val); MsiCloseHandle(hrec); @@ -4687,10 +4666,7 @@ static void test_order(void) ok(val == 3, "Expected 3, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 12, "Expected 12, got %d\n", val); - } + ok(val == 12, "Expected 12, got %d\n", val); MsiCloseHandle(hrec); @@ -4701,10 +4677,7 @@ static void test_order(void) ok(val == 5, "Expected 5, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 12, "Expected 12, got %d\n", val); - } + ok(val == 12, "Expected 12, got %d\n", val); MsiCloseHandle(hrec); @@ -4715,10 +4688,7 @@ static void test_order(void) ok(val == 1, "Expected 1, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 14, "Expected 14, got %d\n", val); - } + ok(val == 14, "Expected 14, got %d\n", val); MsiCloseHandle(hrec); @@ -4729,10 +4699,7 @@ static void test_order(void) ok(val == 3, "Expected 3, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 14, "Expected 14, got %d\n", val); - } + ok(val == 14, "Expected 14, got %d\n", val); MsiCloseHandle(hrec); @@ -4743,10 +4710,7 @@ static void test_order(void) ok(val == 5, "Expected 5, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 14, "Expected 14, got %d\n", val); - } + ok(val == 14, "Expected 14, got %d\n", val); MsiCloseHandle(hrec); @@ -4757,10 +4721,7 @@ static void test_order(void) ok(val == 1, "Expected 1, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 10, "Expected 10, got %d\n", val); - } + ok(val == 10, "Expected 10, got %d\n", val); MsiCloseHandle(hrec); @@ -4771,10 +4732,7 @@ static void test_order(void) ok(val == 3, "Expected 3, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 10, "Expected 10, got %d\n", val); - } + ok(val == 10, "Expected 10, got %d\n", val); MsiCloseHandle(hrec); @@ -4785,10 +4743,7 @@ static void test_order(void) ok(val == 5, "Expected 5, got %d\n", val); val = MsiRecordGetInteger(hrec, 2); - todo_wine - { - ok(val == 10, "Expected 10, got %d\n", val); - } + ok(val == 10, "Expected 10, got %d\n", val); MsiCloseHandle(hrec); diff --git a/dlls/msi/where.c b/dlls/msi/where.c index 4029a7f6754..258cb32296a 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -532,6 +532,14 @@ static UINT WHERE_find_matching_rows( struct tagMSIVIEW *view, UINT col, return find_entry_in_hash(wv->reorder, *row, row); } +static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns) +{ + MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view; + + TRACE("%p %p\n", view, columns); + + return wv->table->ops->sort(wv->table, columns); +} static const MSIVIEWOPS where_ops = { @@ -552,6 +560,7 @@ static const MSIVIEWOPS where_ops = NULL, NULL, NULL, + WHERE_sort, }; static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond,