msi: Always use WHEREVIEW for sorting.
This commit is contained in:
parent
0fd4943277
commit
4ac1e8e034
|
@ -268,15 +268,6 @@ static UINT DISTINCT_find_matching_rows( struct tagMSIVIEW *view, UINT col,
|
||||||
return r;
|
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 =
|
static const MSIVIEWOPS distinct_ops =
|
||||||
{
|
{
|
||||||
DISTINCT_fetch_int,
|
DISTINCT_fetch_int,
|
||||||
|
@ -296,7 +287,7 @@ static const MSIVIEWOPS distinct_ops =
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
DISTINCT_sort,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
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 =
|
static const MSIVIEWOPS select_ops =
|
||||||
{
|
{
|
||||||
|
@ -361,7 +353,7 @@ static const MSIVIEWOPS select_ops =
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
SELECT_sort,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ static struct expr * EXPR_wildcard( void *info );
|
||||||
%type <string> table tablelist id
|
%type <string> table tablelist id
|
||||||
%type <column_list> selcollist column column_and_type column_def table_def
|
%type <column_list> selcollist column column_and_type column_def table_def
|
||||||
%type <column_list> column_assignment update_assign_list constlist
|
%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 <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter onedrop
|
||||||
%type <expr> expr val column_val const_val
|
%type <expr> expr val column_val const_val
|
||||||
%type <column_type> column_type data_type data_type_l data_count
|
%type <column_type> column_type data_type data_type_l data_count
|
||||||
|
@ -409,23 +409,6 @@ data_count:
|
||||||
;
|
;
|
||||||
|
|
||||||
oneselect:
|
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
|
TK_SELECT selectfrom
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
|
@ -477,34 +460,6 @@ selcollist:
|
||||||
;
|
;
|
||||||
|
|
||||||
from:
|
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
|
TK_FROM table
|
||||||
{
|
{
|
||||||
SQL_input* sql = (SQL_input*) info;
|
SQL_input* sql = (SQL_input*) info;
|
||||||
|
@ -517,6 +472,47 @@ fromtable:
|
||||||
|
|
||||||
PARSER_BUBBLE_UP_VIEW( sql, $$, table );
|
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:
|
tablelist:
|
||||||
|
|
181
dlls/msi/table.c
181
dlls/msi/table.c
|
@ -62,13 +62,6 @@ typedef struct tagMSICOLUMNINFO
|
||||||
MSICOLUMNHASHENTRY **hash_table;
|
MSICOLUMNHASHENTRY **hash_table;
|
||||||
} MSICOLUMNINFO;
|
} MSICOLUMNINFO;
|
||||||
|
|
||||||
typedef struct tagMSIORDERINFO
|
|
||||||
{
|
|
||||||
UINT *reorder;
|
|
||||||
UINT num_cols;
|
|
||||||
UINT cols[1];
|
|
||||||
} MSIORDERINFO;
|
|
||||||
|
|
||||||
struct tagMSITABLE
|
struct tagMSITABLE
|
||||||
{
|
{
|
||||||
BYTE **data;
|
BYTE **data;
|
||||||
|
@ -1019,7 +1012,6 @@ typedef struct tagMSITABLEVIEW
|
||||||
MSIDATABASE *db;
|
MSIDATABASE *db;
|
||||||
MSITABLE *table;
|
MSITABLE *table;
|
||||||
MSICOLUMNINFO *columns;
|
MSICOLUMNINFO *columns;
|
||||||
MSIORDERINFO *order;
|
|
||||||
UINT num_cols;
|
UINT num_cols;
|
||||||
UINT row_size;
|
UINT row_size;
|
||||||
WCHAR name[1];
|
WCHAR name[1];
|
||||||
|
@ -1047,9 +1039,6 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
|
||||||
return ERROR_FUNCTION_FAILED;
|
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 );
|
n = bytes_per_column( tv->db, &tv->columns[col - 1], LONG_STR_BYTES );
|
||||||
if (n != 2 && n != 3 && n != 4)
|
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)
|
if (!tv->table)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (tv->order)
|
|
||||||
row = tv->order->reorder[row];
|
|
||||||
|
|
||||||
return msi_view_get_row(tv->db, view, row, rec);
|
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)
|
if (row != new_row + 1)
|
||||||
return ERROR_FUNCTION_FAILED;
|
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);
|
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->table = NULL;
|
||||||
tv->columns = NULL;
|
tv->columns = NULL;
|
||||||
|
|
||||||
if (tv->order)
|
|
||||||
{
|
|
||||||
msi_free( tv->order->reorder );
|
|
||||||
msi_free( tv->order );
|
|
||||||
tv->order = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
msi_free( tv );
|
msi_free( tv );
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
@ -2072,161 +2048,6 @@ done:
|
||||||
return r;
|
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)
|
static UINT TABLE_drop(struct tagMSIVIEW *view)
|
||||||
{
|
{
|
||||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||||
|
@ -2292,7 +2113,7 @@ static const MSIVIEWOPS table_ops =
|
||||||
TABLE_release,
|
TABLE_release,
|
||||||
TABLE_add_column,
|
TABLE_add_column,
|
||||||
TABLE_remove_column,
|
TABLE_remove_column,
|
||||||
TABLE_sort,
|
NULL,
|
||||||
TABLE_drop,
|
TABLE_drop,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue