msi [1/2]: Allow more than one primary key in a table when
importing a database
James Hawkins
truiken at gmail.com
Thu Oct 19 19:30:13 CDT 2006
Hi,
Changelog:
* 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(-)
--
James Hawkins
-------------- next part --------------
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);
}
--
1.4.2.1
More information about the wine-patches
mailing list