msi: Always use WHEREVIEW for sorting.

This commit is contained in:
Bernhard Loos 2011-10-20 14:22:25 +02:00 committed by Alexandre Julliard
parent 0fd4943277
commit 4ac1e8e034
4 changed files with 45 additions and 245 deletions

View file

@ -268,15 +268,6 @@ 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 =
{
DISTINCT_fetch_int,
@ -296,7 +287,7 @@ static const MSIVIEWOPS distinct_ops =
NULL,
NULL,
NULL,
DISTINCT_sort,
NULL,
NULL,
};

View file

@ -333,14 +333,6 @@ 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 =
{
@ -361,7 +353,7 @@ static const MSIVIEWOPS select_ops =
NULL,
NULL,
NULL,
SELECT_sort,
NULL,
NULL,
};

View file

@ -114,7 +114,7 @@ static struct expr * EXPR_wildcard( void *info );
%type <string> table tablelist id
%type <column_list> selcollist column column_and_type column_def table_def
%type <column_list> column_assignment update_assign_list constlist
%type <query> query from fromtable selectfrom unorderedsel
%type <query> query from selectfrom unorderdfrom
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter onedrop
%type <expr> expr val column_val const_val
%type <column_type> column_type data_type data_type_l data_count
@ -409,23 +409,6 @@ data_count:
;
oneselect:
unorderedsel TK_ORDER TK_BY selcollist
{
UINT r;
if( $4 )
{
r = $1->ops->sort( $1, $4 );
if ( r != ERROR_SUCCESS)
YYABORT;
}
$$ = $1;
}
| unorderedsel
;
unorderedsel:
TK_SELECT selectfrom
{
$$ = $2;
@ -477,34 +460,6 @@ selcollist:
;
from:
fromtable
| TK_FROM tablelist TK_WHERE expr
{
SQL_input* sql = (SQL_input*) info;
MSIVIEW* where = NULL;
UINT r;
r = WHERE_CreateView( sql->db, &where, $2, $4 );
if( r != ERROR_SUCCESS )
YYABORT;
PARSER_BUBBLE_UP_VIEW( sql, $$, where );
}
| TK_FROM tablelist
{
SQL_input* sql = (SQL_input*) info;
MSIVIEW* where = NULL;
UINT r;
r = WHERE_CreateView( sql->db, &where, $2, NULL );
if( r != ERROR_SUCCESS )
YYABORT;
PARSER_BUBBLE_UP_VIEW( sql, $$, where );
}
;
fromtable:
TK_FROM table
{
SQL_input* sql = (SQL_input*) info;
@ -517,6 +472,47 @@ fromtable:
PARSER_BUBBLE_UP_VIEW( sql, $$, table );
}
| unorderdfrom TK_ORDER TK_BY selcollist
{
UINT r;
if( $4 )
{
r = $1->ops->sort( $1, $4 );
if ( r != ERROR_SUCCESS)
YYABORT;
}
$$ = $1;
}
| unorderdfrom
;
unorderdfrom:
TK_FROM tablelist
{
SQL_input* sql = (SQL_input*) info;
MSIVIEW* where = NULL;
UINT r;
r = WHERE_CreateView( sql->db, &where, $2, NULL );
if( r != ERROR_SUCCESS )
YYABORT;
PARSER_BUBBLE_UP_VIEW( sql, $$, where );
}
| TK_FROM tablelist TK_WHERE expr
{
SQL_input* sql = (SQL_input*) info;
MSIVIEW* where = NULL;
UINT r;
r = WHERE_CreateView( sql->db, &where, $2, $4 );
if( r != ERROR_SUCCESS )
YYABORT;
PARSER_BUBBLE_UP_VIEW( sql, $$, where );
}
;
tablelist:

View file

@ -62,13 +62,6 @@ typedef struct tagMSICOLUMNINFO
MSICOLUMNHASHENTRY **hash_table;
} MSICOLUMNINFO;
typedef struct tagMSIORDERINFO
{
UINT *reorder;
UINT num_cols;
UINT cols[1];
} MSIORDERINFO;
struct tagMSITABLE
{
BYTE **data;
@ -1019,7 +1012,6 @@ typedef struct tagMSITABLEVIEW
MSIDATABASE *db;
MSITABLE *table;
MSICOLUMNINFO *columns;
MSIORDERINFO *order;
UINT num_cols;
UINT row_size;
WCHAR name[1];
@ -1047,9 +1039,6 @@ 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];
n = bytes_per_column( tv->db, &tv->columns[col - 1], LONG_STR_BYTES );
if (n != 2 && n != 3 && n != 4)
{
@ -1226,9 +1215,6 @@ 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);
}
@ -1726,9 +1712,6 @@ static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
if (row != new_row + 1)
return ERROR_FUNCTION_FAILED;
if(tv->order)
new_row = tv->order->reorder[new_row];
return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1);
}
@ -1853,13 +1836,6 @@ static UINT TABLE_delete( struct tagMSIVIEW *view )
tv->table = NULL;
tv->columns = NULL;
if (tv->order)
{
msi_free( tv->order->reorder );
msi_free( tv->order );
tv->order = NULL;
}
msi_free( tv );
return ERROR_SUCCESS;
@ -2072,161 +2048,6 @@ done:
return r;
}
static UINT order_add_column(struct tagMSIVIEW *view, MSIORDERINFO *order, LPCWSTR name)
{
UINT n, r, count;
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
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, tv->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;
if (rows == 0)
return ERROR_SUCCESS;
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 UINT TABLE_drop(struct tagMSIVIEW *view)
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
@ -2292,7 +2113,7 @@ static const MSIVIEWOPS table_ops =
TABLE_release,
TABLE_add_column,
TABLE_remove_column,
TABLE_sort,
NULL,
TABLE_drop,
};