mirror of
https://github.com/reactos/wine.git
synced 2024-11-30 07:00:30 +00:00
msi: Implement proper sorting in WHEREVIEW.
This commit is contained in:
parent
abd1174941
commit
f0a53a8f1b
120
dlls/msi/where.c
120
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);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
count++;
|
||||
column = column->next;
|
||||
}
|
||||
while ((table = table->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)
|
||||
goto error;
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user