Commit 00cfd289 authored by James Hawkins's avatar James Hawkins Committed by Alexandre Julliard

msi: Use MsiViewModify instead of building a SQL query when adding rows to the table.

parent 4cc569cc
......@@ -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;
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;
UINT i;
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;
static const WCHAR mid[] = {' ',')',' ','V','A','L','U','E','S',' ','(',' ',0};
static const WCHAR end[] = {' ',')',0};
MSIRECORD *rec;
LPWSTR query;
LPWSTR prelude = msi_build_insertsql_prelude(labels[0]);
LPWSTR columns_sql = msi_build_insertsql_columns(columns, types, num_columns);
static const WCHAR select[] = {
'S','E','L','E','C','T',' ','*',' ',
'F','R','O','M',' ','`','%','s','`',0
};
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)
size = lstrlenW(select) + lstrlenW(labels[0]) - 1;
query = msi_alloc(size * sizeof(WCHAR));
if (!query)
return ERROR_OUTOFMEMORY;
lstrcpyW(insert_sql, prelude);
lstrcatW(insert_sql, columns_sql);
lstrcatW(insert_sql, mid);
lstrcatW(insert_sql, data);
lstrcatW(insert_sql, end);
sprintfW(query, select, labels[0]);
msi_free(data);
r = MSI_DatabaseOpenViewW(db, query, &view);
msi_free(query);
if (r != ERROR_SUCCESS)
return r;
r = MSI_DatabaseOpenViewW( db, insert_sql, &view );
msi_free(insert_sql);
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++)
{
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;
}
done:
msi_free(prelude);
msi_free(columns_sql);
msiobj_release(&rec->hdr);
}
done:
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment