In order to avoid the need to create a temporary record and copy values back and forth.
Signed-off-by: Zebediah Figura z.figura12@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,