Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendistinct.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of the Microsoft Installer (msi.dll) 00003 * 00004 * Copyright 2002 Mike McCormack for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 00023 #include "windef.h" 00024 #include "winbase.h" 00025 #include "winerror.h" 00026 #include "wine/debug.h" 00027 #include "msi.h" 00028 #include "msiquery.h" 00029 #include "objbase.h" 00030 #include "objidl.h" 00031 #include "msipriv.h" 00032 #include "winnls.h" 00033 00034 #include "query.h" 00035 00036 WINE_DEFAULT_DEBUG_CHANNEL(msidb); 00037 00038 typedef struct tagDISTINCTSET 00039 { 00040 UINT val; 00041 UINT count; 00042 UINT row; 00043 struct tagDISTINCTSET *nextrow; 00044 struct tagDISTINCTSET *nextcol; 00045 } DISTINCTSET; 00046 00047 typedef struct tagMSIDISTINCTVIEW 00048 { 00049 MSIVIEW view; 00050 MSIDATABASE *db; 00051 MSIVIEW *table; 00052 UINT row_count; 00053 UINT *translation; 00054 } MSIDISTINCTVIEW; 00055 00056 static DISTINCTSET ** distinct_insert( DISTINCTSET **x, UINT val, UINT row ) 00057 { 00058 /* horrible O(n) find */ 00059 while( *x ) 00060 { 00061 if( (*x)->val == val ) 00062 { 00063 (*x)->count++; 00064 return x; 00065 } 00066 x = &(*x)->nextrow; 00067 } 00068 00069 /* nothing found, so add one */ 00070 *x = msi_alloc( sizeof (DISTINCTSET) ); 00071 if( *x ) 00072 { 00073 (*x)->val = val; 00074 (*x)->count = 1; 00075 (*x)->row = row; 00076 (*x)->nextrow = NULL; 00077 (*x)->nextcol = NULL; 00078 } 00079 return x; 00080 } 00081 00082 static void distinct_free( DISTINCTSET *x ) 00083 { 00084 while( x ) 00085 { 00086 DISTINCTSET *next = x->nextrow; 00087 distinct_free( x->nextcol ); 00088 msi_free( x ); 00089 x = next; 00090 } 00091 } 00092 00093 static UINT DISTINCT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) 00094 { 00095 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00096 00097 TRACE("%p %d %d %p\n", dv, row, col, val ); 00098 00099 if( !dv->table ) 00100 return ERROR_FUNCTION_FAILED; 00101 00102 if( row >= dv->row_count ) 00103 return ERROR_INVALID_PARAMETER; 00104 00105 row = dv->translation[ row ]; 00106 00107 return dv->table->ops->fetch_int( dv->table, row, col, val ); 00108 } 00109 00110 static UINT DISTINCT_execute( struct tagMSIVIEW *view, MSIRECORD *record ) 00111 { 00112 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00113 UINT r, i, j, r_count, c_count; 00114 DISTINCTSET *rowset = NULL; 00115 00116 TRACE("%p %p\n", dv, record); 00117 00118 if( !dv->table ) 00119 return ERROR_FUNCTION_FAILED; 00120 00121 r = dv->table->ops->execute( dv->table, record ); 00122 if( r != ERROR_SUCCESS ) 00123 return r; 00124 00125 r = dv->table->ops->get_dimensions( dv->table, &r_count, &c_count ); 00126 if( r != ERROR_SUCCESS ) 00127 return r; 00128 00129 dv->translation = msi_alloc( r_count*sizeof(UINT) ); 00130 if( !dv->translation ) 00131 return ERROR_FUNCTION_FAILED; 00132 00133 /* build it */ 00134 for( i=0; i<r_count; i++ ) 00135 { 00136 DISTINCTSET **x = &rowset; 00137 00138 for( j=1; j<=c_count; j++ ) 00139 { 00140 UINT val = 0; 00141 r = dv->table->ops->fetch_int( dv->table, i, j, &val ); 00142 if( r != ERROR_SUCCESS ) 00143 { 00144 ERR("Failed to fetch int at %d %d\n", i, j ); 00145 distinct_free( rowset ); 00146 return r; 00147 } 00148 x = distinct_insert( x, val, i ); 00149 if( !*x ) 00150 { 00151 ERR("Failed to insert at %d %d\n", i, j ); 00152 distinct_free( rowset ); 00153 return ERROR_FUNCTION_FAILED; 00154 } 00155 if( j != c_count ) 00156 x = &(*x)->nextcol; 00157 } 00158 00159 /* check if it was distinct and if so, include it */ 00160 if( (*x)->row == i ) 00161 { 00162 TRACE("Row %d -> %d\n", dv->row_count, i); 00163 dv->translation[dv->row_count++] = i; 00164 } 00165 } 00166 00167 distinct_free( rowset ); 00168 00169 return ERROR_SUCCESS; 00170 } 00171 00172 static UINT DISTINCT_close( struct tagMSIVIEW *view ) 00173 { 00174 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00175 00176 TRACE("%p\n", dv ); 00177 00178 if( !dv->table ) 00179 return ERROR_FUNCTION_FAILED; 00180 00181 msi_free( dv->translation ); 00182 dv->translation = NULL; 00183 dv->row_count = 0; 00184 00185 return dv->table->ops->close( dv->table ); 00186 } 00187 00188 static UINT DISTINCT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols ) 00189 { 00190 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00191 00192 TRACE("%p %p %p\n", dv, rows, cols ); 00193 00194 if( !dv->table ) 00195 return ERROR_FUNCTION_FAILED; 00196 00197 if( rows ) 00198 { 00199 if( !dv->translation ) 00200 return ERROR_FUNCTION_FAILED; 00201 *rows = dv->row_count; 00202 } 00203 00204 return dv->table->ops->get_dimensions( dv->table, NULL, cols ); 00205 } 00206 00207 static UINT DISTINCT_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name, 00208 UINT *type, BOOL *temporary, LPCWSTR *table_name ) 00209 { 00210 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00211 00212 TRACE("%p %d %p %p %p %p\n", dv, n, name, type, temporary, table_name ); 00213 00214 if( !dv->table ) 00215 return ERROR_FUNCTION_FAILED; 00216 00217 return dv->table->ops->get_column_info( dv->table, n, name, 00218 type, temporary, table_name ); 00219 } 00220 00221 static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, 00222 MSIRECORD *rec, UINT row ) 00223 { 00224 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00225 00226 TRACE("%p %d %p\n", dv, eModifyMode, rec ); 00227 00228 if( !dv->table ) 00229 return ERROR_FUNCTION_FAILED; 00230 00231 return dv->table->ops->modify( dv->table, eModifyMode, rec, row ); 00232 } 00233 00234 static UINT DISTINCT_delete( struct tagMSIVIEW *view ) 00235 { 00236 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00237 00238 TRACE("%p\n", dv ); 00239 00240 if( dv->table ) 00241 dv->table->ops->delete( dv->table ); 00242 00243 msi_free( dv->translation ); 00244 msiobj_release( &dv->db->hdr ); 00245 msi_free( dv ); 00246 00247 return ERROR_SUCCESS; 00248 } 00249 00250 static UINT DISTINCT_find_matching_rows( struct tagMSIVIEW *view, UINT col, 00251 UINT val, UINT *row, MSIITERHANDLE *handle ) 00252 { 00253 MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view; 00254 UINT r; 00255 00256 TRACE("%p, %d, %u, %p\n", view, col, val, *handle); 00257 00258 if( !dv->table ) 00259 return ERROR_FUNCTION_FAILED; 00260 00261 r = dv->table->ops->find_matching_rows( dv->table, col, val, row, handle ); 00262 00263 if( *row > dv->row_count ) 00264 return ERROR_NO_MORE_ITEMS; 00265 00266 *row = dv->translation[ *row ]; 00267 00268 return r; 00269 } 00270 00271 static const MSIVIEWOPS distinct_ops = 00272 { 00273 DISTINCT_fetch_int, 00274 NULL, 00275 NULL, 00276 NULL, 00277 NULL, 00278 NULL, 00279 DISTINCT_execute, 00280 DISTINCT_close, 00281 DISTINCT_get_dimensions, 00282 DISTINCT_get_column_info, 00283 DISTINCT_modify, 00284 DISTINCT_delete, 00285 DISTINCT_find_matching_rows, 00286 NULL, 00287 NULL, 00288 NULL, 00289 NULL, 00290 NULL, 00291 NULL, 00292 }; 00293 00294 UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) 00295 { 00296 MSIDISTINCTVIEW *dv = NULL; 00297 UINT count = 0, r; 00298 00299 TRACE("%p\n", dv ); 00300 00301 r = table->ops->get_dimensions( table, NULL, &count ); 00302 if( r != ERROR_SUCCESS ) 00303 { 00304 ERR("can't get table dimensions\n"); 00305 return r; 00306 } 00307 00308 dv = msi_alloc_zero( sizeof *dv ); 00309 if( !dv ) 00310 return ERROR_FUNCTION_FAILED; 00311 00312 /* fill the structure */ 00313 dv->view.ops = &distinct_ops; 00314 msiobj_addref( &db->hdr ); 00315 dv->db = db; 00316 dv->table = table; 00317 dv->translation = NULL; 00318 dv->row_count = 0; 00319 *view = (MSIVIEW*) dv; 00320 00321 return ERROR_SUCCESS; 00322 } Generated on Sat May 26 2012 04:23:48 for ReactOS by
1.7.6.1
|