Keep the checkGLcall glActiveTexture/glActiveTextureARB separation in
[wine] / dlls / msi / where.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "wine/debug.h"
27 #include "msi.h"
28 #include "msiquery.h"
29 #include "objbase.h"
30 #include "objidl.h"
31 #include "msipriv.h"
32 #include "winnls.h"
33
34 #include "query.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(msi);
37
38
39 /* below is the query interface to a table */
40
41 typedef struct tagMSIWHEREVIEW
42 {
43     MSIVIEW        view;
44     MSIDATABASE   *db;
45     MSIVIEW       *table;
46     UINT           row_count;
47     UINT          *reorder;
48     struct expr   *cond;
49 } MSIWHEREVIEW;
50
51 static UINT WHERE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
52 {
53     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
54
55     TRACE("%p %d %d %p\n", wv, row, col, val );
56
57     if( !wv->table )
58         return ERROR_FUNCTION_FAILED;
59
60     if( row > wv->row_count )
61         return ERROR_NO_MORE_ITEMS;
62
63     row = wv->reorder[ row ];
64
65     return wv->table->ops->fetch_int( wv->table, row, col, val );
66 }
67
68 static UINT INT_evaluate( UINT lval, UINT op, UINT rval )
69 {
70     switch( op )
71     {
72     case OP_EQ:
73         return ( lval == rval );
74     case OP_AND:
75         return ( lval && rval );
76     case OP_OR:
77         return ( lval || rval );
78     case OP_GT:
79         return ( lval > rval );
80     case OP_LT:
81         return ( lval < rval );
82     case OP_LE:
83         return ( lval <= rval );
84     case OP_GE:
85         return ( lval >= rval );
86     case OP_NE:
87         return ( lval != rval );
88     case OP_ISNULL:
89         return ( !lval );
90     case OP_NOTNULL:
91         return ( lval );
92     default:
93         ERR("Unknown operator %d\n", op );
94     }
95     return 0;
96 }
97
98 static UINT WHERE_evaluate( MSIVIEW *table, UINT row, 
99                              struct expr *cond, UINT *val )
100 {
101     UINT r, lval, rval;
102
103     if( !cond )
104         return ERROR_SUCCESS;
105
106     switch( cond->type )
107     {
108     case EXPR_COL_NUMBER:
109         return table->ops->fetch_int( table, row, cond->u.col_number, val );
110
111     /* case EXPR_IVAL:
112         *val = cond->u.ival;
113         return ERROR_SUCCESS; */
114
115     case EXPR_UVAL:
116         *val = cond->u.uval;
117         return ERROR_SUCCESS;
118
119     case EXPR_COMPLEX:
120         r = WHERE_evaluate( table, row, cond->u.expr.left, &lval );
121         if( r != ERROR_SUCCESS )
122             return r;
123         r = WHERE_evaluate( table, row, cond->u.expr.right, &rval );
124         if( r != ERROR_SUCCESS )
125             return r;
126         *val = INT_evaluate( lval, cond->u.expr.op, rval );
127         return ERROR_SUCCESS;
128
129     default:
130         ERR("Invalid expression type\n");
131         break;
132     } 
133
134     return ERROR_SUCCESS;
135
136 }
137
138 static UINT WHERE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
139 {
140     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
141     UINT count = 0, r, val, i;
142     MSIVIEW *table = wv->table;
143
144     TRACE("%p %ld\n", wv, record);
145
146     if( !table )
147          return ERROR_FUNCTION_FAILED;
148
149     r = table->ops->execute( table, record );
150     if( r != ERROR_SUCCESS )
151         return r;
152
153     r = table->ops->get_dimensions( table, &count, NULL );
154     if( r != ERROR_SUCCESS )
155         return r;
156
157     wv->reorder = HeapAlloc( GetProcessHeap(), 0, count*sizeof(UINT) );
158     if( !wv->reorder )
159         return ERROR_FUNCTION_FAILED;
160
161     for( i=0; i<count; i++ )
162     {
163         val = 0;
164         r = WHERE_evaluate( table, i, wv->cond, &val );
165         if( r != ERROR_SUCCESS )
166             return r;
167         if( val )
168             wv->reorder[ wv->row_count ++ ] = i;
169     }
170
171     return ERROR_SUCCESS;
172 }
173
174 static UINT WHERE_close( struct tagMSIVIEW *view )
175 {
176     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
177
178     TRACE("%p\n", wv );
179
180     if( !wv->table )
181          return ERROR_FUNCTION_FAILED;
182
183     if( wv->reorder )
184         HeapFree( GetProcessHeap(), 0, wv->reorder );
185     wv->reorder = NULL;
186
187     return wv->table->ops->close( wv->table );
188 }
189
190 static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
191 {
192     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
193
194     TRACE("%p %p %p\n", wv, rows, cols );
195
196     if( !wv->table )
197          return ERROR_FUNCTION_FAILED;
198
199     if( rows )
200     {
201         if( !wv->reorder )
202             return ERROR_FUNCTION_FAILED;
203         *rows = wv->row_count;
204     }
205
206     return wv->table->ops->get_dimensions( wv->table, NULL, cols );
207 }
208
209 static UINT WHERE_get_column_info( struct tagMSIVIEW *view,
210                 UINT n, LPWSTR *name, UINT *type )
211 {
212     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
213
214     TRACE("%p %d %p %p\n", wv, n, name, type );
215
216     if( !wv->table )
217          return ERROR_FUNCTION_FAILED;
218
219     return wv->table->ops->get_column_info( wv->table, n, name, type );
220 }
221
222 static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec)
223 {
224     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
225
226     TRACE("%p %d %ld\n", wv, eModifyMode, hrec );
227
228     if( !wv->table )
229          return ERROR_FUNCTION_FAILED;
230
231     return wv->table->ops->modify( wv->table, eModifyMode, hrec );
232 }
233
234 static UINT WHERE_delete( struct tagMSIVIEW *view )
235 {
236     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
237
238     TRACE("%p\n", wv );
239
240     if( wv->table )
241         wv->table->ops->delete( wv->table );
242
243     if( wv->reorder )
244         HeapFree( GetProcessHeap(), 0, wv->reorder );
245     wv->reorder = NULL;
246     wv->row_count = 0;
247
248     delete_expr( wv->cond );
249
250     HeapFree( GetProcessHeap(), 0, wv );
251
252     return ERROR_SUCCESS;
253 }
254
255
256 MSIVIEWOPS where_ops =
257 {
258     WHERE_fetch_int,
259     NULL,
260     NULL,
261     WHERE_execute,
262     WHERE_close,
263     WHERE_get_dimensions,
264     WHERE_get_column_info,
265     WHERE_modify,
266     WHERE_delete
267 };
268
269 UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
270 {
271     MSIWHEREVIEW *wv = NULL;
272     UINT count = 0, r;
273
274     TRACE("%p\n", wv );
275
276     r = table->ops->get_dimensions( table, NULL, &count );
277     if( r != ERROR_SUCCESS )
278     {
279         ERR("can't get table dimensions\n");
280         return r;
281     }
282
283     wv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *wv );
284     if( !wv )
285         return ERROR_FUNCTION_FAILED;
286     
287     /* fill the structure */
288     wv->view.ops = &where_ops;
289     wv->db = db;
290     wv->table = table;
291     wv->row_count = 0;
292     wv->reorder = NULL;
293     *view = (MSIVIEW*) wv;
294
295     return ERROR_SUCCESS;
296 }
297
298 static UINT WHERE_VerifyCondition( MSIVIEW *table, struct expr *cond,
299                                    UINT *valid )
300 {
301     UINT r, col = 0;
302
303     switch( cond->type )
304     {
305     case EXPR_COLUMN:
306         r = VIEW_find_column( table, cond->u.column, &col );
307         if( r == ERROR_SUCCESS )
308         {
309             *valid = 1;
310             cond->type = EXPR_COL_NUMBER;
311             cond->u.col_number = col;
312         }
313         else
314         {
315             *valid = 0;
316             ERR("Couldn't find column %s\n", debugstr_w( cond->u.column ) );
317         }
318         break;
319     case EXPR_COMPLEX:
320         r = WHERE_VerifyCondition( table, cond->u.expr.left, valid );
321         if( r != ERROR_SUCCESS )
322             return r;
323         if( !*valid )
324             return ERROR_SUCCESS;
325         r = WHERE_VerifyCondition( table, cond->u.expr.right, valid );
326         if( r != ERROR_SUCCESS )
327             return r;
328         break;
329     case EXPR_IVAL:
330         *valid = 1;
331         cond->type = EXPR_UVAL;
332         cond->u.uval = cond->u.ival + (1<<15);
333         break;
334     case EXPR_SVAL:
335         *valid = 0;
336         FIXME("can't deal with string values yet\n");
337         break;
338     default:
339         ERR("Invalid expression type\n");
340         *valid = 0;
341         break;
342     } 
343
344     return ERROR_SUCCESS;
345 }
346
347 UINT WHERE_AddCondition( MSIVIEW *view, struct expr *cond )
348 {
349     MSIWHEREVIEW *wv = (MSIWHEREVIEW *) view;
350     UINT r, valid = 0;
351
352     if( wv->view.ops != &where_ops )
353         return ERROR_FUNCTION_FAILED;
354     if( !wv->table )
355         return ERROR_INVALID_PARAMETER;
356     
357     if( !cond )
358         return ERROR_SUCCESS;
359
360     TRACE("Adding condition\n");
361
362     r = WHERE_VerifyCondition( wv->table, cond, &valid );
363     if( r != ERROR_SUCCESS )
364         ERR("condition evaluation failed\n");
365
366     TRACE("condition is %s\n", valid ? "valid" : "invalid" );
367     if( !valid )
368     {
369         delete_expr( cond );
370         return ERROR_FUNCTION_FAILED;
371     }
372
373     wv->cond = cond;
374
375     return ERROR_SUCCESS;
376 }