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>
This commit is contained in:
parent
cb9cb83cda
commit
15b47513a1
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
105
dlls/msi/table.c
105
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)
|
||||
if (temporary && !hold && !tv->table->ref_count)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
colinfo = msi_realloc(tv->table->colinfo, sizeof(*tv->table->colinfo) * (tv->table->col_count + 1));
|
||||
if (!colinfo)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
tv->table->colinfo = colinfo;
|
||||
|
||||
MSI_RecordSetStringW(rec, 1, table);
|
||||
MSI_RecordSetInteger(rec, 2, number);
|
||||
MSI_RecordSetStringW(rec, 3, column);
|
||||
MSI_RecordSetInteger(rec, 4, type);
|
||||
|
||||
r = TABLE_insert_row(&tv->view, rec, -1, FALSE);
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue