MSI: implement SQL delete query

Mike McCormack mike at codeweavers.com
Sun Feb 13 23:15:02 CST 2005


ChangeLog:
* implement SQL delete query
-------------- next part --------------
Index: dlls/msi/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/msi/Makefile.in,v
retrieving revision 1.23
diff -u -p -r1.23 Makefile.in
--- dlls/msi/Makefile.in	8 Feb 2005 12:12:29 -0000	1.23
+++ dlls/msi/Makefile.in	14 Feb 2005 05:13:18 -0000
@@ -11,6 +11,7 @@ C_SRCS = \
 	appsearch.c \
 	create.c \
 	custom.c \
+	delete.c \
 	dialog.c \
 	distinct.c \
 	format.c \
Index: dlls/msi/query.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/query.h,v
retrieving revision 1.12
diff -u -p -r1.12 query.h
--- dlls/msi/query.h	22 Dec 2004 15:22:12 -0000	1.12
+++ dlls/msi/query.h	14 Feb 2005 05:13:18 -0000
@@ -131,6 +131,8 @@ UINT INSERT_CreateView( MSIDATABASE *db,
 UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **, LPWSTR table,
                         column_assignment *list, struct expr *expr );
 
+UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table );
+
 void delete_expr( struct expr *e );
 void delete_string_list( string_list *sl );
 void delete_value_list( value_list *vl );
Index: dlls/msi/sql.y
===================================================================
RCS file: /home/wine/wine/dlls/msi/sql.y,v
retrieving revision 1.20
diff -u -p -r1.20 sql.y
--- dlls/msi/sql.y	20 Jan 2005 20:39:15 -0000	1.20
+++ dlls/msi/sql.y	14 Feb 2005 05:13:19 -0000
@@ -129,7 +129,8 @@ static struct expr * EXPR_wildcard();
 
 %type <string> column table string_or_id
 %type <column_list> selcollist
-%type <query> from unorderedsel oneselect onequery onecreate oneinsert oneupdate
+%type <query> from unorderedsel oneselect onequery onecreate oneinsert
+%type <query> oneupdate onedelete
 %type <expr> expr val column_val const_val
 %type <column_type> column_type data_type data_type_l data_count
 %type <column_info> column_def table_def
@@ -159,6 +160,11 @@ onequery:
         SQL_input* sql = (SQL_input*) info;
         *sql->view = $1;
     }
+  | onedelete
+    {
+        SQL_input* sql = (SQL_input*) info;
+        *sql->view = $1;
+    }
     ;
 
 oneinsert:
@@ -211,6 +217,17 @@ oneupdate:
 
             UPDATE_CreateView( sql->db, &update, $2, &$4, $6 );
             $$ = update;
+        }
+    ;
+
+onedelete:
+    TK_DELETE from
+        {
+            SQL_input* sql = (SQL_input*) info;
+            MSIVIEW *delete = NULL; 
+
+            DELETE_CreateView( sql->db, &delete, $2 );
+            $$ = delete;
         }
     ;
 
--- /dev/null	2004-12-26 03:00:47.000000000 +0900
+++ dlls/msi/delete.c	2005-02-14 14:06:50.000000000 +0900
@@ -0,0 +1,218 @@
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2002-2005 Mike McCormack for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "wine/debug.h"
+#include "msi.h"
+#include "msiquery.h"
+#include "objbase.h"
+#include "objidl.h"
+#include "msipriv.h"
+#include "winnls.h"
+
+#include "query.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+
+/*
+ * Code to delete rows from a table.
+ *
+ * We delete rows by blanking them out rather than trying to remove the row.
+ * This appears to be what the native MSI does (or tries to do). For the query:
+ *
+ * delete from Property
+ *
+ * some non-zero entries are left in the table by native MSI.  I'm not sure if
+ * that's a bug in the way I'm running the query, or a just a bug.
+ */
+
+typedef struct tagMSIDELETEVIEW
+{
+    MSIVIEW        view;
+    MSIDATABASE   *db;
+    MSIVIEW       *table;
+} MSIDELETEVIEW;
+
+static UINT DELETE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p %d %d %p\n", dv, row, col, val );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT DELETE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p %d %d %p\n", dv, row, col, stm );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT DELETE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p %d %d %04x\n", dv, row, col, val );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT DELETE_insert_row( struct tagMSIVIEW *view, UINT *num )  
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p %p\n", dv, num );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+    UINT r, i, j, rows = 0, cols = 0;
+
+    TRACE("%p %p\n", dv, record);
+
+    if( !dv->table )
+         return ERROR_FUNCTION_FAILED;
+
+    r = dv->table->ops->execute( dv->table, record );
+    if( r != ERROR_SUCCESS )
+        return r;
+
+    r = dv->table->ops->get_dimensions( dv->table, &rows, &cols );
+    if( r != ERROR_SUCCESS )
+        return r;
+
+    TRACE("blanking %d rows\n", rows); 
+
+    /* blank out all the rows that match */
+    for( i=0; i<rows; i++ )
+        for( j=1; j<=cols; j++ )
+            dv->table->ops->set_int( dv->table, i, j, 0 );
+
+    return ERROR_SUCCESS;
+}
+
+static UINT DELETE_close( struct tagMSIVIEW *view )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p\n", dv );
+
+    if( !dv->table )
+         return ERROR_FUNCTION_FAILED;
+
+    return dv->table->ops->close( dv->table );
+}
+
+static UINT DELETE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p %p %p\n", dv, rows, cols );
+
+    if( !dv->table )
+         return ERROR_FUNCTION_FAILED;
+
+    *rows = 0;
+
+    return dv->table->ops->get_dimensions( dv->table, NULL, cols );
+}
+
+static UINT DELETE_get_column_info( struct tagMSIVIEW *view,
+                UINT n, LPWSTR *name, UINT *type )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p %d %p %p\n", dv, n, name, type );
+
+    if( !dv->table )
+         return ERROR_FUNCTION_FAILED;
+
+    return dv->table->ops->get_column_info( dv->table, n, name, type );
+}
+
+static UINT DELETE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
+                MSIRECORD *rec )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p %d %p\n", dv, eModifyMode, rec );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT DELETE_delete( struct tagMSIVIEW *view )
+{
+    MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
+
+    TRACE("%p\n", dv );
+
+    if( dv->table )
+        dv->table->ops->delete( dv->table );
+
+    HeapFree( GetProcessHeap(), 0, dv );
+
+    return ERROR_SUCCESS;
+}
+
+
+MSIVIEWOPS delete_ops =
+{
+    DELETE_fetch_int,
+    DELETE_fetch_stream,
+    DELETE_set_int,
+    DELETE_insert_row,
+    DELETE_execute,
+    DELETE_close,
+    DELETE_get_dimensions,
+    DELETE_get_column_info,
+    DELETE_modify,
+    DELETE_delete
+};
+
+UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
+{
+    MSIDELETEVIEW *dv = NULL;
+
+    TRACE("%p\n", dv );
+
+    dv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *dv );
+    if( !dv )
+        return ERROR_FUNCTION_FAILED;
+    
+    /* fill the structure */
+    dv->view.ops = &delete_ops;
+    dv->db = db;
+    dv->table = table;
+
+    *view = &dv->view;
+
+    return ERROR_SUCCESS;
+}


More information about the wine-patches mailing list