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;
|
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;
|
LPWSTR postlude, keys, ptr;
|
||||||
DWORD size;
|
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;
|
for (i = 0, size = 1; i < num_keys; i++)
|
||||||
postlude = msi_alloc(size * sizeof(WCHAR));
|
size += lstrlenW(key_fmt) + lstrlenW(primary_keys[i]) - 2;
|
||||||
if (!postlude)
|
|
||||||
|
keys = msi_alloc(size * sizeof(WCHAR));
|
||||||
|
if (!keys)
|
||||||
return NULL;
|
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;
|
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;
|
UINT r;
|
||||||
DWORD size;
|
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]);
|
prelude = msi_build_createsql_prelude(labels[0]);
|
||||||
columns_sql = msi_build_createsql_columns(columns, types, num_columns);
|
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)
|
if (!prelude || !columns_sql || !postlude)
|
||||||
return ERROR_OUTOFMEMORY;
|
return ERROR_OUTOFMEMORY;
|
||||||
|
@ -614,6 +635,7 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
{
|
{
|
||||||
UINT r;
|
UINT r;
|
||||||
DWORD len, i;
|
DWORD len, i;
|
||||||
|
DWORD num_labels;
|
||||||
DWORD num_columns, num_records = 0;
|
DWORD num_columns, num_records = 0;
|
||||||
LPWSTR *columns, *types, *labels;
|
LPWSTR *columns, *types, *labels;
|
||||||
LPWSTR path, ptr, data;
|
LPWSTR path, ptr, data;
|
||||||
|
@ -640,7 +662,7 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
ptr = data;
|
ptr = data;
|
||||||
msi_parse_line( &ptr, &columns, &num_columns );
|
msi_parse_line( &ptr, &columns, &num_columns );
|
||||||
msi_parse_line( &ptr, &types, NULL );
|
msi_parse_line( &ptr, &types, NULL );
|
||||||
msi_parse_line( &ptr, &labels, NULL );
|
msi_parse_line( &ptr, &labels, &num_labels );
|
||||||
|
|
||||||
records = msi_alloc(sizeof(LPWSTR *));
|
records = msi_alloc(sizeof(LPWSTR *));
|
||||||
if (!records)
|
if (!records)
|
||||||
|
@ -657,7 +679,7 @@ UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
|
||||||
return ERROR_OUTOFMEMORY;
|
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)
|
if (r != ERROR_SUCCESS)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
|
|
@ -1365,6 +1365,12 @@ static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortI
|
||||||
"TestTable\tFirstPrimaryColumn\n"
|
"TestTable\tFirstPrimaryColumn\n"
|
||||||
"stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\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)
|
static void write_file(const CHAR *filename, const char *data, int data_size)
|
||||||
{
|
{
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
@ -1402,6 +1408,9 @@ static void test_msiimport(void)
|
||||||
r = add_table_to_db(hdb, test_data);
|
r = add_table_to_db(hdb, test_data);
|
||||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
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`";
|
query = "SELECT * FROM `TestTable`";
|
||||||
r = MsiDatabaseOpenView(hdb, query, &view);
|
r = MsiDatabaseOpenView(hdb, query, &view);
|
||||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
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);
|
ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
|
||||||
|
|
||||||
MsiCloseHandle(rec);
|
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(view);
|
||||||
MsiCloseHandle(hdb);
|
MsiCloseHandle(hdb);
|
||||||
DeleteFileA(msifile);
|
DeleteFileA(msifile);
|
||||||
|
|
Loading…
Reference in New Issue