Module: wine Branch: master Commit: 15b47513a1926a103492e0774396119f57d2e8d5 URL: https://source.winehq.org/git/wine.git/?a=commit;h=15b47513a1926a103492e0774...
Author: Piotr Caban piotr@codeweavers.com Date: Tue Jun 30 05:40:41 2020 +0200
msi: Fix adding temporary columns.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Hans Leidekker hans@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msi/alter.c | 82 +--------------------------------------- dlls/msi/msipriv.h | 2 +- dlls/msi/table.c | 105 +++++++++++++++++++++++++++++++++++++++++----------- dlls/msi/tests/db.c | 10 ++++- 4 files changed, 95 insertions(+), 104 deletions(-)
diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c index 7922171ae2..78f1a3930c 100644 --- a/dlls/msi/alter.c +++ b/dlls/msi/alter.c @@ -61,85 +61,6 @@ static UINT ALTER_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt return ERROR_FUNCTION_FAILED; }
-static UINT ITERATE_columns(MSIRECORD *row, LPVOID param) -{ - (*(UINT *)param)++; - return ERROR_SUCCESS; -} - -static BOOL check_column_exists(MSIDATABASE *db, LPCWSTR table, LPCWSTR column) -{ - MSIQUERY *view; - MSIRECORD *rec; - UINT r; - - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','_','C','o','l','u','m','n','s','`',' ','W','H','E','R','E',' ', - '`','T','a','b','l','e','`','=',''','%','s',''',' ','A','N','D',' ', - '`','N','a','m','e','`','=',''','%','s',''',0 - }; - - r = MSI_OpenQuery(db, &view, query, table, column); - if (r != ERROR_SUCCESS) - return FALSE; - - r = MSI_ViewExecute(view, NULL); - if (r != ERROR_SUCCESS) - goto done; - - r = MSI_ViewFetch(view, &rec); - if (r == ERROR_SUCCESS) - msiobj_release(&rec->hdr); - -done: - msiobj_release(&view->hdr); - return (r == ERROR_SUCCESS); -} - -static UINT alter_add_column(MSIALTERVIEW *av) -{ - UINT r, colnum = 1; - MSIQUERY *view; - MSIVIEW *columns; - - static const WCHAR szColumns[] = {'_','C','o','l','u','m','n','s',0}; - static const WCHAR query[] = { - 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','_','C','o','l','u','m','n','s','`',' ','W','H','E','R','E',' ', - '`','T','a','b','l','e','`','=',''','%','s',''',' ','O','R','D','E','R',' ', - 'B','Y',' ','`','N','u','m','b','e','r','`',0 - }; - - r = TABLE_CreateView(av->db, szColumns, &columns); - if (r != ERROR_SUCCESS) - return r; - - if (check_column_exists(av->db, av->colinfo->table, av->colinfo->column)) - { - columns->ops->delete(columns); - return ERROR_BAD_QUERY_SYNTAX; - } - - r = MSI_OpenQuery(av->db, &view, query, av->colinfo->table, av->colinfo->column); - if (r == ERROR_SUCCESS) - { - r = MSI_IterateRecords(view, NULL, ITERATE_columns, &colnum); - msiobj_release(&view->hdr); - if (r != ERROR_SUCCESS) - { - columns->ops->delete(columns); - return r; - } - } - r = columns->ops->add_column(columns, av->colinfo->table, - colnum, av->colinfo->column, - av->colinfo->type, (av->hold == 1)); - - columns->ops->delete(columns); - return r; -} - static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIALTERVIEW *av = (MSIALTERVIEW*)view; @@ -148,7 +69,8 @@ static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record ) TRACE("%p %p\n", av, record);
if (av->colinfo) - return alter_add_column(av); + return av->table->ops->add_column(av->table, av->colinfo->column, + av->colinfo->type, av->colinfo->temporary, av->hold == 1);
if (av->hold == 1) av->table->ops->add_ref(av->table); diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 71c6565080..6797ebe4bc 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -337,7 +337,7 @@ typedef struct tagMSIVIEWOPS /* * add_column - adds a column to the table */ - UINT (*add_column)( struct tagMSIVIEW *view, LPCWSTR table, UINT number, LPCWSTR column, UINT type, BOOL hold ); + UINT (*add_column)( struct tagMSIVIEW *view, LPCWSTR column, INT type, BOOL temporary, BOOL hold );
/* * sort - orders the table by columns diff --git a/dlls/msi/table.c b/dlls/msi/table.c index c617110604..5a1466592f 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -2040,38 +2040,99 @@ static UINT TABLE_release(struct tagMSIVIEW *view) return ref; }
-static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number, - LPCWSTR column, UINT type, BOOL hold) +static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR column, + INT type, BOOL temporary, BOOL hold) { + UINT i, r, table_id, col_id, size, offset; MSITABLEVIEW *tv = (MSITABLEVIEW*)view; - MSITABLE *msitable; - MSIRECORD *rec; - UINT r; + MSICOLUMNINFO *colinfo;
- rec = MSI_CreateRecord(4); - if (!rec) - return ERROR_OUTOFMEMORY; + if (temporary && !hold && !tv->table->ref_count) + return ERROR_SUCCESS;
- MSI_RecordSetStringW(rec, 1, table); - MSI_RecordSetInteger(rec, 2, number); - MSI_RecordSetStringW(rec, 3, column); - MSI_RecordSetInteger(rec, 4, type); + if (!temporary && tv->table->col_count && + tv->table->colinfo[tv->table->col_count-1].temporary) + return ERROR_BAD_QUERY_SYNTAX; + + for (i = 0; i < tv->table->col_count; i++) + { + if (!wcscmp(tv->table->colinfo[i].colname, column)) + return ERROR_BAD_QUERY_SYNTAX; + }
- r = TABLE_insert_row(&tv->view, rec, -1, FALSE); + colinfo = msi_realloc(tv->table->colinfo, sizeof(*tv->table->colinfo) * (tv->table->col_count + 1)); + if (!colinfo) + return ERROR_OUTOFMEMORY; + tv->table->colinfo = colinfo; + + r = msi_string2id( tv->db->strings, tv->name, -1, &table_id ); if (r != ERROR_SUCCESS) - goto done; + return r; + col_id = msi_add_string( tv->db->strings, column, -1, !temporary );
- msi_update_table_columns(tv->db, table); + colinfo[tv->table->col_count].tablename = msi_string_lookup( tv->db->strings, table_id, NULL ); + colinfo[tv->table->col_count].number = tv->table->col_count + 1; + colinfo[tv->table->col_count].colname = msi_string_lookup( tv->db->strings, col_id, NULL ); + colinfo[tv->table->col_count].type = type; + colinfo[tv->table->col_count].offset = 0; + colinfo[tv->table->col_count].hash_table = NULL; + colinfo[tv->table->col_count].temporary = temporary; + tv->table->col_count++;
- if (!hold) - goto done; + table_calc_column_offsets( tv->db, tv->table->colinfo, tv->table->col_count);
- msitable = find_cached_table(tv->db, table); - InterlockedIncrement(&msitable->ref_count); + size = msi_table_get_row_size( tv->db, tv->table->colinfo, tv->table->col_count, LONG_STR_BYTES ); + offset = tv->table->colinfo[tv->table->col_count - 1].offset; + for (i = 0; i < tv->table->row_count; i++) + { + BYTE *data = msi_realloc( tv->table->data[i], size ); + if (!data) + { + tv->table->col_count--; + return ERROR_OUTOFMEMORY; + }
-done: - msiobj_release(&rec->hdr); - return r; + tv->table->data[i] = data; + memset(data + offset, 0, size - offset); + } + + if (!temporary) + { + MSIVIEW *columns; + MSIRECORD *rec; + + rec = MSI_CreateRecord(4); + if (!rec) + { + tv->table->col_count--; + return ERROR_OUTOFMEMORY; + } + + MSI_RecordSetStringW(rec, 1, tv->name); + MSI_RecordSetInteger(rec, 2, tv->table->col_count); + MSI_RecordSetStringW(rec, 3, column); + MSI_RecordSetInteger(rec, 4, type); + + r = TABLE_CreateView(tv->db, szColumns, &columns); + if (r != ERROR_SUCCESS) + { + tv->table->col_count--; + msiobj_release(&rec->hdr); + return r; + } + + r = TABLE_insert_row(columns, rec, -1, FALSE); + columns->ops->delete(columns); + msiobj_release(&rec->hdr); + if (r != ERROR_SUCCESS) + { + tv->table->col_count--; + return r; + } + } + if (hold) + TABLE_add_ref(view); + return ERROR_SUCCESS; }
static UINT TABLE_drop(struct tagMSIVIEW *view) diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 22466548b1..3e1c551d38 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -3950,7 +3950,7 @@ static void test_temporary_table(void) static void test_alter(void) { MSICONDITION cond; - MSIHANDLE hdb = 0; + MSIHANDLE hdb = 0, rec; const char *query; UINT r;
@@ -4020,6 +4020,10 @@ static void test_alter(void) r = run_query(hdb, 0, query); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+ query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'C'"; + r = do_query(hdb, query, &rec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + /* add column C again */ query = "ALTER TABLE `U` ADD `C` INTEGER"; r = run_query(hdb, 0, query); @@ -4037,6 +4041,10 @@ static void test_alter(void) r = run_query(hdb, 0, query); ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+ query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'D'"; + r = do_query(hdb, query, &rec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )"; r = run_query(hdb, 0, query); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);