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