Module: wine Branch: master Commit: a66584e1a26b4bc12ec0ae1befa87fdd67aa0b84 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a66584e1a26b4bc12ec0ae1bef...
Author: James Hawkins truiken@gmail.com Date: Thu Oct 19 17:30:13 2006 -0700
msi: Allow more than one primary key in a table when importing a database.
---
dlls/msi/database.c | 44 +++++++++++++++++++++++++++++++---------- dlls/msi/tests/db.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 11 deletions(-)
diff --git a/dlls/msi/database.c b/dlls/msi/database.c index 266b467..b793863 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -409,23 +409,44 @@ static LPWSTR msi_build_createsql_column 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 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}; + + 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; + + 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; + }
- static const WCHAR postlude_fmt[] = {'P','R','I','M','A','R','Y',' ','K','E','Y',' ','`','%','s','`',')',' ','H','O','L','D',0}; + /* remove final ', ' */ + *(ptr - 2) = '\0';
- size = sizeof(postlude_fmt) + lstrlenW(primary_key) - 2; + size = lstrlenW(postlude_fmt) + size - 1; postlude = msi_alloc(size * sizeof(WCHAR)); if (!postlude) - return NULL; + goto done; + + sprintfW(postlude, postlude_fmt, keys);
- sprintfW(postlude, postlude_fmt, primary_key); +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(MSIDATAB
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, { 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, 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, 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;
diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 5f5da33..9a39451 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -1365,6 +1365,12 @@ static const CHAR test_data[] = "FirstPr "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); @@ -1465,6 +1474,51 @@ static void test_msiimport(void)
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); }