diff --git a/dlls/msi/query.h b/dlls/msi/query.h index 360f4b5aa97..86773ad7c0f 100644 --- a/dlls/msi/query.h +++ b/dlls/msi/query.h @@ -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; diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y index c0056113be7..17cb95714c8 100644 --- a/dlls/msi/sql.y +++ b/dlls/msi/sql.y @@ -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 ); diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 1bca0d33e86..73602382e7e 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -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); } diff --git a/dlls/msi/where.c b/dlls/msi/where.c index 6fd2f8838ab..a30ebcb7c98 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -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: @@ -224,7 +241,7 @@ static UINT WHERE_evaluate( MSIDATABASE *db, MSIVIEW *table, UINT row, default: ERR("Invalid expression type\n"); break; - } + } return ERROR_SUCCESS; @@ -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; @@ -512,7 +539,7 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr ERR("Invalid expression type\n"); *valid = 0; break; - } + } return ERROR_SUCCESS; }