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

insert.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2004 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 "wine/unicode.h"
00028 #include "msi.h"
00029 #include "msiquery.h"
00030 #include "objbase.h"
00031 #include "objidl.h"
00032 #include "msipriv.h"
00033 #include "winnls.h"
00034 
00035 #include "query.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(msidb);
00038 
00039 
00040 /* below is the query interface to a table */
00041 
00042 typedef struct tagMSIINSERTVIEW
00043 {
00044     MSIVIEW          view;
00045     MSIVIEW         *table;
00046     MSIDATABASE     *db;
00047     BOOL             bIsTemp;
00048     MSIVIEW         *sv;
00049     column_info     *vals;
00050 } MSIINSERTVIEW;
00051 
00052 static UINT INSERT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
00053 {
00054     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
00055 
00056     TRACE("%p %d %d %p\n", iv, row, col, val );
00057 
00058     return ERROR_FUNCTION_FAILED;
00059 }
00060 
00061 /*
00062  * msi_query_merge_record
00063  *
00064  * Merge a value_list and a record to create a second record.
00065  * Replace wildcard entries in the valuelist with values from the record
00066  */
00067 MSIRECORD *msi_query_merge_record( UINT fields, const column_info *vl, MSIRECORD *rec )
00068 {
00069     MSIRECORD *merged;
00070     DWORD wildcard_count = 1, i;
00071 
00072     merged = MSI_CreateRecord( fields );
00073     for( i=1; i <= fields; i++ )
00074     {
00075         if( !vl )
00076         {
00077             TRACE("Not enough elements in the list to insert\n");
00078             goto err;
00079         }
00080         switch( vl->val->type )
00081         {
00082         case EXPR_SVAL:
00083             TRACE("field %d -> %s\n", i, debugstr_w(vl->val->u.sval));
00084             MSI_RecordSetStringW( merged, i, vl->val->u.sval );
00085             break;
00086         case EXPR_IVAL:
00087             MSI_RecordSetInteger( merged, i, vl->val->u.ival );
00088             break;
00089         case EXPR_WILDCARD:
00090             if( !rec )
00091                 goto err;
00092             MSI_RecordCopyField( rec, wildcard_count, merged, i );
00093             wildcard_count++;
00094             break;
00095         default:
00096             ERR("Unknown expression type %d\n", vl->val->type);
00097         }
00098         vl = vl->next;
00099     }
00100 
00101     return merged;
00102 err:
00103     msiobj_release( &merged->hdr );
00104     return NULL;
00105 }
00106 
00107 /* checks to see if the column order specified in the INSERT query
00108  * matches the column order of the table
00109  */
00110 static BOOL msi_columns_in_order(MSIINSERTVIEW *iv, UINT col_count)
00111 {
00112     LPCWSTR a, b;
00113     UINT i;
00114 
00115     for (i = 1; i <= col_count; i++)
00116     {
00117         iv->sv->ops->get_column_info(iv->sv, i, &a, NULL, NULL, NULL);
00118         iv->table->ops->get_column_info(iv->table, i, &b, NULL, NULL, NULL);
00119 
00120         if (strcmpW( a, b )) return FALSE;
00121     }
00122     return TRUE;
00123 }
00124 
00125 /* rearranges the data in the record to be inserted based on column order,
00126  * and pads the record for any missing columns in the INSERT query
00127  */
00128 static UINT msi_arrange_record(MSIINSERTVIEW *iv, MSIRECORD **values)
00129 {
00130     MSIRECORD *padded;
00131     UINT col_count, val_count;
00132     UINT r, i, colidx;
00133     LPCWSTR a, b;
00134 
00135     r = iv->table->ops->get_dimensions(iv->table, NULL, &col_count);
00136     if (r != ERROR_SUCCESS)
00137         return r;
00138 
00139     val_count = MSI_RecordGetFieldCount(*values);
00140 
00141     /* check to see if the columns are arranged already
00142      * to avoid unnecessary copying
00143      */
00144     if (col_count == val_count && msi_columns_in_order(iv, col_count))
00145         return ERROR_SUCCESS;
00146 
00147     padded = MSI_CreateRecord(col_count);
00148     if (!padded)
00149         return ERROR_OUTOFMEMORY;
00150 
00151     for (colidx = 1; colidx <= val_count; colidx++)
00152     {
00153         r = iv->sv->ops->get_column_info(iv->sv, colidx, &a, NULL, NULL, NULL);
00154         if (r != ERROR_SUCCESS)
00155             goto err;
00156 
00157         for (i = 1; i <= col_count; i++)
00158         {
00159             r = iv->table->ops->get_column_info(iv->table, i, &b, NULL,
00160                                                 NULL, NULL);
00161             if (r != ERROR_SUCCESS)
00162                 goto err;
00163 
00164             if (!strcmpW( a, b ))
00165             {
00166                 MSI_RecordCopyField(*values, colidx, padded, i);
00167                 break;
00168             }
00169         }
00170     }
00171     msiobj_release(&(*values)->hdr);
00172     *values = padded;
00173     return ERROR_SUCCESS;
00174 
00175 err:
00176     msiobj_release(&padded->hdr);
00177     return r;
00178 }
00179 
00180 static BOOL row_has_null_primary_keys(MSIINSERTVIEW *iv, MSIRECORD *row)
00181 {
00182     UINT r, i, col_count, type;
00183 
00184     r = iv->table->ops->get_dimensions( iv->table, NULL, &col_count );
00185     if (r != ERROR_SUCCESS)
00186         return FALSE;
00187 
00188     for (i = 1; i <= col_count; i++)
00189     {
00190         r = iv->table->ops->get_column_info(iv->table, i, NULL, &type,
00191                                             NULL, NULL);
00192         if (r != ERROR_SUCCESS)
00193             return FALSE;
00194 
00195         if (!(type & MSITYPE_KEY))
00196             continue;
00197 
00198         if (MSI_RecordIsNull(row, i))
00199             return TRUE;
00200     }
00201 
00202     return FALSE;
00203 }
00204 
00205 static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
00206 {
00207     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
00208     UINT r, row = -1, col_count = 0;
00209     MSIVIEW *sv;
00210     MSIRECORD *values = NULL;
00211 
00212     TRACE("%p %p\n", iv, record );
00213 
00214     sv = iv->sv;
00215     if( !sv )
00216         return ERROR_FUNCTION_FAILED;
00217 
00218     r = sv->ops->execute( sv, 0 );
00219     TRACE("sv execute returned %x\n", r);
00220     if( r )
00221         return r;
00222 
00223     r = sv->ops->get_dimensions( sv, NULL, &col_count );
00224     if( r )
00225         goto err;
00226 
00227     /*
00228      * Merge the wildcard values into the list of values provided
00229      * in the query, and create a record containing both.
00230      */
00231     values = msi_query_merge_record( col_count, iv->vals, record );
00232     if( !values )
00233         goto err;
00234 
00235     r = msi_arrange_record( iv, &values );
00236     if( r != ERROR_SUCCESS )
00237         goto err;
00238 
00239     /* rows with NULL primary keys are inserted at the beginning of the table */
00240     if( row_has_null_primary_keys( iv, values ) )
00241         row = 0;
00242 
00243     r = iv->table->ops->insert_row( iv->table, values, row, iv->bIsTemp );
00244 
00245 err:
00246     if( values )
00247         msiobj_release( &values->hdr );
00248 
00249     return r;
00250 }
00251 
00252 
00253 static UINT INSERT_close( struct tagMSIVIEW *view )
00254 {
00255     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
00256     MSIVIEW *sv;
00257 
00258     TRACE("%p\n", iv);
00259 
00260     sv = iv->sv;
00261     if( !sv )
00262         return ERROR_FUNCTION_FAILED;
00263 
00264     return sv->ops->close( sv );
00265 }
00266 
00267 static UINT INSERT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
00268 {
00269     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
00270     MSIVIEW *sv;
00271 
00272     TRACE("%p %p %p\n", iv, rows, cols );
00273 
00274     sv = iv->sv;
00275     if( !sv )
00276         return ERROR_FUNCTION_FAILED;
00277 
00278     return sv->ops->get_dimensions( sv, rows, cols );
00279 }
00280 
00281 static UINT INSERT_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name,
00282                                     UINT *type, BOOL *temporary, LPCWSTR *table_name )
00283 {
00284     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
00285     MSIVIEW *sv;
00286 
00287     TRACE("%p %d %p %p %p %p\n", iv, n, name, type, temporary, table_name );
00288 
00289     sv = iv->sv;
00290     if( !sv )
00291         return ERROR_FUNCTION_FAILED;
00292 
00293     return sv->ops->get_column_info( sv, n, name, type, temporary, table_name );
00294 }
00295 
00296 static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
00297 {
00298     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
00299 
00300     TRACE("%p %d %p\n", iv, eModifyMode, rec );
00301 
00302     return ERROR_FUNCTION_FAILED;
00303 }
00304 
00305 static UINT INSERT_delete( struct tagMSIVIEW *view )
00306 {
00307     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
00308     MSIVIEW *sv;
00309 
00310     TRACE("%p\n", iv );
00311 
00312     sv = iv->sv;
00313     if( sv )
00314         sv->ops->delete( sv );
00315     msiobj_release( &iv->db->hdr );
00316     msi_free( iv );
00317 
00318     return ERROR_SUCCESS;
00319 }
00320 
00321 static UINT INSERT_find_matching_rows( struct tagMSIVIEW *view, UINT col,
00322     UINT val, UINT *row, MSIITERHANDLE *handle )
00323 {
00324     TRACE("%p, %d, %u, %p\n", view, col, val, *handle);
00325 
00326     return ERROR_FUNCTION_FAILED;
00327 }
00328 
00329 
00330 static const MSIVIEWOPS insert_ops =
00331 {
00332     INSERT_fetch_int,
00333     NULL,
00334     NULL,
00335     NULL,
00336     NULL,
00337     NULL,
00338     INSERT_execute,
00339     INSERT_close,
00340     INSERT_get_dimensions,
00341     INSERT_get_column_info,
00342     INSERT_modify,
00343     INSERT_delete,
00344     INSERT_find_matching_rows,
00345     NULL,
00346     NULL,
00347     NULL,
00348     NULL,
00349     NULL,
00350     NULL,
00351 };
00352 
00353 static UINT count_column_info( const column_info *ci )
00354 {
00355     UINT n = 0;
00356     for ( ; ci; ci = ci->next )
00357         n++;
00358     return n;
00359 }
00360 
00361 UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
00362                         column_info *columns, column_info *values, BOOL temp )
00363 {
00364     MSIINSERTVIEW *iv = NULL;
00365     UINT r;
00366     MSIVIEW *tv = NULL, *sv = NULL;
00367 
00368     TRACE("%p\n", iv );
00369 
00370     /* there should be one value for each column */
00371     if ( count_column_info( columns ) != count_column_info(values) )
00372         return ERROR_BAD_QUERY_SYNTAX;
00373 
00374     r = TABLE_CreateView( db, table, &tv );
00375     if( r != ERROR_SUCCESS )
00376         return r;
00377 
00378     r = SELECT_CreateView( db, &sv, tv, columns );
00379     if( r != ERROR_SUCCESS )
00380     {
00381         if( tv )
00382             tv->ops->delete( tv );
00383         return r;
00384     }
00385 
00386     iv = msi_alloc_zero( sizeof *iv );
00387     if( !iv )
00388         return ERROR_FUNCTION_FAILED;
00389 
00390     /* fill the structure */
00391     iv->view.ops = &insert_ops;
00392     msiobj_addref( &db->hdr );
00393     iv->table = tv;
00394     iv->db = db;
00395     iv->vals = values;
00396     iv->bIsTemp = temp;
00397     iv->sv = sv;
00398     *view = (MSIVIEW*) iv;
00399 
00400     return ERROR_SUCCESS;
00401 }

Generated on Sun May 27 2012 04:25:16 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.