MSI: start implementing the SQL insert query

Mike McCormack mike at codeweavers.com
Fri Mar 19 20:41:12 CST 2004


ChangeLog:
* start implementing the SQL insert query
-------------- next part --------------
? dlls/msi/insert.c
Index: dlls/msi/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/msi/Makefile.in,v
retrieving revision 1.8
diff -u -r1.8 Makefile.in
--- dlls/msi/Makefile.in	17 Mar 2004 20:49:59 -0000	1.8
+++ dlls/msi/Makefile.in	20 Mar 2004 01:54:36 -0000
@@ -10,6 +10,7 @@
 	create.c \
 	distinct.c \
 	handle.c \
+	insert.c \
 	msi.c \
 	msiquery.c \
 	order.c \
Index: dlls/msi/query.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/query.h,v
retrieving revision 1.5
diff -u -r1.5 query.h
--- dlls/msi/query.h	19 Mar 2004 01:16:36 -0000	1.5
+++ dlls/msi/query.h	20 Mar 2004 01:54:38 -0000
@@ -49,6 +49,12 @@
 #define EXPR_SVAL     5
 #define EXPR_UVAL     6
 
+typedef struct _string_list
+{
+    LPWSTR string;
+    struct _string_list *next;
+} string_list;
+
 struct complex_expr
 {
     UINT op;
@@ -77,6 +83,12 @@
     struct _create_col_info *next;
 } create_col_info;
 
+typedef struct _value_list
+{
+    struct expr *val;
+    struct _value_list *next;
+} value_list;
+
 UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phView);
 
 UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view );
@@ -94,6 +106,13 @@
 
 UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
                         create_col_info *col_info, BOOL temp );
+
+UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
+                        string_list *columns, value_list *values, BOOL temp );
+
+void delete_expr( struct expr *e );
+void delete_string_list( string_list *sl );
+void delete_value_list( value_list *vl );
 
 int sqliteGetToken(const WCHAR *z, int *tokenType);
 
Index: dlls/msi/sql.y
===================================================================
RCS file: /home/wine/wine/dlls/msi/sql.y,v
retrieving revision 1.7
diff -u -r1.7 sql.y
--- dlls/msi/sql.y	19 Mar 2004 01:16:36 -0000	1.7
+++ dlls/msi/sql.y	20 Mar 2004 01:54:38 -0000
@@ -48,23 +48,17 @@
     MSIVIEW **view;  /* view structure for the resulting query */
 } SQL_input;
 
-struct string_list
-{
-    LPWSTR string;
-    struct string_list *next;
-};
-
 static LPWSTR SQL_getstring( SQL_input *info );
 static INT SQL_getint( SQL_input *sql );
 static int SQL_lex( void *SQL_lval, SQL_input *info);
 
 static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, 
-                        struct string_list *columns );
+                               string_list *columns );
 static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, 
-                               struct string_list *columns );
+                             string_list *columns );
 
 static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
-                                 struct string_list *keys);
+                                 string_list *keys);
 
 static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r );
 static struct expr * EXPR_column( LPWSTR column );
@@ -78,7 +72,8 @@
 %union
 {
     LPWSTR string;
-    struct string_list *column_list;
+    string_list *column_list;
+    value_list *val_list;
     MSIVIEW *query;
     struct expr *expr;
     USHORT column_type;
@@ -129,10 +124,11 @@
 
 %type <string> column table string_or_id
 %type <column_list> selcollist
-%type <query> from unorderedsel oneselect onequery onecreate
-%type <expr> expr val column_val
+%type <query> from unorderedsel oneselect onequery onecreate oneinsert
+%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
+%type <val_list> constlist
 
 %%
 
@@ -147,6 +143,30 @@
         SQL_input* sql = (SQL_input*) info;
         *sql->view = $1;
     }
+  | oneinsert
+    {
+        SQL_input* sql = (SQL_input*) info;
+        *sql->view = $1;
+    }
+    ;
+
+oneinsert:
+    TK_INSERT TK_INTO table selcollist TK_VALUES constlist
+    {
+        SQL_input *sql = (SQL_input*) info;
+        MSIVIEW *insert = NULL; 
+
+        INSERT_CreateView( sql->db, &insert, $3, $4, $6, FALSE ); 
+        $$ = insert;
+    }
+  | TK_INSERT TK_INTO table selcollist TK_VALUES constlist TK_TEMP
+    {
+        SQL_input *sql = (SQL_input*) info;
+        MSIVIEW *insert = NULL; 
+
+        INSERT_CreateView( sql->db, &insert, $3, $4, $6, TRUE ); 
+        $$ = insert;
+    }
     ;
 
 onecreate:
@@ -323,7 +343,7 @@
 selcollist:
     column 
         { 
-            struct string_list *list;
+            string_list *list;
 
             list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );
             if( !list )
@@ -336,7 +356,7 @@
         }
   | column TK_COMMA selcollist
         { 
-            struct string_list *list;
+            string_list *list;
 
             list = HeapAlloc( GetProcessHeap(), 0, sizeof *list );
             if( !list )
@@ -436,10 +456,39 @@
 
 val:
     column_val
+  | const_val
+        ;
+
+constlist:
+    const_val
+        {
+            value_list *vals;
+
+            vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );
+            if( vals )
+            {
+                vals->val = $1;
+                vals->next = NULL;
+            }
+            $$ = vals;
+        }
+  | constlist TK_COMMA const_val
         {
+            value_list *vals;
+
+            vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );
+            if( vals )
+            {
+                vals->val = $3;
+                vals->next = NULL;
+            }
+            $1->next = vals;
             $$ = $1;
         }
-  | TK_INTEGER
+        ;
+
+const_val:
+    TK_INTEGER
         {
             SQL_input* sql = (SQL_input*) info;
             $$ = EXPR_ival( SQL_getint(sql) );
@@ -546,18 +595,18 @@
 }
 
 static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, 
-                               struct string_list *columns )
+                               string_list *columns )
 {
     MSIVIEW *view = NULL;
 
     SELECT_CreateView( db, &view, in );
     if( view )
     {
-        struct string_list *x = columns;
+        string_list *x = columns;
 
         while( x )
         {
-            struct string_list *t = x->next;
+            string_list *t = x->next;
             SELECT_AddColumn( view, x->string );
             HeapFree( GetProcessHeap(), 0, x->string );
             HeapFree( GetProcessHeap(), 0, x );
@@ -570,26 +619,21 @@
 }
 
 static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, 
-                               struct string_list *columns )
+                             string_list *columns )
 {
     MSIVIEW *view = NULL;
 
     ORDER_CreateView( db, &view, in );
     if( view )
     {
-        struct string_list *x = columns;
+        string_list *x = columns;
 
-        while( x )
-        {
-            struct string_list *t = x->next;
+        for( x = columns; x ; x = x->next )
             ORDER_AddColumn( view, x->string );
-            HeapFree( GetProcessHeap(), 0, x->string );
-            HeapFree( GetProcessHeap(), 0, x );
-            x = t;
-        }
     }
     else
         ERR("Error creating select query\n");
+    delete_string_list( columns );
     return view;
 }
 
@@ -639,10 +683,44 @@
     return e;
 }
 
+void delete_expr( struct expr *e )
+{
+    if( !e )
+        return;
+    if( e->type == EXPR_COMPLEX )
+    {
+        delete_expr( e->u.expr.left );
+        delete_expr( e->u.expr.right );
+    }
+    HeapFree( GetProcessHeap(), 0, e );
+}
+
+void delete_string_list( string_list *sl )
+{
+    while( sl )
+    {
+        string_list *t = sl->next;
+        HeapFree( GetProcessHeap(), 0, sl->string );
+        HeapFree( GetProcessHeap(), 0, sl );
+        sl = t;
+    }
+}
+
+void delete_value_list( value_list *vl )
+{
+    while( vl )
+    {
+        value_list *t = vl->next;
+        delete_expr( vl->val );
+        HeapFree( GetProcessHeap(), 0, vl );
+        vl = t;
+    }
+}
+
 static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
-                                 struct string_list *keys )
+                                 string_list *keys )
 {
-    struct string_list *k;
+    string_list *k;
     BOOL found = TRUE;
 
     for( k = keys; k && found; k = k->next )
Index: dlls/msi/where.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/where.c,v
retrieving revision 1.4
diff -u -r1.4 where.c
--- dlls/msi/where.c	19 Mar 2004 01:16:36 -0000	1.4
+++ dlls/msi/where.c	20 Mar 2004 01:54:38 -0000
@@ -231,18 +231,6 @@
     return wv->table->ops->modify( wv->table, eModifyMode, hrec );
 }
 
-static void WHERE_delete_expr( struct expr *e )
-{
-    if( !e )
-        return;
-    if( e->type == EXPR_COMPLEX )
-    {
-        WHERE_delete_expr( e->u.expr.left );
-        WHERE_delete_expr( e->u.expr.right );
-    }
-    HeapFree( GetProcessHeap(), 0, e );
-}
-
 static UINT WHERE_delete( struct tagMSIVIEW *view )
 {
     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
@@ -257,7 +245,7 @@
     wv->reorder = NULL;
     wv->row_count = 0;
 
-    WHERE_delete_expr( wv->cond );
+    delete_expr( wv->cond );
 
     HeapFree( GetProcessHeap(), 0, wv );
 
@@ -378,7 +366,7 @@
     TRACE("condition is %s\n", valid ? "valid" : "invalid" );
     if( !valid )
     {
-        WHERE_delete_expr( cond );
+        delete_expr( cond );
         return ERROR_FUNCTION_FAILED;
     }
 
--- /dev/null	1994-07-18 08:46:18.000000000 +0900
+++ dlls/msi/insert.c	2004-03-20 11:40:08.000000000 +0900
@@ -0,0 +1,247 @@
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2004 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);
+
+
+/* below is the query interface to a table */
+
+typedef struct tagMSIINSERTVIEW
+{
+    MSIVIEW          view;
+    MSIDATABASE     *db;
+    LPWSTR           name;
+    BOOL             bIsTemp;
+    string_list     *cols;
+    value_list      *vals;
+} MSIINSERTVIEW;
+
+static UINT INSERT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
+{
+    MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
+
+    TRACE("%p %d %d %p\n", iv, row, col, val );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT INSERT_execute( struct tagMSIVIEW *view, MSIHANDLE record )
+{
+#if 0
+    MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
+    create_col_info *col;
+    UINT r, nField, row, table_val, column_val;
+    const WCHAR szTables[] =  { '_','T','a','b','l','e','s',0 };
+    const WCHAR szColumns[] = { '_','C','o','l','u','m','n','s',0 };
+    MSIVIEW *tv = NULL;
+
+    TRACE("%p Table %s (%s)\n", iv, debugstr_w(iv->name), 
+          iv->bIsTemp?"temporary":"permanent");
+
+    /* only add tables that don't exist already */
+    if( TABLE_Exists(iv->db, iv->name ) )
+        return ERROR_BAD_QUERY_SYNTAX;
+
+    /* add the name to the _Tables table */
+    table_val = msi_addstringW( iv->db->strings, 0, iv->name, -1, 1 );
+    TRACE("New string %s -> %d\n", debugstr_w( iv->name ), table_val );
+    if( table_val < 0 )
+        return ERROR_FUNCTION_FAILED;
+
+    r = TABLE_CreateView( iv->db, szTables, &tv );
+    TRACE("CreateView returned %x\n", r);
+    if( r )
+        return r;
+
+    r = tv->ops->execute( tv, 0 );
+    TRACE("tv execute returned %x\n", r);
+    if( r )
+        return r;
+
+    row = -1;
+    r = tv->ops->insert_row( tv, &row );
+    TRACE("insert_row returned %x\n", r);
+    if( r )
+        goto err;
+
+    r = tv->ops->set_int( tv, row, 1, table_val );
+    if( r )
+        goto err;
+    tv->ops->delete( tv );
+    tv = NULL;
+
+    /* add each column to the _Columns table */
+    r = TABLE_CreateView( iv->db, szColumns, &tv );
+    if( r )
+        return r;
+
+    r = tv->ops->execute( tv, 0 );
+    TRACE("tv execute returned %x\n", r);
+    if( r )
+        return r;
+
+    /*
+     * need to set the table, column number, col name and type
+     * for each column we enter in the table
+     */
+    nField = 1;
+    for( col = iv->col_info; col; col = col->next )
+    {
+        row = -1;
+        r = tv->ops->insert_row( tv, &row );
+        if( r )
+            goto err;
+
+        column_val = msi_addstringW( iv->db->strings, 0, col->colname, -1, 1 );
+        TRACE("New string %s -> %d\n", debugstr_w( col->colname ), column_val );
+        if( column_val < 0 )
+            break;
+
+        r = tv->ops->set_int( tv, row, 1, table_val );
+        if( r )
+            break;
+
+        r = tv->ops->set_int( tv, row, 2, 0x8000|nField );
+        if( r )
+            break;
+
+        r = tv->ops->set_int( tv, row, 3, column_val );
+        if( r )
+            break;
+
+        r = tv->ops->set_int( tv, row, 4, 0x8000|col->type );
+        if( r )
+            break;
+    }
+    if( !col )
+        r = ERROR_SUCCESS;
+
+err:
+    /* FIXME: remove values from the string table on error */
+    if( tv )
+        tv->ops->delete( tv );
+    return r;
+#else
+    return ERROR_FUNCTION_FAILED;
+#endif
+}
+
+static UINT INSERT_close( struct tagMSIVIEW *view )
+{
+    MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
+
+    TRACE("%p\n", iv);
+
+    return ERROR_SUCCESS;
+}
+
+static UINT INSERT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
+{
+    MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
+
+    TRACE("%p %p %p\n", iv, rows, cols );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT INSERT_get_column_info( struct tagMSIVIEW *view,
+                UINT n, LPWSTR *name, UINT *type )
+{
+    MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
+
+    TRACE("%p %d %p %p\n", iv, n, name, type );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec)
+{
+    MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
+
+    TRACE("%p %d %ld\n", iv, eModifyMode, hrec );
+
+    return ERROR_FUNCTION_FAILED;
+}
+
+static UINT INSERT_delete( struct tagMSIVIEW *view )
+{
+    MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
+
+    TRACE("%p\n", iv );
+
+    delete_string_list( iv->cols ); 
+    delete_value_list( iv->vals );
+    HeapFree( GetProcessHeap(), 0, iv->name );
+    HeapFree( GetProcessHeap(), 0, iv );
+
+    return ERROR_SUCCESS;
+}
+
+
+MSIVIEWOPS insert_ops =
+{
+    INSERT_fetch_int,
+    NULL,
+    NULL,
+    INSERT_execute,
+    INSERT_close,
+    INSERT_get_dimensions,
+    INSERT_get_column_info,
+    INSERT_modify,
+    INSERT_delete
+};
+
+UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
+                        string_list *columns, value_list *values, BOOL temp )
+{
+    MSIINSERTVIEW *iv = NULL;
+
+    TRACE("%p\n", iv );
+
+    iv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *iv );
+    if( !iv )
+        return ERROR_FUNCTION_FAILED;
+    
+    /* fill the structure */
+    iv->view.ops = &insert_ops;
+    iv->db = db;
+    iv->name = table;  /* FIXME: strdupW it? */
+    iv->cols = columns;
+    iv->vals = values;
+    iv->bIsTemp = temp;
+    *view = (MSIVIEW*) iv;
+
+    return ERROR_SUCCESS;
+}


More information about the wine-patches mailing list