2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2006 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
26 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msidb
);
36 typedef struct tagMSIJOINVIEW
40 MSIVIEW
*left
, *right
;
41 UINT left_count
, right_count
;
42 UINT left_rows
, right_rows
;
45 static UINT
JOIN_fetch_int( struct tagMSIVIEW
*view
, UINT row
, UINT col
, UINT
*val
)
47 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
50 TRACE("%p %d %d %p\n", jv
, row
, col
, val
);
52 if( !jv
->left
|| !jv
->right
)
53 return ERROR_FUNCTION_FAILED
;
55 if( (col
==0) || (col
>(jv
->left_count
+ jv
->right_count
)) )
56 return ERROR_FUNCTION_FAILED
;
58 if( row
>= (jv
->left_rows
* jv
->right_rows
) )
59 return ERROR_FUNCTION_FAILED
;
61 if( col
<= jv
->left_count
)
64 row
= (row
/jv
->right_rows
);
69 row
= (row
% jv
->right_rows
);
70 col
-= jv
->left_count
;
73 return table
->ops
->fetch_int( table
, row
, col
, val
);
76 static UINT
JOIN_fetch_stream( struct tagMSIVIEW
*view
, UINT row
, UINT col
, IStream
**stm
)
78 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
81 TRACE("%p %d %d %p\n", jv
, row
, col
, stm
);
83 if( !jv
->left
|| !jv
->right
)
84 return ERROR_FUNCTION_FAILED
;
86 if( (col
==0) || (col
>(jv
->left_count
+ jv
->right_count
)) )
87 return ERROR_FUNCTION_FAILED
;
89 if( row
>= jv
->left_rows
* jv
->right_rows
)
90 return ERROR_FUNCTION_FAILED
;
92 if( row
<= jv
->left_count
)
95 row
= (row
/jv
->right_rows
);
100 row
= (row
% jv
->right_rows
);
101 col
-= jv
->left_count
;
104 return table
->ops
->fetch_stream( table
, row
, col
, stm
);
107 static UINT
JOIN_execute( struct tagMSIVIEW
*view
, MSIRECORD
*record
)
109 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
110 UINT r
, *ldata
= NULL
, *rdata
= NULL
;
112 TRACE("%p %p\n", jv
, record
);
114 if( !jv
->left
|| !jv
->right
)
115 return ERROR_FUNCTION_FAILED
;
117 r
= jv
->left
->ops
->execute( jv
->left
, NULL
);
118 if (r
!= ERROR_SUCCESS
)
121 r
= jv
->right
->ops
->execute( jv
->right
, NULL
);
122 if (r
!= ERROR_SUCCESS
)
125 /* get the number of rows in each table */
126 r
= jv
->left
->ops
->get_dimensions( jv
->left
, &jv
->left_rows
, NULL
);
127 if( r
!= ERROR_SUCCESS
)
129 ERR("can't get left table dimensions\n");
133 r
= jv
->right
->ops
->get_dimensions( jv
->right
, &jv
->right_rows
, NULL
);
134 if( r
!= ERROR_SUCCESS
)
136 ERR("can't get right table dimensions\n");
147 static UINT
JOIN_close( struct tagMSIVIEW
*view
)
149 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
153 if( !jv
->left
|| !jv
->right
)
154 return ERROR_FUNCTION_FAILED
;
156 jv
->left
->ops
->close( jv
->left
);
157 jv
->right
->ops
->close( jv
->right
);
159 return ERROR_SUCCESS
;
162 static UINT
JOIN_get_dimensions( struct tagMSIVIEW
*view
, UINT
*rows
, UINT
*cols
)
164 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
166 TRACE("%p %p %p\n", jv
, rows
, cols
);
169 *cols
= jv
->left_count
+ jv
->right_count
;
173 if( !jv
->left
|| !jv
->right
)
174 return ERROR_FUNCTION_FAILED
;
176 *rows
= jv
->left_rows
* jv
->right_rows
;
179 return ERROR_SUCCESS
;
182 static UINT
JOIN_get_column_info( struct tagMSIVIEW
*view
,
183 UINT n
, LPWSTR
*name
, UINT
*type
)
185 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
187 TRACE("%p %d %p %p\n", jv
, n
, name
, type
);
189 if( !jv
->left
|| !jv
->right
)
190 return ERROR_FUNCTION_FAILED
;
192 if( (n
==0) || (n
>(jv
->left_count
+ jv
->right_count
)) )
193 return ERROR_FUNCTION_FAILED
;
195 if( n
<= jv
->left_count
)
196 return jv
->left
->ops
->get_column_info( jv
->left
, n
, name
, type
);
198 n
= n
- jv
->left_count
;
200 return jv
->right
->ops
->get_column_info( jv
->right
, n
, name
, type
);
203 static UINT
JOIN_modify( struct tagMSIVIEW
*view
, MSIMODIFY eModifyMode
,
206 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
208 TRACE("%p %d %p\n", jv
, eModifyMode
, rec
);
210 return ERROR_FUNCTION_FAILED
;
213 static UINT
JOIN_delete( struct tagMSIVIEW
*view
)
215 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
220 jv
->left
->ops
->delete( jv
->left
);
224 jv
->right
->ops
->delete( jv
->right
);
229 return ERROR_SUCCESS
;
232 static UINT
JOIN_find_matching_rows( struct tagMSIVIEW
*view
, UINT col
,
233 UINT val
, UINT
*row
, MSIITERHANDLE
*handle
)
235 MSIJOINVIEW
*jv
= (MSIJOINVIEW
*)view
;
237 FIXME("%p, %d, %u, %p\n", jv
, col
, val
, *handle
);
239 return ERROR_FUNCTION_FAILED
;
242 static const MSIVIEWOPS join_ops
=
251 JOIN_get_column_info
,
254 JOIN_find_matching_rows
257 UINT
JOIN_CreateView( MSIDATABASE
*db
, MSIVIEW
**view
,
258 LPCWSTR left
, LPCWSTR right
)
260 MSIJOINVIEW
*jv
= NULL
;
261 UINT r
= ERROR_SUCCESS
;
263 TRACE("%p (%s,%s)\n", jv
, debugstr_w(left
), debugstr_w(right
) );
265 jv
= msi_alloc_zero( sizeof *jv
);
267 return ERROR_FUNCTION_FAILED
;
269 /* fill the structure */
270 jv
->view
.ops
= &join_ops
;
273 /* create the tables to join */
274 r
= TABLE_CreateView( db
, left
, &jv
->left
);
275 if( r
!= ERROR_SUCCESS
)
277 ERR("can't create left table\n");
281 r
= TABLE_CreateView( db
, right
, &jv
->right
);
282 if( r
!= ERROR_SUCCESS
)
284 ERR("can't create right table\n");
288 /* get the number of columns in each table */
289 r
= jv
->left
->ops
->get_dimensions( jv
->left
, NULL
, &jv
->left_count
);
290 if( r
!= ERROR_SUCCESS
)
292 ERR("can't get left table dimensions\n");
296 r
= jv
->right
->ops
->get_dimensions( jv
->right
, NULL
, &jv
->right_count
);
297 if( r
!= ERROR_SUCCESS
)
299 ERR("can't get right table dimensions\n");
304 return ERROR_SUCCESS
;
307 jv
->view
.ops
->delete( &jv
->view
);