ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

distinct.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.