📄 where.c
字号:
value = 0;
else
{
r = msi_string2idW(wv->db->strings, val_cond->u.sval, &value);
if (r != ERROR_SUCCESS)
{
TRACE("no id for %s, assuming it doesn't exist in the table\n", debugstr_w(wv->cond->u.expr.right->u.sval));
return ERROR_SUCCESS;
}
}
do
{
r = table->ops->find_matching_rows(table, col, value, &row, &handle);
if (r == ERROR_SUCCESS)
wv->reorder[ wv->row_count ++ ] = row;
} while (r == ERROR_SUCCESS);
if (r == ERROR_NO_MORE_ITEMS)
return ERROR_SUCCESS;
else
return r;
}
/* else fallback to slow case */
}
for( i=0; i<count; i++ )
{
val = 0;
r = WHERE_evaluate( wv->db, table, i, wv->cond, &val, record );
if( r != ERROR_SUCCESS )
return r;
if( val )
wv->reorder[ wv->row_count ++ ] = i;
}
return ERROR_SUCCESS;
}
static UINT WHERE_close( struct tagMSIVIEW *view )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p\n", wv );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
msi_free( wv->reorder );
wv->reorder = NULL;
return wv->table->ops->close( wv->table );
}
static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %p %p\n", wv, rows, cols );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
if( rows )
{
if( !wv->reorder )
return ERROR_FUNCTION_FAILED;
*rows = wv->row_count;
}
return wv->table->ops->get_dimensions( wv->table, NULL, cols );
}
static UINT WHERE_get_column_info( struct tagMSIVIEW *view,
UINT n, LPWSTR *name, UINT *type )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %d %p %p\n", wv, n, name, type );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
return wv->table->ops->get_column_info( wv->table, n, name, type );
}
static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
MSIRECORD *rec )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %d %p\n", wv, eModifyMode, rec );
if( !wv->table )
return ERROR_FUNCTION_FAILED;
return wv->table->ops->modify( wv->table, eModifyMode, rec );
}
static UINT WHERE_delete( struct tagMSIVIEW *view )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p\n", wv );
if( wv->table )
wv->table->ops->delete( wv->table );
wv->table = 0;
msi_free( wv->reorder );
wv->reorder = NULL;
wv->row_count = 0;
msiobj_release( &wv->db->hdr );
msi_free( wv );
return ERROR_SUCCESS;
}
static UINT WHERE_find_matching_rows( struct tagMSIVIEW *view, UINT col,
UINT val, UINT *row, MSIITERHANDLE *handle )
{
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
UINT r;
TRACE("%p, %d, %u, %p\n", view, col, val, *handle);
if( !wv->table )
return ERROR_FUNCTION_FAILED;
r = wv->table->ops->find_matching_rows( wv->table, col, val, row, handle );
if( *row > wv->row_count )
return ERROR_NO_MORE_ITEMS;
*row = wv->reorder[ *row ];
return r;
}
static const MSIVIEWOPS where_ops =
{
WHERE_fetch_int,
WHERE_fetch_stream,
WHERE_set_row,
NULL,
WHERE_execute,
WHERE_close,
WHERE_get_dimensions,
WHERE_get_column_info,
WHERE_modify,
WHERE_delete,
WHERE_find_matching_rows
};
static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond,
UINT *valid )
{
UINT r, val = 0;
switch( cond->type )
{
case EXPR_COLUMN:
r = VIEW_find_column( table, cond->u.column, &val );
if( r == ERROR_SUCCESS )
{
UINT type = 0;
r = table->ops->get_column_info( table, val, NULL, &type );
if( r == ERROR_SUCCESS )
{
if (type&MSITYPE_STRING)
cond->type = EXPR_COL_NUMBER_STRING;
else if ((type&0xff) == 4)
cond->type = EXPR_COL_NUMBER32;
else
cond->type = EXPR_COL_NUMBER;
cond->u.col_number = val;
*valid = 1;
}
else
*valid = 0;
}
else
{
*valid = 0;
ERR("Couldn't find column %s\n", debugstr_w( cond->u.column ) );
}
break;
case EXPR_COMPLEX:
r = WHERE_VerifyCondition( db, table, cond->u.expr.left, valid );
if( r != ERROR_SUCCESS )
return r;
if( !*valid )
return ERROR_SUCCESS;
r = WHERE_VerifyCondition( db, table, cond->u.expr.right, valid );
if( r != ERROR_SUCCESS )
return r;
/* check the type of the comparison */
if( ( cond->u.expr.left->type == EXPR_SVAL ) ||
( cond->u.expr.left->type == EXPR_COL_NUMBER_STRING ) ||
( cond->u.expr.right->type == EXPR_SVAL ) ||
( cond->u.expr.right->type == EXPR_COL_NUMBER_STRING ) )
{
switch( cond->u.expr.op )
{
case OP_EQ:
case OP_GT:
case OP_LT:
break;
default:
*valid = FALSE;
return ERROR_INVALID_PARAMETER;
}
/* FIXME: check we're comparing a string to a column */
cond->type = EXPR_STRCMP;
}
break;
case EXPR_UNARY:
if ( cond->u.expr.left->type != EXPR_COLUMN )
{
*valid = FALSE;
return ERROR_INVALID_PARAMETER;
}
r = WHERE_VerifyCondition( db, table, cond->u.expr.left, valid );
if( r != ERROR_SUCCESS )
return r;
break;
case EXPR_IVAL:
*valid = 1;
cond->type = EXPR_UVAL;
cond->u.uval = cond->u.ival;
break;
case EXPR_WILDCARD:
*valid = 1;
break;
case EXPR_SVAL:
*valid = 1;
break;
default:
ERR("Invalid expression type\n");
*valid = 0;
break;
}
return ERROR_SUCCESS;
}
UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table,
struct expr *cond )
{
MSIWHEREVIEW *wv = NULL;
UINT count = 0, r, valid = 0;
TRACE("%p\n", table );
r = table->ops->get_dimensions( table, NULL, &count );
if( r != ERROR_SUCCESS )
{
ERR("can't get table dimensions\n");
return r;
}
if( cond )
{
r = WHERE_VerifyCondition( db, table, cond, &valid );
if( r != ERROR_SUCCESS )
return r;
if( !valid )
return ERROR_FUNCTION_FAILED;
}
wv = msi_alloc_zero( sizeof *wv );
if( !wv )
return ERROR_FUNCTION_FAILED;
/* fill the structure */
wv->view.ops = &where_ops;
msiobj_addref( &db->hdr );
wv->db = db;
wv->table = table;
wv->row_count = 0;
wv->reorder = NULL;
wv->cond = cond;
*view = (MSIVIEW*) wv;
return ERROR_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -