forked from Mirrors/wine-wine
msi: Use MsiViewModify instead of building a SQL query when adding rows to the table.
parent
4cc569cce6
commit
00cfd2899b
|
@ -509,156 +509,88 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LPWSTR msi_build_insertsql_prelude(LPWSTR table)
|
static UINT construct_record(DWORD num_columns, LPWSTR *types,
|
||||||
|
LPWSTR *data, MSIRECORD **rec)
|
||||||
{
|
{
|
||||||
LPWSTR prelude;
|
UINT i;
|
||||||
DWORD size;
|
|
||||||
|
|
||||||
static const WCHAR insert_fmt[] = {'I','N','S','E','R','T',' ','I','N','T','O',' ','`','%','s','`',' ','(',' ',0};
|
*rec = MSI_CreateRecord(num_columns);
|
||||||
|
if (!*rec)
|
||||||
size = sizeof(insert_fmt) + lstrlenW(table) - 2;
|
return ERROR_OUTOFMEMORY;
|
||||||
prelude = msi_alloc(size * sizeof(WCHAR));
|
|
||||||
if (!prelude)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sprintfW(prelude, insert_fmt, table);
|
|
||||||
return prelude;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LPWSTR msi_build_insertsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
|
|
||||||
{
|
|
||||||
LPWSTR columns, p;
|
|
||||||
DWORD sql_size = 1, i;
|
|
||||||
WCHAR expanded[128];
|
|
||||||
|
|
||||||
static const WCHAR column_fmt[] = {'`','%','s','`',',',' ',0};
|
|
||||||
|
|
||||||
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
|
|
||||||
if (!columns)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < num_columns; i++)
|
|
||||||
{
|
|
||||||
sprintfW(expanded, column_fmt, columns_data[i]);
|
|
||||||
sql_size += lstrlenW(expanded);
|
|
||||||
|
|
||||||
if (i == num_columns - 1)
|
|
||||||
{
|
|
||||||
sql_size -= 2;
|
|
||||||
expanded[lstrlenW(expanded) - 2] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
p = msi_realloc(columns, sql_size * sizeof(WCHAR));
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
msi_free(columns);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
columns = p;
|
|
||||||
|
|
||||||
lstrcatW(columns, expanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
return columns;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LPWSTR msi_build_insertsql_data(LPWSTR **records, LPWSTR *types, DWORD num_columns, DWORD irec)
|
|
||||||
{
|
|
||||||
LPWSTR columns, temp_columns;
|
|
||||||
DWORD sql_size = 1, i;
|
|
||||||
WCHAR expanded[128];
|
|
||||||
|
|
||||||
static const WCHAR str_fmt[] = {'\'','%','s','\'',',',' ',0};
|
|
||||||
static const WCHAR int_fmt[] = {'%','s',',',' ',0};
|
|
||||||
static const WCHAR empty[] = {'\'','\'',',',' ',0};
|
|
||||||
|
|
||||||
columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
|
|
||||||
if (!columns)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < num_columns; i++)
|
for (i = 0; i < num_columns; i++)
|
||||||
{
|
{
|
||||||
switch (types[i][0])
|
switch (types[i][0])
|
||||||
{
|
{
|
||||||
case 'L': case 'l': case 'S': case 's':
|
case 'L': case 'l': case 'S': case 's':
|
||||||
sprintfW(expanded, str_fmt, records[irec][i]);
|
MSI_RecordSetStringW(*rec, i + 1, data[i]);
|
||||||
break;
|
break;
|
||||||
case 'I': case 'i':
|
case 'I': case 'i':
|
||||||
if (*records[0][i])
|
if (*data[i])
|
||||||
sprintfW(expanded, int_fmt, records[irec][i]);
|
MSI_RecordSetInteger(*rec, i + 1, atoiW(data[i]));
|
||||||
else
|
|
||||||
lstrcpyW(expanded, empty);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
HeapFree( GetProcessHeap(), 0, columns );
|
ERR("Unhandled column type: %c\n", types[i][0]);
|
||||||
return NULL;
|
msiobj_release(&(*rec)->hdr);
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == num_columns - 1)
|
|
||||||
expanded[lstrlenW(expanded) - 2] = '\0';
|
|
||||||
|
|
||||||
sql_size += lstrlenW(expanded);
|
|
||||||
temp_columns = msi_realloc(columns, sql_size * sizeof(WCHAR));
|
|
||||||
if (!temp_columns)
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, columns);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
columns = temp_columns;
|
|
||||||
|
|
||||||
lstrcatW(columns, expanded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return columns;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
||||||
LPWSTR *labels, LPWSTR **records,
|
LPWSTR *labels, LPWSTR **records,
|
||||||
int num_columns, int num_records)
|
int num_columns, int num_records)
|
||||||
{
|
{
|
||||||
|
UINT r;
|
||||||
|
DWORD i, size;
|
||||||
MSIQUERY *view;
|
MSIQUERY *view;
|
||||||
LPWSTR insert_sql;
|
MSIRECORD *rec;
|
||||||
DWORD size, i;
|
LPWSTR query;
|
||||||
UINT r = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
static const WCHAR mid[] = {' ',')',' ','V','A','L','U','E','S',' ','(',' ',0};
|
static const WCHAR select[] = {
|
||||||
static const WCHAR end[] = {' ',')',0};
|
'S','E','L','E','C','T',' ','*',' ',
|
||||||
|
'F','R','O','M',' ','`','%','s','`',0
|
||||||
|
};
|
||||||
|
|
||||||
|
size = lstrlenW(select) + lstrlenW(labels[0]) - 1;
|
||||||
|
query = msi_alloc(size * sizeof(WCHAR));
|
||||||
|
if (!query)
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
sprintfW(query, select, labels[0]);
|
||||||
|
|
||||||
|
r = MSI_DatabaseOpenViewW(db, query, &view);
|
||||||
|
msi_free(query);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS)
|
||||||
|
{
|
||||||
|
r = MSI_ViewModify(view, MSIMODIFY_DELETE, rec);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
LPWSTR prelude = msi_build_insertsql_prelude(labels[0]);
|
|
||||||
LPWSTR columns_sql = msi_build_insertsql_columns(columns, types, num_columns);
|
|
||||||
|
|
||||||
for (i = 0; i < num_records; i++)
|
for (i = 0; i < num_records; i++)
|
||||||
{
|
{
|
||||||
LPWSTR data = msi_build_insertsql_data(records, types, num_columns, i);
|
r = construct_record(num_columns, types, records[i], &rec);
|
||||||
|
|
||||||
size = lstrlenW(prelude) + lstrlenW(columns_sql) + sizeof(mid) + lstrlenW(data) + sizeof(end) - 1;
|
|
||||||
insert_sql = msi_alloc(size * sizeof(WCHAR));
|
|
||||||
if (!insert_sql)
|
|
||||||
return ERROR_OUTOFMEMORY;
|
|
||||||
|
|
||||||
lstrcpyW(insert_sql, prelude);
|
|
||||||
lstrcatW(insert_sql, columns_sql);
|
|
||||||
lstrcatW(insert_sql, mid);
|
|
||||||
lstrcatW(insert_sql, data);
|
|
||||||
lstrcatW(insert_sql, end);
|
|
||||||
|
|
||||||
msi_free(data);
|
|
||||||
|
|
||||||
r = MSI_DatabaseOpenViewW( db, insert_sql, &view );
|
|
||||||
msi_free(insert_sql);
|
|
||||||
|
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
r = MSI_ViewExecute(view, NULL);
|
r = MSI_ViewModify(view, MSIMODIFY_INSERT, rec);
|
||||||
MSI_ViewClose(view);
|
if (r != ERROR_SUCCESS)
|
||||||
msiobj_release(&view->hdr);
|
{
|
||||||
|
msiobj_release(&rec->hdr);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
msiobj_release(&rec->hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
msi_free(prelude);
|
msiobj_release(&view->hdr);
|
||||||
msi_free(columns_sql);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -718,9 +650,15 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
records = temp_records;
|
records = temp_records;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
|
if (!TABLE_Exists(db, labels[0]))
|
||||||
if (r != ERROR_SUCCESS)
|
{
|
||||||
goto done;
|
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
r = ERROR_FUNCTION_FAILED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
|
r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records );
|
||||||
|
|
||||||
|
|
|
@ -1649,11 +1649,8 @@ static void test_msiimport(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
r = add_table_to_db(hdb, endlines2);
|
r = add_table_to_db(hdb, endlines2);
|
||||||
todo_wine
|
ok(r == ERROR_FUNCTION_FAILED,
|
||||||
{
|
"Expected ERROR_FUNCTION_FAILED, got %d\n", r);
|
||||||
ok(r == ERROR_FUNCTION_FAILED,
|
|
||||||
"Expected ERROR_FUNCTION_FAILED, got %d\n", r);
|
|
||||||
}
|
|
||||||
|
|
||||||
query = "SELECT * FROM `TestTable`";
|
query = "SELECT * FROM `TestTable`";
|
||||||
r = MsiDatabaseOpenView(hdb, query, &view);
|
r = MsiDatabaseOpenView(hdb, query, &view);
|
||||||
|
@ -5255,10 +5252,7 @@ static void test_quotes(void)
|
||||||
write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
|
write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
|
||||||
|
|
||||||
r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
|
r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
|
||||||
todo_wine
|
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||||
{
|
|
||||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteFileA("import.idt");
|
DeleteFileA("import.idt");
|
||||||
|
|
||||||
|
@ -5275,19 +5269,13 @@ static void test_quotes(void)
|
||||||
size = MAX_PATH;
|
size = MAX_PATH;
|
||||||
r = MsiRecordGetString(hrec, 1, buf, &size);
|
r = MsiRecordGetString(hrec, 1, buf, &size);
|
||||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||||
todo_wine
|
ok(!lstrcmp(buf, "This is a new 'string' ok"),
|
||||||
{
|
"Expected \"This is a new 'string' ok\", got %s\n", buf);
|
||||||
ok(!lstrcmp(buf, "This is a new 'string' ok"),
|
|
||||||
"Expected \"This is a new 'string' ok\", got %s\n", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
MsiCloseHandle(hrec);
|
MsiCloseHandle(hrec);
|
||||||
|
|
||||||
r = MsiViewFetch(hview, &hrec);
|
r = MsiViewFetch(hview, &hrec);
|
||||||
todo_wine
|
ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
|
||||||
{
|
|
||||||
ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
|
|
||||||
}
|
|
||||||
|
|
||||||
MsiCloseHandle(hview);
|
MsiCloseHandle(hview);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue