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, ...@@ -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};
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) *rec = MSI_CreateRecord(num_columns);
{ if (!*rec)
LPWSTR columns, p; return ERROR_OUTOFMEMORY;
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
};
LPWSTR prelude = msi_build_insertsql_prelude(labels[0]); size = lstrlenW(select) + lstrlenW(labels[0]) - 1;
LPWSTR columns_sql = msi_build_insertsql_columns(columns, types, num_columns); query = msi_alloc(size * sizeof(WCHAR));
if (!query)
for (i = 0; i < num_records; i++) return ERROR_OUTOFMEMORY;
{
LPWSTR data = msi_build_insertsql_data(records, types, num_columns, i);
size = lstrlenW(prelude) + lstrlenW(columns_sql) + sizeof(mid) + lstrlenW(data) + sizeof(end) - 1; sprintfW(query, select, labels[0]);
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, query, &view);
msi_free(query);
if (r != ERROR_SUCCESS)
return r;
r = MSI_DatabaseOpenViewW( db, insert_sql, &view ); while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS)
msi_free(insert_sql); {
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) 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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
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