msi: Allow more than one primary key in a table when importing a database.
This commit is contained in:
parent
463cec6af6
commit
a66584e1a2
|
@ -409,23 +409,44 @@ static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, D
|
|||
return columns;
|
||||
}
|
||||
|
||||
static LPWSTR msi_build_createsql_postlude(LPWSTR primary_key)
|
||||
static LPWSTR msi_build_createsql_postlude(LPWSTR *primary_keys, DWORD num_keys)
|
||||
{
|
||||
LPWSTR postlude;
|
||||
DWORD size;
|
||||
LPWSTR postlude, keys, ptr;
|
||||
DWORD size, key_size, i;
|
||||
|
||||
static const WCHAR postlude_fmt[] = {'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','%','s','`',')',' ','H','O','L','D',0};
|
||||
static const WCHAR key_fmt[] = {'`','%','s','`',',',' ',0};
|
||||
static const WCHAR postlude_fmt[] = {'P','R','I','M','A','R','Y',' ','K','E','Y',' ','%','s',')',' ','H','O','L','D',0};
|
||||
|
||||
size = sizeof(postlude_fmt) + lstrlenW(primary_key) - 2;
|
||||
postlude = msi_alloc(size * sizeof(WCHAR));
|
||||
if (!postlude)
|
||||
for (i = 0, size = 1; i < num_keys; i++)
|
||||
size += lstrlenW(key_fmt) + lstrlenW(primary_keys[i]) - 2;
|
||||
|
||||
keys = msi_alloc(size * sizeof(WCHAR));
|
||||
if (!keys)
|
||||
return NULL;
|
||||
|
||||
sprintfW(postlude, postlude_fmt, primary_key);
|
||||
for (i = 0, ptr = keys; i < num_keys; i++)
|
||||
{
|
||||
key_size = lstrlenW(key_fmt) + lstrlenW(primary_keys[i]) -2;
|
||||
sprintfW(ptr, key_fmt, primary_keys[i]);
|
||||
ptr += key_size;
|
||||
}
|
||||
|
||||
/* remove final ', ' */
|
||||
*(ptr - 2) = '\0';
|
||||
|
||||
size = lstrlenW(postlude_fmt) + size - 1;
|
||||
postlude = msi_alloc(size * sizeof(WCHAR));
|
||||
if (!postlude)
|
||||
goto done;
|
||||
|
||||
sprintfW(postlude, postlude_fmt, keys);
|
||||
|
||||
done:
|
||||
msi_free(keys);
|
||||
return postlude;
|
||||
}
|
||||
|
||||
static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, DWORD num_columns)
|
||||
static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, DWORD num_labels, DWORD num_columns)
|
||||
{
|
||||
UINT r;
|
||||
DWORD size;
|
||||
|
@ -435,7 +456,7 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types,
|
|||
|
||||
prelude = msi_build_createsql_prelude(labels[0]);
|
||||
columns_sql = msi_build_createsql_columns(columns, types, num_columns);
|
||||
postlude = msi_build_createsql_postlude(labels[1]);
|
||||
postlude = msi_build_createsql_postlude(labels + 1, num_labels - 1); /* skip over table name */
|
||||
|
||||
if (!prelude || !columns_sql || !postlude)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
@ -614,6 +635,7 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
{
|
||||
UINT r;
|
||||
DWORD len, i;
|
||||
DWORD num_labels;
|
||||
DWORD num_columns, num_records = 0;
|
||||
LPWSTR *columns, *types, *labels;
|
||||
LPWSTR path, ptr, data;
|
||||
|
@ -640,7 +662,7 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
ptr = data;
|
||||
msi_parse_line( &ptr, &columns, &num_columns );
|
||||
msi_parse_line( &ptr, &types, NULL );
|
||||
msi_parse_line( &ptr, &labels, NULL );
|
||||
msi_parse_line( &ptr, &labels, &num_labels );
|
||||
|
||||
records = msi_alloc(sizeof(LPWSTR *));
|
||||
if (!records)
|
||||
|
@ -657,7 +679,7 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
|||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
r = msi_add_table_to_db( db, columns, types, labels, num_columns );
|
||||
r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -1365,6 +1365,12 @@ static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortI
|
|||
"TestTable\tFirstPrimaryColumn\n"
|
||||
"stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
|
||||
|
||||
static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
|
||||
"s255\ts255\n"
|
||||
"TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
|
||||
"papaya\tleaf\n"
|
||||
"papaya\tflower\n";
|
||||
|
||||
static void write_file(const CHAR *filename, const char *data, int data_size)
|
||||
{
|
||||
DWORD size;
|
||||
|
@ -1402,6 +1408,9 @@ static void test_msiimport(void)
|
|||
r = add_table_to_db(hdb, test_data);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
r = add_table_to_db(hdb, two_primary);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "SELECT * FROM `TestTable`";
|
||||
r = MsiDatabaseOpenView(hdb, query, &view);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
@ -1464,6 +1473,51 @@ static void test_msiimport(void)
|
|||
ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
|
||||
|
||||
MsiCloseHandle(rec);
|
||||
MsiCloseHandle(view);
|
||||
|
||||
query = "SELECT * FROM `TwoPrimary`";
|
||||
r = MsiDatabaseOpenView(hdb, query, &view);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
|
||||
count = MsiRecordGetFieldCount(rec);
|
||||
ok(count == 2, "Expected 2, got %d\n", count);
|
||||
ok(check_record(rec, 1, "PrimaryOne"), "Expected PrimaryOne\n");
|
||||
ok(check_record(rec, 2, "PrimaryTwo"), "Expected PrimaryTwo\n");
|
||||
|
||||
MsiCloseHandle(rec);
|
||||
|
||||
r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
|
||||
count = MsiRecordGetFieldCount(rec);
|
||||
ok(count == 2, "Expected 2, got %d\n", count);
|
||||
ok(check_record(rec, 1, "s255"), "Expected s255\n");
|
||||
ok(check_record(rec, 2, "s255"), "Expected s255\n");
|
||||
|
||||
r = MsiViewExecute(view, 0);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
r = MsiViewFetch(view, &rec);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
|
||||
ok(check_record(rec, 2, "leaf"), "Expected 'leaf'\n");
|
||||
|
||||
MsiCloseHandle(rec);
|
||||
|
||||
r = MsiViewFetch(view, &rec);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
ok(check_record(rec, 1, "papaya"), "Expected 'papaya'\n");
|
||||
ok(check_record(rec, 2, "flower"), "Expected 'flower'\n");
|
||||
|
||||
MsiCloseHandle(rec);
|
||||
|
||||
r = MsiViewFetch(view, &rec);
|
||||
ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
|
||||
|
||||
r = MsiViewClose(view);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
MsiCloseHandle(view);
|
||||
MsiCloseHandle(hdb);
|
||||
DeleteFileA(msifile);
|
||||
|
|
Loading…
Reference in New Issue