msi: Allow more than one primary key in a table when importing a database.

This commit is contained in:
James Hawkins 2006-10-19 17:30:13 -07:00 committed by Alexandre Julliard
parent 463cec6af6
commit a66584e1a2
2 changed files with 88 additions and 12 deletions

View File

@ -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;

View File

@ -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);