Bernhard Loos : msi: Implement proper sorting in WHEREVIEW.
Alexandre Julliard
julliard at winehq.org
Fri Aug 26 10:40:54 CDT 2011
Module: wine
Branch: master
Commit: f0a53a8f1bde9b8f1be096160f9664415835e29b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f0a53a8f1bde9b8f1be096160f9664415835e29b
Author: Bernhard Loos <bernhardloos at googlemail.com>
Date: Fri Aug 26 04:53:44 2011 +0200
msi: Implement proper sorting in WHEREVIEW.
---
dlls/msi/where.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 106 insertions(+), 12 deletions(-)
diff --git a/dlls/msi/where.c b/dlls/msi/where.c
index 0742244..16b6c03 100644
--- a/dlls/msi/where.c
+++ b/dlls/msi/where.c
@@ -38,9 +38,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
/* below is the query interface to a table */
-
typedef struct tagMSIROWENTRY
{
+ struct tagMSIWHEREVIEW *wv; /* used during sorting */
UINT values[1];
} MSIROWENTRY;
@@ -53,6 +53,13 @@ typedef struct tagJOINTABLE
UINT table_index;
} JOINTABLE;
+typedef struct tagMSIORDERINFO
+{
+ UINT col_count;
+ UINT error;
+ union ext_column columns[1];
+} MSIORDERINFO;
+
typedef struct tagMSIWHEREVIEW
{
MSIVIEW view;
@@ -65,6 +72,7 @@ typedef struct tagMSIWHEREVIEW
UINT reorder_size; /* number of entries available in reorder */
struct expr *cond;
UINT rec_index;
+ MSIORDERINFO *order_info;
} MSIWHEREVIEW;
#define INITIAL_REORDER_SIZE 16
@@ -136,6 +144,7 @@ static UINT add_row(MSIWHEREVIEW *wv, UINT vals[])
wv->reorder[wv->row_count++] = new;
memcpy(new->values, vals, wv->table_count * sizeof(UINT));
+ new->wv = wv;
return ERROR_SUCCESS;
}
@@ -549,6 +558,53 @@ static UINT check_condition( MSIWHEREVIEW *wv, MSIRECORD *record, JOINTABLE *tab
return r;
}
+static int compare_entry( const void *left, const void *right )
+{
+ const MSIROWENTRY *le = *(const MSIROWENTRY**)left;
+ const MSIROWENTRY *re = *(const MSIROWENTRY**)right;
+ const MSIWHEREVIEW *wv = le->wv;
+ MSIORDERINFO *order = wv->order_info;
+ UINT i, j, r, l_val, r_val;
+
+ assert(le->wv == re->wv);
+
+ if (order)
+ {
+ for (i = 0; i < order->col_count; i++)
+ {
+ const union ext_column *column = &order->columns[i];
+
+ r = column->parsed.table->view->ops->fetch_int(column->parsed.table->view,
+ le->values[column->parsed.table->table_index],
+ column->parsed.column, &l_val);
+ if (r != ERROR_SUCCESS)
+ {
+ order->error = r;
+ return 0;
+ }
+
+ r = column->parsed.table->view->ops->fetch_int(column->parsed.table->view,
+ re->values[column->parsed.table->table_index],
+ column->parsed.column, &r_val);
+ if (r != ERROR_SUCCESS)
+ {
+ order->error = r;
+ return 0;
+ }
+
+ if (l_val != r_val)
+ return l_val < r_val ? -1 : 1;
+ }
+ }
+
+ for (j = 0; j < wv->table_count; j++)
+ {
+ if (le->values[j] != re->values[j])
+ return le->values[j] < re->values[j] ? -1 : 1;
+ }
+ return 0;
+}
+
static UINT WHERE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
@@ -583,6 +639,15 @@ static UINT WHERE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
while ((table = table->next));
r = check_condition(wv, record, wv->tables, rows);
+
+ if (wv->order_info)
+ wv->order_info->error = ERROR_SUCCESS;
+
+ qsort(wv->reorder, wv->row_count, sizeof(MSIROWENTRY *), compare_entry);
+
+ if (wv->order_info)
+ r = wv->order_info->error;
+
return r;
}
@@ -773,6 +838,12 @@ static UINT WHERE_delete( struct tagMSIVIEW *view )
free_reorder(wv);
+ if (wv->order_info)
+ {
+ msi_free(wv->order_info);
+ wv->order_info = NULL;
+ }
+
msiobj_release( &wv->db->hdr );
msi_free( wv );
@@ -813,22 +884,49 @@ static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns)
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
JOINTABLE *table = wv->tables;
- UINT r;
+ column_info *column = columns;
+ MSIORDERINFO *orderinfo;
+ UINT r, count = 0;
+ int i;
TRACE("%p %p\n", view, columns);
if (!table)
return ERROR_FUNCTION_FAILED;
- do
+ while (column)
{
- r = table->view->ops->sort(table->view, columns);
+ count++;
+ column = column->next;
+ }
+
+ if (count == 0)
+ return ERROR_SUCCESS;
+
+ orderinfo = msi_alloc(sizeof(MSIORDERINFO) + (count - 1) * sizeof(union ext_column));
+ if (!orderinfo)
+ return ERROR_OUTOFMEMORY;
+
+ orderinfo->col_count = count;
+
+ column = columns;
+
+ for (i = 0; i < count; i++)
+ {
+ orderinfo->columns[i].unparsed.column = column->column;
+ orderinfo->columns[i].unparsed.table = column->table;
+
+ r = parse_column(wv, &orderinfo->columns[i], NULL);
if (r != ERROR_SUCCESS)
- return r;
+ goto error;
}
- while ((table = table->next));
+
+ wv->order_info = orderinfo;
return ERROR_SUCCESS;
+error:
+ msi_free(orderinfo);
+ return r;
}
static const MSIVIEWOPS where_ops =
@@ -949,7 +1047,6 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables,
MSIWHEREVIEW *wv = NULL;
UINT r, valid = 0;
WCHAR *ptr;
- JOINTABLE **lastnext;
TRACE("(%s)\n", debugstr_w(tables) );
@@ -963,8 +1060,6 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables,
wv->db = db;
wv->cond = cond;
- lastnext = &wv->tables;
-
while (*tables)
{
JOINTABLE *table;
@@ -998,10 +1093,9 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables,
wv->col_count += table->col_count;
table->table_index = wv->table_count++;
- table->next = NULL;
- *lastnext = table;
- lastnext = &table->next;
+ table->next = wv->tables;
+ wv->tables = table;
if (!ptr)
break;
More information about the wine-cvs
mailing list