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

Alexandre Julliard julliard at wine.codeweavers.com
Fri Oct 20 04:46:07 CDT 2006


Module: wine
Branch: master
Commit: a66584e1a26b4bc12ec0ae1befa87fdd67aa0b84
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a66584e1a26b4bc12ec0ae1befa87fdd67aa0b84

Author: James Hawkins <truiken at 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);
 }




More information about the wine-cvs mailing list