[PATCH 2/5] msi: Set table values directly in msi_select_update().

Zebediah Figura z.figura12 at gmail.com
Sat Jan 26 16:58:58 CST 2019


In order to avoid the need to create a temporary record and copy values back
and forth.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/msi/alter.c    |  2 ++
 dlls/msi/create.c   |  2 ++
 dlls/msi/delete.c   |  2 ++
 dlls/msi/distinct.c |  2 ++
 dlls/msi/drop.c     |  2 ++
 dlls/msi/insert.c   |  2 ++
 dlls/msi/msipriv.h  | 14 +++++++++
 dlls/msi/select.c   | 26 ++++++-----------
 dlls/msi/storages.c |  8 +++++
 dlls/msi/streams.c  |  8 +++++
 dlls/msi/table.c    | 71 +++++++++++++++++++++++++++++++++++++++++++--
 dlls/msi/update.c   |  2 ++
 dlls/msi/where.c    | 42 +++++++++++++++++++++++++++
 13 files changed, 164 insertions(+), 19 deletions(-)

diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c
index 011a2dcfb8..96ff284a3d 100644
--- a/dlls/msi/alter.c
+++ b/dlls/msi/alter.c
@@ -229,6 +229,8 @@ static const MSIVIEWOPS alter_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
+    NULL,
     ALTER_execute,
     ALTER_close,
     ALTER_get_dimensions,
diff --git a/dlls/msi/create.c b/dlls/msi/create.c
index dd4739df12..2777954aa7 100644
--- a/dlls/msi/create.c
+++ b/dlls/msi/create.c
@@ -130,6 +130,8 @@ static const MSIVIEWOPS create_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
+    NULL,
     CREATE_execute,
     CREATE_close,
     CREATE_get_dimensions,
diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c
index 468115186b..81bd9d7db2 100644
--- a/dlls/msi/delete.c
+++ b/dlls/msi/delete.c
@@ -172,6 +172,8 @@ static const MSIVIEWOPS delete_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
+    NULL,
     DELETE_execute,
     DELETE_close,
     DELETE_get_dimensions,
diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c
index b1945a1546..e102adb3de 100644
--- a/dlls/msi/distinct.c
+++ b/dlls/msi/distinct.c
@@ -255,6 +255,8 @@ static const MSIVIEWOPS distinct_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
+    NULL,
     DISTINCT_execute,
     DISTINCT_close,
     DISTINCT_get_dimensions,
diff --git a/dlls/msi/drop.c b/dlls/msi/drop.c
index 3179f14219..89fac9dfc7 100644
--- a/dlls/msi/drop.c
+++ b/dlls/msi/drop.c
@@ -94,6 +94,8 @@ static UINT DROP_delete( struct tagMSIVIEW *view )
 
 static const MSIVIEWOPS drop_ops =
 {
+    NULL,
+    NULL,
     NULL,
     NULL,
     NULL,
diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c
index a5333c9cdc..f1185eebae 100644
--- a/dlls/msi/insert.c
+++ b/dlls/msi/insert.c
@@ -326,6 +326,8 @@ static const MSIVIEWOPS insert_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
+    NULL,
     INSERT_execute,
     INSERT_close,
     INSERT_get_dimensions,
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 1cbeae4af0..e9c000de58 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -248,6 +248,20 @@ typedef struct tagMSIVIEWOPS
      */
     UINT (*get_row)( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec );
 
+    /*
+     * set_int - set the integer value at {row, col}
+     * This function has undefined behaviour if the column does not contain
+     * integers.
+     */
+    UINT (*set_int)( struct tagMSIVIEW *view, UINT row, UINT col, int val );
+
+    /*
+     * set_string - set the string value at {row, col}
+     * This function has undefined behaviour if the column does not contain
+     * strings.
+     */
+    UINT (*set_string)( struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len );
+
     /*
      * set_row - sets values in a row as specified by mask
      *
diff --git a/dlls/msi/select.c b/dlls/msi/select.c
index e17cbbbdf2..91765c8ec3 100644
--- a/dlls/msi/select.c
+++ b/dlls/msi/select.c
@@ -247,16 +247,11 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
     MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
     UINT r, i, num_columns, col, type, val;
     LPCWSTR str;
-    MSIRECORD *mod;
 
     r = SELECT_get_dimensions(view, NULL, &num_columns);
     if (r != ERROR_SUCCESS)
         return r;
 
-    r = sv->table->ops->get_row(sv->table, row, &mod);
-    if (r != ERROR_SUCCESS)
-        return r;
-
     for (i = 0; i < num_columns; i++)
     {
         col = sv->cols[i];
@@ -265,39 +260,34 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
         if (r != ERROR_SUCCESS)
         {
             ERR("Failed to get column information: %d\n", r);
-            goto done;
+            return r;
         }
 
         if (MSITYPE_IS_BINARY(type))
         {
             ERR("Cannot modify binary data!\n");
-            r = ERROR_FUNCTION_FAILED;
-            goto done;
+            return ERROR_FUNCTION_FAILED;
         }
         else if (type & MSITYPE_STRING)
         {
             int len;
-            str = msi_record_get_string( rec, i + 1, &len );
-            r = msi_record_set_string( mod, col, str, len );
+            str = msi_record_get_string(rec, i + 1, &len);
+            r = sv->table->ops->set_string(sv->table, row, col, str, len);
         }
         else
         {
             val = MSI_RecordGetInteger(rec, i + 1);
-            r = MSI_RecordSetInteger(mod, col, val);
+            r = sv->table->ops->set_int(sv->table, row, col, val);
         }
 
         if (r != ERROR_SUCCESS)
         {
             ERR("Failed to modify record: %d\n", r);
-            goto done;
+            return r;
         }
     }
 
-    r = sv->table->ops->modify(sv->table, MSIMODIFY_UPDATE, mod, row);
-
-done:
-    msiobj_release(&mod->hdr);
-    return r;
+    return ERROR_SUCCESS;
 }
 
 static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
@@ -336,6 +326,8 @@ static const MSIVIEWOPS select_ops =
     SELECT_fetch_int,
     SELECT_fetch_stream,
     SELECT_get_row,
+    NULL,
+    NULL,
     SELECT_set_row,
     SELECT_insert_row,
     NULL,
diff --git a/dlls/msi/storages.c b/dlls/msi/storages.c
index 4379ae268b..ad020dec55 100644
--- a/dlls/msi/storages.c
+++ b/dlls/msi/storages.c
@@ -124,6 +124,12 @@ static UINT STORAGES_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec
     return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
+static UINT STORAGES_set_string( struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len )
+{
+    ERR("Cannot modify primary key.\n");
+    return ERROR_FUNCTION_FAILED;
+}
+
 static HRESULT stream_to_storage(IStream *stm, IStorage **stg)
 {
     ILockBytes *lockbytes = NULL;
@@ -420,6 +426,8 @@ static const MSIVIEWOPS storages_ops =
     STORAGES_fetch_int,
     STORAGES_fetch_stream,
     STORAGES_get_row,
+    NULL,
+    STORAGES_set_string,
     STORAGES_set_row,
     STORAGES_insert_row,
     STORAGES_delete_row,
diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c
index fc9f715bb6..ae45c1df8f 100644
--- a/dlls/msi/streams.c
+++ b/dlls/msi/streams.c
@@ -104,6 +104,12 @@ static UINT STREAMS_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IS
     return ERROR_SUCCESS;
 }
 
+static UINT STREAMS_set_string( struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len )
+{
+    ERR("Cannot modify primary key.\n");
+    return ERROR_FUNCTION_FAILED;
+}
+
 static UINT STREAMS_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
 {
     MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
@@ -342,6 +348,8 @@ static const MSIVIEWOPS streams_ops =
     STREAMS_fetch_int,
     STREAMS_fetch_stream,
     STREAMS_get_row,
+    NULL,
+    STREAMS_set_string,
     STREAMS_set_row,
     STREAMS_insert_row,
     STREAMS_delete_row,
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index e4f6b56f18..a5de8ccf59 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -1164,7 +1164,8 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
     return r;
 }
 
-static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val )
+/* Set a table value, i.e. preadjusted integer or string ID. */
+static UINT table_set_bytes( MSITABLEVIEW *tv, UINT row, UINT col, UINT val )
 {
     UINT offset, n, i;
 
@@ -1221,6 +1222,70 @@ static UINT int_to_table_storage( const MSITABLEVIEW *tv, UINT col, int val, UIN
     return ERROR_SUCCESS;
 }
 
+static UINT TABLE_set_int( MSIVIEW *view, UINT row, UINT col, int val )
+{
+    MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
+    UINT r, table_int;
+
+    TRACE("row %u, col %u, val %d.\n", row, col, val);
+
+    if ((r = int_to_table_storage( tv, col, val, &table_int )))
+        return r;
+
+    if (tv->columns[col-1].type & MSITYPE_KEY)
+    {
+        UINT key;
+
+        if ((r = TABLE_fetch_int( view, row, col, &key )))
+            return r;
+        if (key != table_int)
+        {
+            ERR("Cannot modify primary key %s.%s.\n",
+                debugstr_w(tv->table->name), debugstr_w(tv->columns[col-1].colname));
+            return ERROR_FUNCTION_FAILED;
+        }
+    }
+
+    return table_set_bytes( tv, row, col, table_int );
+}
+
+static UINT TABLE_set_string( MSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len )
+{
+    MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
+    BOOL persistent;
+    UINT id, r;
+
+    TRACE("row %u, col %u, val %s.\n", row, col, debugstr_wn(val, len));
+
+    persistent = (tv->table->persistent != MSICONDITION_FALSE)
+                  && tv->table->data_persistent[row];
+
+    if (val)
+    {
+        r = msi_string2id( tv->db->strings, val, len, &id );
+        if (r != ERROR_SUCCESS)
+            id = msi_add_string( tv->db->strings, val, len, persistent );
+    }
+    else
+        id = 0;
+
+    if (tv->columns[col-1].type & MSITYPE_KEY)
+    {
+        UINT key;
+
+        if ((r = TABLE_fetch_int( view, row, col, &key )))
+            return r;
+        if (key != id)
+        {
+            ERR("Cannot modify primary key %s.%s.\n",
+                debugstr_w(tv->table->name), debugstr_w(tv->columns[col-1].colname));
+            return ERROR_FUNCTION_FAILED;
+        }
+    }
+
+    return table_set_bytes( tv, row, col, id );
+}
+
 static UINT TABLE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
@@ -1402,7 +1467,7 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
             }
         }
 
-        r = TABLE_set_int( tv, row, i+1, val );
+        r = table_set_bytes( tv, row, i+1, val );
         if ( r != ERROR_SUCCESS )
             break;
     }
@@ -2060,6 +2125,8 @@ static const MSIVIEWOPS table_ops =
     TABLE_fetch_int,
     TABLE_fetch_stream,
     TABLE_get_row,
+    TABLE_set_int,
+    TABLE_set_string,
     TABLE_set_row,
     TABLE_insert_row,
     TABLE_delete_row,
diff --git a/dlls/msi/update.c b/dlls/msi/update.c
index ff4e1abf5f..e61342d11e 100644
--- a/dlls/msi/update.c
+++ b/dlls/msi/update.c
@@ -203,6 +203,8 @@ static const MSIVIEWOPS update_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
+    NULL,
     UPDATE_execute,
     UPDATE_close,
     UPDATE_get_dimensions,
diff --git a/dlls/msi/where.c b/dlls/msi/where.c
index 234ba5e008..6a10a049a6 100644
--- a/dlls/msi/where.c
+++ b/dlls/msi/where.c
@@ -271,6 +271,46 @@ static UINT WHERE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
     return msi_view_get_row( wv->db, view, row, rec );
 }
 
+static UINT WHERE_set_int(struct tagMSIVIEW *view, UINT row, UINT col, int val)
+{
+    MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
+    JOINTABLE *table;
+    UINT *rows;
+    UINT r;
+
+    TRACE("view %p, row %u, col %u, val %d.\n", wv, row, col, val );
+
+    r = find_row(wv, row, &rows);
+    if (r != ERROR_SUCCESS)
+        return r;
+
+    table = find_table(wv, col, &col);
+    if (!table)
+        return ERROR_FUNCTION_FAILED;
+
+    return table->view->ops->set_int(table->view, rows[table->table_index], col, val);
+}
+
+static UINT WHERE_set_string(struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
+{
+    MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
+    JOINTABLE *table;
+    UINT *rows;
+    UINT r;
+
+    TRACE("view %p, row %u, col %u, val %s.\n", wv, row, col, debugstr_wn(val, len));
+
+    r = find_row(wv, row, &rows);
+    if (r != ERROR_SUCCESS)
+        return r;
+
+    table = find_table(wv, col, &col);
+    if (!table)
+        return ERROR_FUNCTION_FAILED;
+
+    return table->view->ops->set_string(table->view, rows[table->table_index], col, val, len);
+}
+
 static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
 {
     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
@@ -1069,6 +1109,8 @@ static const MSIVIEWOPS where_ops =
     WHERE_fetch_int,
     WHERE_fetch_stream,
     WHERE_get_row,
+    WHERE_set_int,
+    WHERE_set_string,
     WHERE_set_row,
     NULL,
     WHERE_delete_row,
-- 
2.17.1




More information about the wine-devel mailing list