msi: Fix WHERE IS (NOT) NULL queries.
This commit is contained in:
parent
2b943bfddc
commit
50e5caeb6c
|
@ -54,6 +54,7 @@
|
|||
#define EXPR_WILDCARD 9
|
||||
#define EXPR_COL_NUMBER_STRING 10
|
||||
#define EXPR_COL_NUMBER32 11
|
||||
#define EXPR_UNARY 12
|
||||
|
||||
struct sql_str {
|
||||
LPCWSTR data;
|
||||
|
|
|
@ -59,6 +59,7 @@ static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR colu
|
|||
static BOOL SQL_MarkPrimaryKeys( column_info *cols, column_info *keys);
|
||||
|
||||
static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );
|
||||
static struct expr * EXPR_unary( void *info, struct expr *l, UINT op );
|
||||
static struct expr * EXPR_column( void *info, column_info *column );
|
||||
static struct expr * EXPR_ival( void *info, int val );
|
||||
static struct expr * EXPR_sval( void *info, struct sql_str * );
|
||||
|
@ -513,13 +514,13 @@ expr:
|
|||
}
|
||||
| column_val TK_IS TK_NULL
|
||||
{
|
||||
$$ = EXPR_complex( info, $1, OP_ISNULL, NULL );
|
||||
$$ = EXPR_unary( info, $1, OP_ISNULL );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_IS TK_NOT TK_NULL
|
||||
{
|
||||
$$ = EXPR_complex( info, $1, OP_NOTNULL, NULL );
|
||||
$$ = EXPR_unary( info, $1, OP_NOTNULL );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
|
@ -762,6 +763,19 @@ static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct e
|
|||
return e;
|
||||
}
|
||||
|
||||
static struct expr * EXPR_unary( void *info, struct expr *l, UINT op )
|
||||
{
|
||||
struct expr *e = parser_alloc( info, sizeof *e );
|
||||
if( e )
|
||||
{
|
||||
e->type = EXPR_UNARY;
|
||||
e->u.expr.left = l;
|
||||
e->u.expr.op = op;
|
||||
e->u.expr.right = NULL;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct expr * EXPR_column( void *info, column_info *column )
|
||||
{
|
||||
struct expr *e = parser_alloc( info, sizeof *e );
|
||||
|
|
|
@ -1354,6 +1354,12 @@ static void test_where(void)
|
|||
|
||||
MsiCloseHandle( rec );
|
||||
|
||||
rec = 0;
|
||||
query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
|
||||
r = do_query(hdb, query, &rec);
|
||||
ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
|
||||
MsiCloseHandle( rec );
|
||||
|
||||
MsiCloseHandle( hdb );
|
||||
DeleteFile(msifile);
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
|
|||
return wv->table->ops->set_row( wv->table, row, rec, mask );
|
||||
}
|
||||
|
||||
static INT INT_evaluate( INT lval, UINT op, INT rval )
|
||||
static INT INT_evaluate_binary( INT lval, UINT op, INT rval )
|
||||
{
|
||||
switch( op )
|
||||
{
|
||||
|
@ -119,6 +119,16 @@ static INT INT_evaluate( INT lval, UINT op, INT rval )
|
|||
return ( lval >= rval );
|
||||
case OP_NE:
|
||||
return ( lval != rval );
|
||||
default:
|
||||
ERR("Unknown operator %d\n", op );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT INT_evaluate_unary( INT lval, UINT op )
|
||||
{
|
||||
switch( op )
|
||||
{
|
||||
case OP_ISNULL:
|
||||
return ( !lval );
|
||||
case OP_NOTNULL:
|
||||
|
@ -211,7 +221,14 @@ static UINT WHERE_evaluate( MSIDATABASE *db, MSIVIEW *table, UINT row,
|
|||
r = WHERE_evaluate( db, table, row, cond->u.expr.right, &rval, record );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
*val = INT_evaluate( lval, cond->u.expr.op, rval );
|
||||
*val = INT_evaluate_binary( lval, cond->u.expr.op, rval );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case EXPR_UNARY:
|
||||
r = table->ops->fetch_int( table, row, cond->u.expr.left->u.col_number, &tval );
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
*val = INT_evaluate_unary( tval, cond->u.expr.op );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case EXPR_STRCMP:
|
||||
|
@ -497,6 +514,16 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue