2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002 Mike McCormack for CodeWeavers
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
28 #include "wine/unicode.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msidb
);
40 /* below is the query interface to a table */
41 typedef struct tagMSIROWENTRY
43 struct tagMSIWHEREVIEW
*wv
; /* used during sorting */
47 typedef struct tagJOINTABLE
49 struct tagJOINTABLE
*next
;
56 typedef struct tagMSIORDERINFO
60 union ext_column columns
[1];
63 typedef struct tagMSIWHEREVIEW
71 MSIROWENTRY
**reorder
;
72 UINT reorder_size
; /* number of entries available in reorder */
75 MSIORDERINFO
*order_info
;
78 #define INITIAL_REORDER_SIZE 16
80 static UINT
init_reorder(MSIWHEREVIEW
*wv
)
82 MSIROWENTRY
**new = msi_alloc_zero(sizeof(MSIROWENTRY
*) * INITIAL_REORDER_SIZE
);
84 return ERROR_OUTOFMEMORY
;
87 msi_free(wv
->reorder
);
90 wv
->reorder_size
= INITIAL_REORDER_SIZE
;
96 static void free_reorder(MSIWHEREVIEW
*wv
)
103 for (i
= 0; i
< wv
->row_count
; i
++)
104 msi_free(wv
->reorder
[i
]);
106 msi_free( wv
->reorder
);
108 wv
->reorder_size
= 0;
112 static inline UINT
find_row(MSIWHEREVIEW
*wv
, UINT row
, UINT
*(values
[]))
114 if (row
>= wv
->row_count
)
115 return ERROR_NO_MORE_ITEMS
;
117 *values
= wv
->reorder
[row
]->values
;
119 return ERROR_SUCCESS
;
122 static UINT
add_row(MSIWHEREVIEW
*wv
, UINT vals
[])
126 if (wv
->reorder_size
<= wv
->row_count
)
128 MSIROWENTRY
**new_reorder
;
129 UINT newsize
= wv
->reorder_size
* 2;
131 new_reorder
= msi_realloc_zero(wv
->reorder
, sizeof(MSIROWENTRY
*) * newsize
);
133 return ERROR_OUTOFMEMORY
;
135 wv
->reorder
= new_reorder
;
136 wv
->reorder_size
= newsize
;
139 new = msi_alloc(FIELD_OFFSET( MSIROWENTRY
, values
[wv
->table_count
] ));
142 return ERROR_OUTOFMEMORY
;
144 wv
->reorder
[wv
->row_count
++] = new;
146 memcpy(new->values
, vals
, wv
->table_count
* sizeof(UINT
));
149 return ERROR_SUCCESS
;
152 JOINTABLE
*find_table(MSIWHEREVIEW
*wv
, UINT col
, UINT
*table_col
)
154 JOINTABLE
*table
= wv
->tables
;
156 if(col
== 0 || col
> wv
->col_count
)
159 while (col
> table
->col_count
)
161 col
-= table
->col_count
;
170 static UINT
parse_column(MSIWHEREVIEW
*wv
, union ext_column
*column
,
173 JOINTABLE
*table
= wv
->tables
;
180 if (column
->unparsed
.table
)
182 r
= table
->view
->ops
->get_column_info(table
->view
, 1, NULL
, NULL
,
184 if (r
!= ERROR_SUCCESS
)
186 if (strcmpW(table_name
, column
->unparsed
.table
) != 0)
190 for(i
= 1; i
<= table
->col_count
; i
++)
194 r
= table
->view
->ops
->get_column_info(table
->view
, i
, &col_name
, column_type
,
196 if(r
!= ERROR_SUCCESS
)
199 if(strcmpW(col_name
, column
->unparsed
.column
))
201 column
->parsed
.column
= i
;
202 column
->parsed
.table
= table
;
203 return ERROR_SUCCESS
;
207 while ((table
= table
->next
));
209 WARN("Couldn't find column %s.%s\n", debugstr_w( column
->unparsed
.table
), debugstr_w( column
->unparsed
.column
) );
210 return ERROR_BAD_QUERY_SYNTAX
;
213 static UINT
WHERE_fetch_int( struct tagMSIVIEW
*view
, UINT row
, UINT col
, UINT
*val
)
215 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
220 TRACE("%p %d %d %p\n", wv
, row
, col
, val
);
223 return ERROR_FUNCTION_FAILED
;
225 r
= find_row(wv
, row
, &rows
);
226 if (r
!= ERROR_SUCCESS
)
229 table
= find_table(wv
, col
, &col
);
231 return ERROR_FUNCTION_FAILED
;
233 return table
->view
->ops
->fetch_int(table
->view
, rows
[table
->table_index
], col
, val
);
236 static UINT
WHERE_fetch_stream( struct tagMSIVIEW
*view
, UINT row
, UINT col
, IStream
**stm
)
238 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
243 TRACE("%p %d %d %p\n", wv
, row
, col
, stm
);
246 return ERROR_FUNCTION_FAILED
;
248 r
= find_row(wv
, row
, &rows
);
249 if (r
!= ERROR_SUCCESS
)
252 table
= find_table(wv
, col
, &col
);
254 return ERROR_FUNCTION_FAILED
;
256 return table
->view
->ops
->fetch_stream( table
->view
, rows
[table
->table_index
], col
, stm
);
259 static UINT
WHERE_get_row( struct tagMSIVIEW
*view
, UINT row
, MSIRECORD
**rec
)
261 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
263 TRACE("%p %d %p\n", wv
, row
, rec
);
266 return ERROR_FUNCTION_FAILED
;
268 return msi_view_get_row( wv
->db
, view
, row
, rec
);
271 static UINT
WHERE_set_row( struct tagMSIVIEW
*view
, UINT row
, MSIRECORD
*rec
, UINT mask
)
273 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
274 UINT i
, r
, offset
= 0;
275 JOINTABLE
*table
= wv
->tables
;
277 UINT mask_copy
= mask
;
279 TRACE("%p %d %p %08x\n", wv
, row
, rec
, mask
);
282 return ERROR_FUNCTION_FAILED
;
284 r
= find_row(wv
, row
, &rows
);
285 if (r
!= ERROR_SUCCESS
)
288 if (mask
>= 1 << wv
->col_count
)
289 return ERROR_INVALID_PARAMETER
;
293 for (i
= 0; i
< table
->col_count
; i
++) {
296 if (!(mask_copy
& (1 << i
)))
298 r
= table
->view
->ops
->get_column_info(table
->view
, i
+ 1, NULL
,
300 if (r
!= ERROR_SUCCESS
)
302 if (type
& MSITYPE_KEY
)
303 return ERROR_FUNCTION_FAILED
;
305 mask_copy
>>= table
->col_count
;
307 while (mask_copy
&& (table
= table
->next
));
313 const UINT col_count
= table
->col_count
;
316 UINT reduced_mask
= (mask
>> offset
) & ((1 << col_count
) - 1);
324 reduced
= MSI_CreateRecord(col_count
);
326 return ERROR_FUNCTION_FAILED
;
328 for (i
= 1; i
<= col_count
; i
++)
330 r
= MSI_RecordCopyField(rec
, i
+ offset
, reduced
, i
);
331 if (r
!= ERROR_SUCCESS
)
337 if (r
== ERROR_SUCCESS
)
338 r
= table
->view
->ops
->set_row(table
->view
, rows
[table
->table_index
], reduced
, reduced_mask
);
340 msiobj_release(&reduced
->hdr
);
342 while ((table
= table
->next
));
346 static UINT
WHERE_delete_row(struct tagMSIVIEW
*view
, UINT row
)
348 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
352 TRACE("(%p %d)\n", view
, row
);
355 return ERROR_FUNCTION_FAILED
;
357 r
= find_row(wv
, row
, &rows
);
358 if ( r
!= ERROR_SUCCESS
)
361 if (wv
->table_count
> 1)
362 return ERROR_CALL_NOT_IMPLEMENTED
;
364 return wv
->tables
->view
->ops
->delete_row(wv
->tables
->view
, rows
[0]);
367 static INT
INT_evaluate_binary( INT lval
, UINT op
, INT rval
)
372 return ( lval
== rval
);
374 return ( lval
&& rval
);
376 return ( lval
|| rval
);
378 return ( lval
> rval
);
380 return ( lval
< rval
);
382 return ( lval
<= rval
);
384 return ( lval
>= rval
);
386 return ( lval
!= rval
);
388 ERR("Unknown operator %d\n", op
);
393 static inline UINT
expr_fetch_value(const union ext_column
*expr
, const UINT rows
[], UINT
*val
)
395 JOINTABLE
*table
= expr
->parsed
.table
;
397 return table
->view
->ops
->fetch_int(table
->view
, rows
[table
->table_index
],
398 expr
->parsed
.column
, val
);
402 static INT
INT_evaluate_unary( INT lval
, UINT op
)
411 ERR("Unknown operator %d\n", op
);
416 static const WCHAR
*STRING_evaluate( MSIWHEREVIEW
*wv
, const UINT rows
[],
417 const struct expr
*expr
,
418 const MSIRECORD
*record
)
424 case EXPR_COL_NUMBER_STRING
:
425 r
= expr_fetch_value(&expr
->u
.column
, rows
, &val
);
426 if( r
!= ERROR_SUCCESS
)
428 return msi_string_lookup_id( wv
->db
->strings
, val
);
434 return MSI_RecordGetString( record
, ++wv
->rec_index
);
437 ERR("Invalid expression type\n");
443 static UINT
STRCMP_Evaluate( MSIWHEREVIEW
*wv
, const UINT rows
[], const struct expr
*cond
,
444 INT
*val
, const MSIRECORD
*record
)
447 const WCHAR
*l_str
, *r_str
;
449 l_str
= STRING_evaluate( wv
, rows
, cond
->u
.expr
.left
, record
);
450 r_str
= STRING_evaluate( wv
, rows
, cond
->u
.expr
.right
, record
);
451 if( l_str
== r_str
||
452 ((!l_str
|| !*l_str
) && (!r_str
|| !*r_str
)) )
454 else if( l_str
&& ! r_str
)
456 else if( r_str
&& ! l_str
)
459 sr
= strcmpW( l_str
, r_str
);
461 *val
= ( cond
->u
.expr
.op
== OP_EQ
&& ( sr
== 0 ) ) ||
462 ( cond
->u
.expr
.op
== OP_NE
&& ( sr
!= 0 ) );
464 return ERROR_SUCCESS
;
467 static UINT
WHERE_evaluate( MSIWHEREVIEW
*wv
, const UINT rows
[],
468 struct expr
*cond
, INT
*val
, MSIRECORD
*record
)
476 return ERROR_SUCCESS
;
481 case EXPR_COL_NUMBER
:
482 r
= expr_fetch_value(&cond
->u
.column
, rows
, &tval
);
483 if( r
!= ERROR_SUCCESS
)
485 *val
= tval
- 0x8000;
486 return ERROR_SUCCESS
;
488 case EXPR_COL_NUMBER32
:
489 r
= expr_fetch_value(&cond
->u
.column
, rows
, &tval
);
490 if( r
!= ERROR_SUCCESS
)
492 *val
= tval
- 0x80000000;
497 return ERROR_SUCCESS
;
500 r
= WHERE_evaluate( wv
, rows
, cond
->u
.expr
.left
, &lval
, record
);
501 if( r
!= ERROR_SUCCESS
)
503 r
= WHERE_evaluate( wv
, rows
, cond
->u
.expr
.right
, &rval
, record
);
504 if( r
!= ERROR_SUCCESS
)
506 *val
= INT_evaluate_binary( lval
, cond
->u
.expr
.op
, rval
);
507 return ERROR_SUCCESS
;
510 r
= expr_fetch_value(&cond
->u
.expr
.left
->u
.column
, rows
, &tval
);
511 if( r
!= ERROR_SUCCESS
)
513 *val
= INT_evaluate_unary( tval
, cond
->u
.expr
.op
);
514 return ERROR_SUCCESS
;
517 return STRCMP_Evaluate( wv
, rows
, cond
, val
, record
);
520 *val
= MSI_RecordGetInteger( record
, ++wv
->rec_index
);
521 return ERROR_SUCCESS
;
524 ERR("Invalid expression type\n");
528 return ERROR_SUCCESS
;
531 static UINT
check_condition( MSIWHEREVIEW
*wv
, MSIRECORD
*record
, JOINTABLE
*table
,
534 UINT r
= ERROR_FUNCTION_FAILED
;
537 for (table_rows
[table
->table_index
] = 0; table_rows
[table
->table_index
] < table
->row_count
;
538 table_rows
[table
->table_index
]++)
542 r
= check_condition(wv
, record
, table
->next
, table_rows
);
543 if(r
!= ERROR_SUCCESS
)
550 r
= WHERE_evaluate (wv
, table_rows
, wv
->cond
, &val
, record
);
551 if(r
!= ERROR_SUCCESS
)
555 add_row(wv
, table_rows
);
561 static int compare_entry( const void *left
, const void *right
)
563 const MSIROWENTRY
*le
= *(const MSIROWENTRY
**)left
;
564 const MSIROWENTRY
*re
= *(const MSIROWENTRY
**)right
;
565 const MSIWHEREVIEW
*wv
= le
->wv
;
566 MSIORDERINFO
*order
= wv
->order_info
;
567 UINT i
, j
, r
, l_val
, r_val
;
569 assert(le
->wv
== re
->wv
);
573 for (i
= 0; i
< order
->col_count
; i
++)
575 const union ext_column
*column
= &order
->columns
[i
];
577 r
= column
->parsed
.table
->view
->ops
->fetch_int(column
->parsed
.table
->view
,
578 le
->values
[column
->parsed
.table
->table_index
],
579 column
->parsed
.column
, &l_val
);
580 if (r
!= ERROR_SUCCESS
)
586 r
= column
->parsed
.table
->view
->ops
->fetch_int(column
->parsed
.table
->view
,
587 re
->values
[column
->parsed
.table
->table_index
],
588 column
->parsed
.column
, &r_val
);
589 if (r
!= ERROR_SUCCESS
)
596 return l_val
< r_val
? -1 : 1;
600 for (j
= 0; j
< wv
->table_count
; j
++)
602 if (le
->values
[j
] != re
->values
[j
])
603 return le
->values
[j
] < re
->values
[j
] ? -1 : 1;
608 static UINT
WHERE_execute( struct tagMSIVIEW
*view
, MSIRECORD
*record
)
610 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
612 JOINTABLE
*table
= wv
->tables
;
613 UINT rows
[wv
->table_count
];
615 TRACE("%p %p\n", wv
, record
);
618 return ERROR_FUNCTION_FAILED
;
620 r
= init_reorder(wv
);
621 if (r
!= ERROR_SUCCESS
)
626 table
->view
->ops
->execute(table
->view
, NULL
);
628 r
= table
->view
->ops
->get_dimensions(table
->view
, &table
->row_count
, NULL
);
629 if (r
!= ERROR_SUCCESS
)
631 ERR("failed to get table dimensions\n");
635 /* each table must have at least one row */
636 if (table
->row_count
== 0)
637 return ERROR_SUCCESS
;
639 while ((table
= table
->next
));
641 r
= check_condition(wv
, record
, wv
->tables
, rows
);
644 wv
->order_info
->error
= ERROR_SUCCESS
;
646 qsort(wv
->reorder
, wv
->row_count
, sizeof(MSIROWENTRY
*), compare_entry
);
649 r
= wv
->order_info
->error
;
654 static UINT
WHERE_close( struct tagMSIVIEW
*view
)
656 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
657 JOINTABLE
*table
= wv
->tables
;
662 return ERROR_FUNCTION_FAILED
;
665 table
->view
->ops
->close(table
->view
);
666 while ((table
= table
->next
));
668 return ERROR_SUCCESS
;
671 static UINT
WHERE_get_dimensions( struct tagMSIVIEW
*view
, UINT
*rows
, UINT
*cols
)
673 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
675 TRACE("%p %p %p\n", wv
, rows
, cols
);
678 return ERROR_FUNCTION_FAILED
;
683 return ERROR_FUNCTION_FAILED
;
684 *rows
= wv
->row_count
;
688 *cols
= wv
->col_count
;
690 return ERROR_SUCCESS
;
693 static UINT
WHERE_get_column_info( struct tagMSIVIEW
*view
, UINT n
, LPCWSTR
*name
,
694 UINT
*type
, BOOL
*temporary
, LPCWSTR
*table_name
)
696 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
699 TRACE("%p %d %p %p %p %p\n", wv
, n
, name
, type
, temporary
, table_name
);
702 return ERROR_FUNCTION_FAILED
;
704 table
= find_table(wv
, n
, &n
);
706 return ERROR_FUNCTION_FAILED
;
708 return table
->view
->ops
->get_column_info(table
->view
, n
, name
,
709 type
, temporary
, table_name
);
712 static UINT
join_find_row( MSIWHEREVIEW
*wv
, MSIRECORD
*rec
, UINT
*row
)
717 str
= MSI_RecordGetString( rec
, 1 );
718 r
= msi_string2idW( wv
->db
->strings
, str
, &id
);
719 if (r
!= ERROR_SUCCESS
)
722 for (i
= 0; i
< wv
->row_count
; i
++)
724 WHERE_fetch_int( &wv
->view
, i
, 1, &data
);
729 return ERROR_SUCCESS
;
733 return ERROR_FUNCTION_FAILED
;
736 static UINT
join_modify_update( struct tagMSIVIEW
*view
, MSIRECORD
*rec
)
738 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
739 UINT r
, row
, i
, mask
= 0;
743 r
= join_find_row( wv
, rec
, &row
);
744 if (r
!= ERROR_SUCCESS
)
747 r
= msi_view_get_row( wv
->db
, view
, row
, ¤t
);
748 if (r
!= ERROR_SUCCESS
)
751 assert(MSI_RecordGetFieldCount(rec
) == MSI_RecordGetFieldCount(current
));
753 for (i
= MSI_RecordGetFieldCount(rec
); i
> 0; i
--)
755 if (!MSI_RecordsAreFieldsEqual(rec
, current
, i
))
756 mask
|= 1 << (i
- 1);
758 msiobj_release(¤t
->hdr
);
760 return WHERE_set_row( view
, row
, rec
, mask
);
763 static UINT
WHERE_modify( struct tagMSIVIEW
*view
, MSIMODIFY eModifyMode
,
764 MSIRECORD
*rec
, UINT row
)
766 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
767 JOINTABLE
*table
= wv
->tables
;
770 TRACE("%p %d %p\n", wv
, eModifyMode
, rec
);
773 return ERROR_FUNCTION_FAILED
;
779 if (find_row(wv
, row
- 1, &rows
) == ERROR_SUCCESS
)
784 return table
->view
->ops
->modify(table
->view
, eModifyMode
, rec
, row
);
789 case MSIMODIFY_UPDATE
:
790 return join_modify_update( view
, rec
);
792 case MSIMODIFY_ASSIGN
:
793 case MSIMODIFY_DELETE
:
794 case MSIMODIFY_INSERT
:
795 case MSIMODIFY_INSERT_TEMPORARY
:
796 case MSIMODIFY_MERGE
:
797 case MSIMODIFY_REPLACE
:
799 case MSIMODIFY_VALIDATE
:
800 case MSIMODIFY_VALIDATE_DELETE
:
801 case MSIMODIFY_VALIDATE_FIELD
:
802 case MSIMODIFY_VALIDATE_NEW
:
803 r
= ERROR_FUNCTION_FAILED
;
806 case MSIMODIFY_REFRESH
:
807 r
= ERROR_CALL_NOT_IMPLEMENTED
;
811 WARN("%p %d %p %u - unknown mode\n", view
, eModifyMode
, rec
, row
);
812 r
= ERROR_INVALID_PARAMETER
;
819 static UINT
WHERE_delete( struct tagMSIVIEW
*view
)
821 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
822 JOINTABLE
*table
= wv
->tables
;
830 table
->view
->ops
->delete(table
->view
);
843 msi_free(wv
->order_info
);
844 wv
->order_info
= NULL
;
847 msiobj_release( &wv
->db
->hdr
);
850 return ERROR_SUCCESS
;
853 static UINT
WHERE_find_matching_rows( struct tagMSIVIEW
*view
, UINT col
,
854 UINT val
, UINT
*row
, MSIITERHANDLE
*handle
)
856 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
859 TRACE("%p, %d, %u, %p\n", view
, col
, val
, *handle
);
862 return ERROR_FUNCTION_FAILED
;
864 if (col
== 0 || col
> wv
->col_count
)
865 return ERROR_INVALID_PARAMETER
;
867 for (i
= PtrToUlong(*handle
); i
< wv
->row_count
; i
++)
869 if (view
->ops
->fetch_int( view
, i
, col
, &row_value
) != ERROR_SUCCESS
)
872 if (row_value
== val
)
875 *handle
= UlongToPtr(i
+ 1);
876 return ERROR_SUCCESS
;
880 return ERROR_NO_MORE_ITEMS
;
883 static UINT
WHERE_sort(struct tagMSIVIEW
*view
, column_info
*columns
)
885 MSIWHEREVIEW
*wv
= (MSIWHEREVIEW
*)view
;
886 JOINTABLE
*table
= wv
->tables
;
887 column_info
*column
= columns
;
888 MSIORDERINFO
*orderinfo
;
892 TRACE("%p %p\n", view
, columns
);
895 return ERROR_FUNCTION_FAILED
;
900 column
= column
->next
;
904 return ERROR_SUCCESS
;
906 orderinfo
= msi_alloc(sizeof(MSIORDERINFO
) + (count
- 1) * sizeof(union ext_column
));
908 return ERROR_OUTOFMEMORY
;
910 orderinfo
->col_count
= count
;
914 for (i
= 0; i
< count
; i
++)
916 orderinfo
->columns
[i
].unparsed
.column
= column
->column
;
917 orderinfo
->columns
[i
].unparsed
.table
= column
->table
;
919 r
= parse_column(wv
, &orderinfo
->columns
[i
], NULL
);
920 if (r
!= ERROR_SUCCESS
)
924 wv
->order_info
= orderinfo
;
926 return ERROR_SUCCESS
;
932 static const MSIVIEWOPS where_ops
=
942 WHERE_get_dimensions
,
943 WHERE_get_column_info
,
946 WHERE_find_matching_rows
,
955 static UINT
WHERE_VerifyCondition( MSIWHEREVIEW
*wv
, struct expr
*cond
,
968 r
= parse_column(wv
, &cond
->u
.column
, &type
);
969 if (r
!= ERROR_SUCCESS
)
972 if (type
&MSITYPE_STRING
)
973 cond
->type
= EXPR_COL_NUMBER_STRING
;
974 else if ((type
&0xff) == 4)
975 cond
->type
= EXPR_COL_NUMBER32
;
977 cond
->type
= EXPR_COL_NUMBER
;
983 r
= WHERE_VerifyCondition( wv
, cond
->u
.expr
.left
, valid
);
984 if( r
!= ERROR_SUCCESS
)
987 return ERROR_SUCCESS
;
988 r
= WHERE_VerifyCondition( wv
, cond
->u
.expr
.right
, valid
);
989 if( r
!= ERROR_SUCCESS
)
992 /* check the type of the comparison */
993 if( ( cond
->u
.expr
.left
->type
== EXPR_SVAL
) ||
994 ( cond
->u
.expr
.left
->type
== EXPR_COL_NUMBER_STRING
) ||
995 ( cond
->u
.expr
.right
->type
== EXPR_SVAL
) ||
996 ( cond
->u
.expr
.right
->type
== EXPR_COL_NUMBER_STRING
) )
998 switch( cond
->u
.expr
.op
)
1005 return ERROR_INVALID_PARAMETER
;
1008 /* FIXME: check we're comparing a string to a column */
1010 cond
->type
= EXPR_STRCMP
;
1015 if ( cond
->u
.expr
.left
->type
!= EXPR_COLUMN
)
1018 return ERROR_INVALID_PARAMETER
;
1020 r
= WHERE_VerifyCondition( wv
, cond
->u
.expr
.left
, valid
);
1021 if( r
!= ERROR_SUCCESS
)
1026 cond
->type
= EXPR_UVAL
;
1027 cond
->u
.uval
= cond
->u
.ival
;
1036 ERR("Invalid expression type\n");
1041 return ERROR_SUCCESS
;
1044 UINT
WHERE_CreateView( MSIDATABASE
*db
, MSIVIEW
**view
, LPWSTR tables
,
1047 MSIWHEREVIEW
*wv
= NULL
;
1051 TRACE("(%s)\n", debugstr_w(tables
) );
1053 wv
= msi_alloc_zero( sizeof *wv
);
1055 return ERROR_FUNCTION_FAILED
;
1057 /* fill the structure */
1058 wv
->view
.ops
= &where_ops
;
1059 msiobj_addref( &db
->hdr
);
1067 if ((ptr
= strchrW(tables
, ' ')))
1070 table
= msi_alloc(sizeof(JOINTABLE
));
1073 r
= ERROR_OUTOFMEMORY
;
1077 r
= TABLE_CreateView(db
, tables
, &table
->view
);
1078 if (r
!= ERROR_SUCCESS
)
1080 WARN("can't create table: %s\n", debugstr_w(tables
));
1082 r
= ERROR_BAD_QUERY_SYNTAX
;
1086 r
= table
->view
->ops
->get_dimensions(table
->view
, NULL
,
1088 if (r
!= ERROR_SUCCESS
)
1090 ERR("can't get table dimensions\n");
1094 wv
->col_count
+= table
->col_count
;
1095 table
->table_index
= wv
->table_count
++;
1097 table
->next
= wv
->tables
;
1108 r
= WHERE_VerifyCondition( wv
, cond
, &valid
);
1109 if( r
!= ERROR_SUCCESS
)
1112 r
= ERROR_FUNCTION_FAILED
;
1117 *view
= (MSIVIEW
*) wv
;
1119 return ERROR_SUCCESS
;
1121 WHERE_delete(&wv
->view
);